Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions packages/kos-codec/src/chains/ada/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,13 @@ pub fn encode_for_broadcast(
let tx_body = TransactionBody::decode_fragment(metadata.as_slice())
.map_err(|e| ChainError::InvalidData(e.to_string()))?;

let public_key =
let mut public_key =
hex::decode(account.public_key.clone()).map_err(|_| ChainError::InvalidPublicKey)?;

if public_key.len() > 32 {
public_key = public_key[..32].to_vec();
}

let v_key_witness = VKeyWitness {
vkey: public_key.into(),
signature: transaction.signature.clone().into(),
Expand Down Expand Up @@ -112,12 +116,12 @@ mod test {
let mnemonic =
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
.to_string();
let ada = ADA::new(false);
let ada = ADA::new();

let seed = ada.mnemonic_to_seed(mnemonic, "".to_string()).unwrap();
let path = ada.get_path(0, false);

let pvk = ada.derive(seed, path).unwrap();
let pvk: Vec<u8> = ada.derive(seed, path).unwrap();

let transaction = Transaction {
raw_data: simple_base64_decode("gnkBNmE0MDA4MTgyNTgyMGQxOWMwNTQwOTlkODllMjJiNWJlNTU3ZTI0YzAyMzE0ZGU3YWM5M2Q3ZDFlNjAyZDNiYmZjODY4NDY3OWQzYzEwMDAxODI4MjU4MzkwMWFmMDZmYTVmMWIyOGM5MGJkYzFjODdiYmI2NzMwYmMwZGE5ODY0MjBjNGJkMDBmZDRlNWRkMWYyYWViMGM3NDdjNjhhNDAzYzJlY2UwNWE3OTg4MWVmZTk0YWVjMmVjOTIyZmU0YmQxYzA4ZTNkNjMxYTAwMGY0MjQwODI1ODFkNjFkNTVmNDUzZjkzOTU0NzU1OTEzOTkxZDIxMTk1MmU0YmRkZmNjZDllZWE3ZTQyNDk2N2E3NzlmNDFhMDEwZjcxYTEwMjFhMDAwMzM2ZGYwMzFhMDhmNzFlOTWham9wZXJhdGlvbnOBpnRvcGVyYXRpb25faWRlbnRpZmllcqFlaW5kZXgAZHR5cGVlaW5wdXRmc3RhdHVzYGdhY2NvdW50oWdhZGRyZXNzeDphZGRyMXY4MjQ3M2ZsancyNXc0djM4eGdheXl2NDllOWFtbHhkbm00OHVzamZ2N25obmFxOXYyNTl1ZmFtb3VudKJldmFsdWVoMTkwMDAwMDBoY3VycmVuY3miZnN5bWJvbGNBREFoZGVjaW1hbHMGa2NvaW5fY2hhbmdlom9jb2luX2lkZW50aWZpZXKhamlkZW50aWZpZXJ4QmQxOWMwNTQwOTlkODllMjJiNWJlNTU3ZTI0YzAyMzE0ZGU3YWM5M2Q3ZDFlNjAyZDNiYmZjODY4NDY3OWQzYzE6MGtjb2luX2FjdGlvbmpjb2luX3NwZW50").unwrap(),
Expand Down
3 changes: 2 additions & 1 deletion packages/kos-hardware/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ pub extern "C" fn rs_sign_message(
node: &mut CNodeStruct,
message: &mut CBuffer,
sig: &mut CBuffer,
legacy: bool,
) -> bool {
let pvk = node.read_pvk();
let c = match chains::get_chain_by_params(chain.to_chain_type()) {
Expand All @@ -191,7 +192,7 @@ pub extern "C" fn rs_sign_message(

let message = message.read();

let signature = match c.sign_message(pvk, message) {
let signature = match c.sign_message(pvk, message, legacy) {
Ok(s) => s,
Err(e) => {
unsafe {
Expand Down
7 changes: 4 additions & 3 deletions packages/kos-mobile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,11 @@ fn sign_transaction(
}

#[uniffi::export]
fn sign_message(account: KOSAccount, hex: String) -> Result<Vec<u8>, KOSError> {
fn sign_message(account: KOSAccount, hex: String, legacy: bool) -> Result<Vec<u8>, KOSError> {
let chain = get_chain_by(account.chain_id)?;
let message = hex::decode(hex)?;
let signature = chain.sign_message(hex::decode(account.private_key).unwrap(), message)?;
let signature =
chain.sign_message(hex::decode(account.private_key).unwrap(), message, legacy)?;
Ok(signature)
}

Expand Down Expand Up @@ -635,7 +636,7 @@ mod tests {
false
).unwrap();

let signature = sign_message(account, message).unwrap();
let signature = sign_message(account, message, true).unwrap();
assert_eq!(signature.len(), 64, "The signature length doesn't match");
}

Expand Down
8 changes: 4 additions & 4 deletions packages/kos-web/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,15 +325,15 @@ impl Wallet {
impl Wallet {
#[wasm_bindgen(js_name = "signMessage")]
/// sign message with keypair
pub fn sign_message(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
pub fn sign_message(&self, message: &[u8], legacy: bool) -> Result<Vec<u8>, Error> {
match self.private_key {
Some(ref pk_hex) => {
let pk_bytes = hex::decode(pk_hex)?;
let chain = get_chain_by_base_id(self.chain)
.ok_or_else(|| Error::WalletManager("Invalid chain".to_string()))?;

chain
.sign_message(pk_bytes, message.to_vec())
.sign_message(pk_bytes, message.to_vec(), legacy)
.map_err(|e| Error::WalletManager(format!("sign message: {}", e)))
}
None => Err(Error::WalletManager("no keypair".to_string())),
Expand Down Expand Up @@ -490,7 +490,7 @@ mod tests {

let wallet = Wallet::from_private_key(chain_id, TEST_PRIVATE_KEY.to_string()).unwrap();

let signature = wallet.sign_message(message).unwrap();
let signature = wallet.sign_message(message, true).unwrap();
assert!(!signature.is_empty());
}

Expand Down Expand Up @@ -556,7 +556,7 @@ mod tests {

// Signing operations should fail
let message = b"test message";
assert!(wallet.sign_message(message).is_err());
assert!(wallet.sign_message(message, true).is_err());
}

#[test]
Expand Down
40 changes: 20 additions & 20 deletions packages/kos/src/chains/ada/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ use alloc::vec::Vec;

pub const BASE_ID: u32 = 20;

pub struct ADA {
extended_key: bool,
}
pub struct ADA {}

impl ADA {
pub fn new(extended_key: bool) -> Self {
ADA { extended_key }
pub fn new() -> Self {
ADA {}
}
}

impl Default for ADA {
fn default() -> Self {
Self::new()
}
}

Expand Down Expand Up @@ -77,10 +81,6 @@ impl Chain for ADA {
cc.copy_from_slice(&private_key[64..]);
let vk = self.get_pbk(pvk.to_vec())?;

if !self.extended_key {
return Ok(vk);
}

let mut xvk = Vec::new();
xvk.append(&mut vk.to_vec());
xvk.append(&mut cc.to_vec());
Expand Down Expand Up @@ -137,7 +137,12 @@ impl Chain for ADA {
Ok(tx)
}

fn sign_message(&self, private_key: Vec<u8>, message: Vec<u8>) -> Result<Vec<u8>, ChainError> {
fn sign_message(
&self,
private_key: Vec<u8>,
message: Vec<u8>,
_legacy: bool,
) -> Result<Vec<u8>, ChainError> {
let sig = self.sign_raw(private_key.clone(), message)?;

let pbk = self.get_pbk(private_key)?;
Expand Down Expand Up @@ -177,9 +182,7 @@ mod test {
let mnemonic =
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
.to_string();
let ada = super::ADA {
extended_key: false,
};
let ada = super::ADA {};

let seed = ada.mnemonic_to_seed(mnemonic, "".to_string()).unwrap();
let path = ada.get_path(0, false);
Expand All @@ -199,19 +202,16 @@ mod test {
let mnemonic =
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
.to_string();
let ada = super::ADA {
extended_key: false,
};
let ada = super::ADA {};

let seed = ada.mnemonic_to_seed(mnemonic, "".to_string()).unwrap();
let path = ada.get_path(0, false);

let pvk = ada.derive(seed, path).unwrap();
let message = "test message".as_bytes().to_vec();

let message = "hello world".as_bytes().to_vec();

let sig = ada.sign_message(pvk, message).unwrap();
let sig = ada.sign_message(pvk, message, false).unwrap();

assert_eq!(hex::encode(sig), "c9343740a90a19a4ffac066357297c41401dd90710266445803a010a53cc041c3cb5cbbdb6a7ec2e41f8bc9c640876458d3ae31652abe2de2086ea34676923007ea09a34aebb13c9841c71397b1cabfec5ddf950405293dee496cac2f437480a".to_string())
assert_eq!(hex::encode(sig), "3a958c70d7e86c7beae52eba5e0738ee4ede4f27bb2ce79b8082373cb9ac16ea3988a1500b6cc47cde5769d7f7fee886c998ab5e5ea4646024682fadb1adb3057ea09a34aebb13c9841c71397b1cabfec5ddf950405293dee496cac2f437480a88848e8af62a27a57e982215741c9eac17e6e45cbfd6ea65a0e0dcc03bb777b2".to_string())
}
}
13 changes: 9 additions & 4 deletions packages/kos/src/chains/apt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ impl Chain for APT {
Ok(tx)
}

fn sign_message(&self, private_key: Vec<u8>, message: Vec<u8>) -> Result<Vec<u8>, ChainError> {
fn sign_message(
&self,
private_key: Vec<u8>,
message: Vec<u8>,
_legacy: bool,
) -> Result<Vec<u8>, ChainError> {
let sig = self.sign_raw(private_key.clone(), message)?;

let pbk = self.get_pbk(private_key)?;
Expand Down Expand Up @@ -138,10 +143,10 @@ mod test {

let pvk = ada.derive(seed, path).unwrap();

let message = "hello world".as_bytes().to_vec();
let message = "test message".as_bytes().to_vec();

let sig = ada.sign_message(pvk, message).unwrap();
let sig = ada.sign_message(pvk, message, true).unwrap();

assert_eq!(hex::encode(sig), "7c2879913c2939e6e62d45cd3c30fbed11dd37cc147a38e8dbd12b6dee537342f7404632535522156331a44992753ef35982456aed78f7345d85f8c63718cf01a686f0309ab80312979606cfccc10ea2740147ae6888351488d11c46f08fbf60".to_string())
assert_eq!(hex::encode(sig), "8f64c4f4717b60b4ab14633636aab83fa0d7b41455b9c3133224816e2cae32ee9b3221f67ab8698126cd165a841d9e8b2ce0044e5a33deac57125c5233a05e0ea686f0309ab80312979606cfccc10ea2740147ae6888351488d11c46f08fbf60".to_string())
}
}
27 changes: 16 additions & 11 deletions packages/kos/src/chains/atom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,19 +120,27 @@ impl Chain for ATOM {
mut tx: Transaction,
) -> Result<Transaction, ChainError> {
let prepared_tx = ATOM::prepare_transaction(tx.raw_data.clone()).to_vec();
tx.signature = self.sign_raw(private_key, prepared_tx)?;
let signature = self.sign_raw(private_key, prepared_tx)?;

tx.signature = signature[..64].to_vec();

Ok(tx)
}

fn sign_message(&self, private_key: Vec<u8>, message: Vec<u8>) -> Result<Vec<u8>, ChainError> {
fn sign_message(
&self,
private_key: Vec<u8>,
message: Vec<u8>,
_legacy: bool,
) -> Result<Vec<u8>, ChainError> {
let prepared_msg: [u8; 32] = ATOM::prepare_message(message);
let signature = self.sign_raw(private_key, prepared_msg.to_vec())?;

let mut sig_vec = Vec::new();
// <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R><padded bytes for signature S>
sig_vec.extend_from_slice(&[27]);
sig_vec.extend_from_slice(signature.as_ref());
let mut sig_vec = Vec::new();
let rec_byte = signature[64];
sig_vec.extend_from_slice(&[27 + rec_byte]);
sig_vec.extend_from_slice(&signature[..64]);

Ok(sig_vec.to_vec())
}
Expand All @@ -143,10 +151,7 @@ impl Chain for ATOM {

let sig: [u8; 65] = secp256k1::Secp256K1::sign(&payload_bytes, &pvk_bytes)?;

let mut sig_vec = [0; 64];
sig_vec.copy_from_slice(&sig[..64]);

Ok(sig_vec.to_vec())
Ok(sig.to_vec())
}

fn get_tx_info(&self, _raw_tx: Vec<u8>) -> Result<TxInfo, ChainError> {
Expand Down Expand Up @@ -190,11 +195,11 @@ mod test {

let message_bytes = "test message".as_bytes().to_vec();

let signature = atom.sign_message(pvk, message_bytes).unwrap();
let signature = atom.sign_message(pvk, message_bytes, false).unwrap();

assert_eq!(
hex::encode(signature),
"1bd48bf6446d3cd53869ff9ab787548fd04648fe4a1bc72cab594f9cd9a525d88e6a1b0c6252247f11dd8361629635df0e98f2ceedfee06bb6a116d18f5c5da150"
"1cd48bf6446d3cd53869ff9ab787548fd04648fe4a1bc72cab594f9cd9a525d88e6a1b0c6252247f11dd8361629635df0e98f2ceedfee06bb6a116d18f5c5da150"
);
}

Expand Down
13 changes: 9 additions & 4 deletions packages/kos/src/chains/bch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,14 @@ impl Chain for BCH {
Ok(tx)
}

fn sign_message(&self, private_key: Vec<u8>, message: Vec<u8>) -> Result<Vec<u8>, ChainError> {
fn sign_message(
&self,
private_key: Vec<u8>,
message: Vec<u8>,
legacy: bool,
) -> Result<Vec<u8>, ChainError> {
let btc = BTC::new();
btc.sign_message(private_key, message)
btc.sign_message(private_key, message, legacy)
}

fn sign_raw(&self, private_key: Vec<u8>, payload: Vec<u8>) -> Result<Vec<u8>, ChainError> {
Expand Down Expand Up @@ -257,9 +262,9 @@ mod test {
let pvk = bch.derive(seed, path).unwrap();

let result = bch
.sign_message(pvk, "test message".as_bytes().to_vec())
.sign_message(pvk, "test message".as_bytes().to_vec(), true)
.unwrap();

assert_eq!(hex::encode(result), "303a181697a1b5d5b4f5adac6f42a44a660c893589c4b52ef71385ccc301a4d27b6c9068e30b84e5f3d08ca314cd45563c3114b4f42216945de1304f85e0617b00");
assert_eq!(hex::encode(result), "1ba94d065712b8c35814d67a2923caae4626d902c852c1be95bb038e689b647ae97b0fdd5ea813da9c261c90d406f6bd2a42854a355fbdcdbb074223461dee2032");
}
}
27 changes: 25 additions & 2 deletions packages/kos/src/chains/btc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ impl BTC {

sha256_digest(&msg[..])
}

pub fn prepare_message_legacy(message: Vec<u8>) -> [u8; 32] {
sha256_digest(&sha256_digest(&message))
}
}

impl Chain for BTC {
Expand Down Expand Up @@ -279,7 +283,26 @@ impl Chain for BTC {

Ok(tx)
}
fn sign_message(&self, private_key: Vec<u8>, message: Vec<u8>) -> Result<Vec<u8>, ChainError> {

fn sign_message(
&self,
private_key: Vec<u8>,
message: Vec<u8>,
legacy: bool,
) -> Result<Vec<u8>, ChainError> {
if legacy {
let prepared_message = BTC::prepare_message_legacy(message);
let signature = self.sign_raw(private_key, prepared_message.to_vec())?;

// <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R><padded bytes for signature S>
let mut sig_vec = Vec::new();
let rec_byte = signature[64];
sig_vec.extend_from_slice(&[27 + rec_byte]);
sig_vec.extend_from_slice(&signature[..64]);

return Ok(sig_vec);
}

let prepared_message = BTC::prepare_message(message);
let signature = self.sign_raw(private_key, prepared_message.to_vec())?;
Ok(signature)
Expand Down Expand Up @@ -416,7 +439,7 @@ mod test {
let seed = btc.mnemonic_to_seed(mnemonic, "".to_string()).unwrap();
let pvk = btc.derive(seed, path).unwrap();
let message = "Hello, World!".as_bytes().to_vec();
let signature = btc.sign_message(pvk, message).unwrap();
let signature = btc.sign_message(pvk, message, false).unwrap();
assert_eq!(hex::encode(signature.clone()), "9d561a0ba6ea562e61606e7f3b6a92c889246eec2c05e86e3f465f43469ae9436d7e46accdcfaea848460e42c83c52238b6956c4bfb192e67023b6024e95bdcf01");
assert_eq!(signature.len(), 65);
}
Expand Down
29 changes: 27 additions & 2 deletions packages/kos/src/chains/eth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,12 @@ impl Chain for ETH {
Ok(tx)
}

fn sign_message(&self, private_key: Vec<u8>, message: Vec<u8>) -> Result<Vec<u8>, ChainError> {
fn sign_message(
&self,
private_key: Vec<u8>,
message: Vec<u8>,
_legacy: bool,
) -> Result<Vec<u8>, ChainError> {
#[cfg(not(feature = "ksafe"))]
{
if let Ok(data) = std::str::from_utf8(&message) {
Expand Down Expand Up @@ -332,7 +337,27 @@ mod test {
.unwrap();
let message = data.as_bytes();

let signature = eth.sign_message(pvk, message.to_vec()).unwrap();
let signature = eth.sign_message(pvk, message.to_vec(), false).unwrap();
assert_eq!(signature.len(), 65);
}

#[test]
fn test_sign_message() {
let mnemonic =
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about".to_string();

let eth = super::ETH::new();
let seed = eth.mnemonic_to_seed(mnemonic, "".to_string()).unwrap();
let path = eth.get_path(0, false);
let pvk = eth.derive(seed, path).unwrap();

let message_bytes = "test message".as_bytes().to_vec();

let signature = eth.sign_message(pvk, message_bytes, true).unwrap();

assert_eq!(
hex::encode(signature),
"960e9bb7f2cdfa4325661e11218c28ab2804b8966d6529b86073886a95142c881a965b3608a573ff035a780039afcbca13be25ee57ac175dd5ca7b82b79948c61c"
);
}
}
Loading