Skip to content

Commit

Permalink
Merge pull request IntersectMBO#34 from input-output-hk/sign-verify-tx
Browse files Browse the repository at this point in the history
Sign verify tx
  • Loading branch information
NicolasDP authored Apr 11, 2018
2 parents 67b3388 + 6a8d8b3 commit 448da6d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 4 deletions.
51 changes: 50 additions & 1 deletion js/Tx.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,59 @@ export const addOutput = (module, tx, txout) => {
return out;
};


/**
* Sign the given tx, this function returns the signature, not the TxInWitness
*
* @param module - the WASM module that is used for crypto operations
* @param tx - the transaction to add the given TxOut
* @param xprv - the extended private key to sign the transaction with
* @returns {*} - the signature
*/
export const sign = (module, tx, xprv) => {
const buftx = newArray(module, tx);
const bufxprv = newArray(module, xprv);
const bufsig = newArray0(module, 64);

module.wallet_tx_sign(bufxprv, buftx, tx.length, bufsig);
let result = copyArray(module, bufsig, 64);

module.dealloc(bufsig);
module.dealloc(bufxprv);
module.dealloc(buftx);

return result
};

/**
* Verify the given signature of a tx
*
* @param module - the WASM module that is used for crypto operations
* @param tx - the transaction to add the given TxOut
* @param xpub - the extended private key to sign the transaction with
* @param signature - the signature to verify
* @returns {*} - true or false
*/
export const verify = (module, tx, xpub, signature) => {
const buftx = newArray(module, tx);
const bufxpub = newArray(module, xpub);
const bufsig = newArray(module, signature);

let result = module.wallet_tx_verify(bufxpub, buftx, tx.length, bufsig);

module.dealloc(bufsig);
module.dealloc(bufxpub);
module.dealloc(buftx);

return result === 0
};

export default {
newTxOut: apply(newTxOut, RustModule),
newTxIn: apply(newTxIn, RustModule),
create: apply(create, RustModule),
addInput: apply(addInput, RustModule),
addOutput: apply(addOutput, RustModule)
addOutput: apply(addOutput, RustModule),
sign: apply(sign, RustModule),
verify: apply(verify, RustModule),
};
15 changes: 14 additions & 1 deletion js/tests/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ const TEST_VECTORS = [
txout: new Uint8Array([0x82, 0x82, 0xd8, 0x18, 0x58, 0x29, 0x83, 0x58, 0x1c, 0x83, 0xee, 0xa1, 0xb5, 0xec, 0x8e, 0x80, 0x26, 0x65, 0x81, 0x46, 0x4a, 0xee, 0x0e, 0x2d, 0x6a, 0x45, 0xfd, 0x6d, 0x7b, 0x9e, 0x1a, 0x98, 0x3a, 0x50, 0x48, 0xcd, 0x15, 0xa1, 0x01, 0x46, 0x45, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x1a, 0x9d, 0x45, 0x88, 0x4a, 0x18, 0x2a]),

tx: new Uint8Array([0x83, 0x9f, 0x82, 0x00, 0xd8, 0x18, 0x58, 0x26, 0x82, 0x58, 0x20, 0xaa, 0xd7, 0x8a, 0x13, 0xb5, 0x0a, 0x01, 0x4a, 0x24, 0x63, 0x3c, 0x7d, 0x44, 0xfd, 0x8f, 0x8d, 0x18, 0xf6, 0x7b, 0xbb, 0x3f, 0xa9, 0xcb, 0xce, 0xdf, 0x83, 0x4a, 0xc8, 0x99, 0x75, 0x9d, 0xcd, 0x19, 0x02, 0x9a, 0xff, 0x9f, 0x82, 0x82, 0xd8, 0x18, 0x58, 0x29, 0x83, 0x58, 0x1c, 0x83, 0xee, 0xa1, 0xb5, 0xec, 0x8e, 0x80, 0x26, 0x65, 0x81, 0x46, 0x4a, 0xee, 0x0e, 0x2d, 0x6a, 0x45, 0xfd, 0x6d, 0x7b, 0x9e, 0x1a, 0x98, 0x3a, 0x50, 0x48, 0xcd, 0x15, 0xa1, 0x01, 0x46, 0x45, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x1a, 0x9d, 0x45, 0x88, 0x4a, 0x18, 0x2a, 0xff, 0xa0]),

xprv: new Uint8Array([0x30,0x16,0x04,0x04,0x5d,0xe9,0x13,0x8b,0x8b,0x23,0xb6,0x73,0x04,0x95,0xf7,0xe3,0x4b,0x51,0x51,0xd2,0x9b,0xa3,0x45,0x6b,0xc9,0xb3,0x32,0xf6,0xf0,0x84,0xa5,0x51,0xd6,0x46,0xbc,0x30,0xcf,0x12,0x6f,0xa8,0xed,0x77,0x6c,0x05,0xa8,0x93,0x2a,0x5a,0xb3,0x5c,0x8b,0xac,0x41,0xeb,0x01,0xbb,0x9a,0x16,0xcf,0xe2,0x29,0xb9,0x4b,0x40,0x5d,0x36,0x61,0xde,0xb9,0x06,0x4f,0x2d,0x0e,0x03,0xfe,0x85,0xd6,0x80,0x70,0xb2,0xfe,0x33,0xb4,0x91,0x60,0x59,0x65,0x8e,0x28,0xac,0x7f,0x7f,0x91,0xca,0x4b,0x12]),
xpub: new Uint8Array([0x1c,0x0c,0x3a,0xe1,0x82,0x5e,0x90,0xb6,0xdd,0xda,0x3f,0x40,0xa1,0x22,0xc0,0x07,0xe1,0x00,0x8e,0x83,0xb2,0xe1,0x02,0xc1,0x42,0xba,0xef,0xb7,0x21,0xd7,0x2c,0x1a,0x5d,0x36,0x61,0xde,0xb9,0x06,0x4f,0x2d,0x0e,0x03,0xfe,0x85,0xd6,0x80,0x70,0xb2,0xfe,0x33,0xb4,0x91,0x60,0x59,0x65,0x8e,0x28,0xac,0x7f,0x7f,0x91,0xca,0x4b,0x12]),
signature: new Uint8Array([0x9D,0x6D,0x91,0x1E,0x58,0x8D,0xD4,0xFB,0x77,0xCB,0x80,0xC2,0xC6,0xAD,0xBC,0x2B,0x94,0x2B,0xCE,0xA5,0xD8,0xA0,0x39,0x22,0x0D,0xDC,0xD2,0x35,0xCB,0x75,0x86,0x2C,0x0C,0x95,0xF6,0x2B,0xA1,0x11,0xE5,0x7D,0x7C,0x1A,0x22,0x1C,0xF5,0x13,0x3E,0x44,0x12,0x88,0x32,0xC1,0x49,0x35,0x4D,0x1E,0x57,0xB6,0x80,0xFE,0x57,0x2D,0x76,0x0C]),
}
];

