Skip to content

Commit

Permalink
Python message signing (#117)
Browse files Browse the repository at this point in the history
* Python wallet message signing

* message signing example

* .pyi
  • Loading branch information
smartgoo authored Oct 27, 2024
1 parent 480526d commit ef8e872
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 4 deletions.
12 changes: 12 additions & 0 deletions python/examples/message-signing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from kaspa import PrivateKey, PublicKey, sign_message, verify_message

if __name__ == "__main__":
message = "Hello Kaspa!"
private_key = PrivateKey("b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfef")
public_key = PublicKey("dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659")

signature = sign_message(message, private_key)
print(f'Signature: {signature}')

valid_sig = verify_message(message, signature, public_key)
print('Valid sig' if valid_sig else 'Invalid sig')
5 changes: 5 additions & 0 deletions python/kaspa.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,11 @@ class Opcodes(Enum):
OpInvalidOpCode = 0xff


def sign_message(message: str, private_key: PrivateKey) -> str: ...

def verify_message(message: str, signature: str, public_key: PublicKey) -> bool: ...


class Generator:

def __init__(
Expand Down
10 changes: 6 additions & 4 deletions python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,18 @@ cfg_if::cfg_if! {
m.add_class::<kaspa_txscript::python::ScriptBuilder>()?;
m.add_class::<kaspa_txscript::wasm::opcodes::Opcodes>()?;

m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::message::py_sign_message, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::message::py_verify_message, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::signer::py_sign_transaction, m)?)?;
m.add_class::<kaspa_wallet_core::python::tx::generator::generator::Generator>()?;
m.add_class::<kaspa_wallet_core::python::tx::generator::pending::PendingTransaction>()?;
m.add_class::<kaspa_wallet_core::python::tx::generator::summary::GeneratorSummary>()?;
m.add_class::<kaspa_wallet_core::tx::payment::PaymentOutput>()?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::tx::utils::create_transaction_py, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::tx::utils::create_transactions_py, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::utils::kaspa_to_sompi, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::utils::sompi_to_kaspa, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::utils::sompi_to_kaspa_string_with_suffix, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::tx::utils::create_transaction_py, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::tx::utils::create_transactions_py, m)?)?;
m.add_function(wrap_pyfunction!(kaspa_wallet_core::python::signer::py_sign_transaction, m)?)?;
m.add_class::<kaspa_wallet_core::tx::payment::PaymentOutput>()?;

m.add_class::<kaspa_wallet_keys::derivation_path::DerivationPath>()?;
m.add_class::<kaspa_wallet_keys::keypair::Keypair>()?;
Expand Down
25 changes: 25 additions & 0 deletions wallet/core/src/python/message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::imports::*;
use crate::message::*;
use kaspa_wallet_keys::privatekey::PrivateKey;
use kaspa_wallet_keys::publickey::PublicKey;

#[pyfunction]
#[pyo3(name = "sign_message")]
pub fn py_sign_message(message: String, private_key: PrivateKey) -> PyResult<String> {
let mut privkey_bytes = [0u8; 32];
privkey_bytes.copy_from_slice(&private_key.secret_bytes());
let pm = PersonalMessage(&message);
let sig_vec = sign_message(&pm, &privkey_bytes).map_err(|err| PyException::new_err(format!("{}", err)))?;
privkey_bytes.zeroize();
Ok(faster_hex::hex_string(sig_vec.as_slice()).into())
}

#[pyfunction]
#[pyo3(name = "verify_message")]
pub fn py_verify_message(message: String, signature: String, public_key: PublicKey) -> PyResult<bool> {
let pm = PersonalMessage(&message);
let mut signature_bytes = [0u8; 64];
faster_hex::hex_decode(signature.as_bytes(), &mut signature_bytes).map_err(|err| PyException::new_err(format!("{}", err)))?;

Ok(verify_message(&pm, &signature_bytes.to_vec(), &public_key.xonly_public_key).is_ok())
}
1 change: 1 addition & 0 deletions wallet/core/src/python/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod message;
pub mod signer;
pub mod tx;
pub mod utils;

0 comments on commit ef8e872

Please sign in to comment.