let mkTest = (i) => {
const { txid, index, txin, address, amount, txout, tx } = TEST_VECTORS[i];
const { txid, index, txin, address, amount, txout, tx, xprv, xpub, signature} = TEST_VECTORS[i];

describe('Test ' + i, function() {
it('create a TxIn', function() {
Expand All @@ -39,6 +43,15 @@ let mkTest = (i) => {
txtmp = CardanoCrypto.Tx.addOutput(txtmp, txout);
expect(txtmp).deep.equal(tx);
});

it('sign a Tx', function() {
expect(CardanoCrypto.Tx.sign(tx, xprv))
.deep.equal(signature);
});
it('verify a TX signature', function() {
expect(CardanoCrypto.Tx.verify(tx, xpub, signature))
.equal(true);
});
});
}

Expand Down
33 changes: 31 additions & 2 deletions wallet-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ unsafe fn write_xpub(xpub: &hdwallet::XPub, xpub_ptr: *mut c_uchar) {
out[0..hdwallet::XPUB_SIZE].clone_from_slice(xpub.as_ref());
}

unsafe fn read_signature(sig_ptr: *const c_uchar) -> hdwallet::Signature<Vec<u8>> {
unsafe fn read_signature<T>(sig_ptr: *const c_uchar) -> hdwallet::Signature<T> {
let signature_slice = std::slice::from_raw_parts(sig_ptr, hdwallet::SIGNATURE_SIZE);
hdwallet::Signature::from_slice(signature_slice).unwrap()
}
Expand Down Expand Up @@ -165,7 +165,7 @@ pub extern "C" fn wallet_sign(xprv_ptr: *const c_uchar, msg_ptr: *const c_uchar,
pub extern "C" fn wallet_verify(xpub_ptr: *const c_uchar, msg_ptr: *const c_uchar, msg_sz: usize, sig_ptr: *const c_uchar) -> bool {
let xpub = unsafe { read_xpub(xpub_ptr) };
let msg = unsafe { read_data(msg_ptr, msg_sz) };
let signature = unsafe { read_signature(sig_ptr) };
let signature = unsafe { read_signature::<Vec<u8>>(sig_ptr) };
xpub.verify(&msg, &signature)
}

Expand Down Expand Up @@ -335,3 +335,32 @@ pub extern "C" fn wallet_tx_add_txout(tx_ptr: *const c_uchar, tx_sz: usize, txou
unsafe { write_data(&out_buf, out) }
out_buf.len() as u32
}

#[no_mangle]
pub extern "C" fn wallet_tx_sign(xprv_ptr: *const c_uchar, tx_ptr: *const c_uchar, tx_sz: usize, out: *mut c_uchar) {
let xprv = unsafe { read_xprv(xprv_ptr) };
let tx_bytes = unsafe { read_data(tx_ptr, tx_sz) };

let tx = decode_from_cbor(&tx_bytes).unwrap();

let txinwitness = tx::TxInWitness::new(&xprv, &tx);

let signature = match txinwitness {
tx::TxInWitness::PkWitness(_, sig) => sig,
_ => unimplemented!() // this should never happen as we are signing for the tx anyway
};
unsafe { write_signature(&signature, out) }
}

#[no_mangle]
pub extern "C" fn wallet_tx_verify(xpub_ptr: *const c_uchar, tx_ptr: *const c_uchar, tx_sz: usize, sig_ptr: *const c_uchar) -> i32 {
let xpub = unsafe { read_xpub(xpub_ptr) };
let signature = unsafe { read_signature(sig_ptr) };

let tx_bytes = unsafe { read_data(tx_ptr, tx_sz) };
let tx = decode_from_cbor(&tx_bytes).unwrap();

let txinwitness = tx::TxInWitness::PkWitness(xpub, signature);

if txinwitness.verify_tx(&tx) { 0 } else { -1 }
}

0 comments on commit 448da6d

Please sign in to comment.