From 67a2674d275b88b1a11d776949f65ccc6fc58c4c Mon Sep 17 00:00:00 2001 From: rvcas Date: Mon, 6 Feb 2023 14:43:21 -0500 Subject: [PATCH] feat: allow verify functions to build for wasm --- Cargo.lock | 163 +++++++++++++++++++++++++++++ crates/uplc/Cargo.toml | 5 +- crates/uplc/src/machine/error.rs | 4 + crates/uplc/src/machine/runtime.rs | 94 +++++++++++------ 4 files changed, 233 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43a56806..b294ff5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -253,6 +253,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base58" version = "0.2.0" @@ -439,6 +445,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "const-oid" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" + [[package]] name = "const-random" version = "0.1.15" @@ -550,6 +562,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -576,6 +600,16 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "diff" version = "0.1.13" @@ -613,12 +647,44 @@ dependencies = [ "winapi", ] +[[package]] +name = "ecdsa" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12844141594ad74185a926d030f3b605f6a903b4e3fec351f3ea338ac5b7637e" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "either" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.31" @@ -637,6 +703,16 @@ dependencies = [ "instant", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -837,6 +913,17 @@ dependencies = [ "regex", ] +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "h2" version = "0.3.15" @@ -1085,6 +1172,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92a55e0ff3b72c262bcf041d9e97f1b84492b68f1c1a384de2323d3dc9403397" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1618,6 +1719,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.26" @@ -1895,6 +2006,17 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -1950,6 +2072,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secp256k1" version = "0.26.0" @@ -2077,6 +2213,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "slab" version = "0.4.7" @@ -2108,6 +2254,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -2500,6 +2656,7 @@ dependencies = [ "hex", "indexmap", "itertools", + "k256", "pallas-addresses", "pallas-codec", "pallas-crypto", @@ -2837,6 +2994,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" + [[package]] name = "zip" version = "0.6.4" diff --git a/crates/uplc/Cargo.toml b/crates/uplc/Cargo.toml index bed15716..21322ad0 100644 --- a/crates/uplc/Cargo.toml +++ b/crates/uplc/Cargo.toml @@ -31,11 +31,14 @@ strum = "0.24.1" strum_macros = "0.24.3" itertools = "0.10.5" indexmap = "1.9.2" -secp256k1 = "0.26.0" +secp256k1 = { version = "0.26.0", optional = true } +k256 = { version = "0.12.0", optional = true } [dev-dependencies] hex = "0.4.3" proptest = "1.0.0" [features] +default = ["dep:secp256k1"] +wasm = ["dep:k256"] unstable = [] diff --git a/crates/uplc/src/machine/error.rs b/crates/uplc/src/machine/error.rs index 8fa22c23..2407c915 100644 --- a/crates/uplc/src/machine/error.rs +++ b/crates/uplc/src/machine/error.rs @@ -48,6 +48,10 @@ pub enum Error { DeserialisationError(String, Value), #[error("Integer overflow")] OverflowError, + #[cfg(not(feature = "wasm"))] #[error(transparent)] Secp256k1(#[from] secp256k1::Error), + #[cfg(feature = "wasm")] + #[error(transparent)] + Secp256k1(#[from] k256::ecdsa::Error), } diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index ba3b8213..74abc548 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -682,21 +682,7 @@ impl DefaultFunction { Constant::ByteString(public_key), Constant::ByteString(message), Constant::ByteString(signature), - ) => { - use secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1}; - - let secp = Secp256k1::verification_only(); - - let public_key = PublicKey::from_slice(public_key.as_slice())?; - - let signature = Signature::from_compact(signature.as_slice())?; - - let message = Message::from_slice(message.as_slice())?; - - let valid = secp.verify_ecdsa(&message, &signature, &public_key); - - Ok(Value::Con(Constant::Bool(valid.is_ok()).into()).into()) - } + ) => verify_ecdsa(public_key, message, signature), _ => unreachable!(), } } @@ -711,23 +697,7 @@ impl DefaultFunction { Constant::ByteString(public_key), Constant::ByteString(message), Constant::ByteString(signature), - ) => { - use secp256k1::{ - schnorr::Signature, Message, Secp256k1, XOnlyPublicKey, - }; - - let secp = Secp256k1::verification_only(); - - let public_key = XOnlyPublicKey::from_slice(public_key.as_slice())?; - - let signature = Signature::from_slice(signature.as_slice())?; - - let message = Message::from_slice(message.as_slice())?; - - let valid = secp.verify_schnorr(&signature, &message, &public_key); - - Ok(Value::Con(Constant::Bool(valid.is_ok()).into()).into()) - } + ) => verify_schnorr(public_key, message, signature), _ => unreachable!(), } } @@ -1175,3 +1145,63 @@ pub fn convert_constr_to_tag(constr: u64) -> u64 { todo!() } } + +#[cfg(not(feature = "wasm"))] +fn verify_ecdsa(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result, Error> { + use secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1}; + + let secp = Secp256k1::verification_only(); + + let public_key = PublicKey::from_slice(public_key)?; + + let signature = Signature::from_compact(signature)?; + + let message = Message::from_slice(message)?; + + let valid = secp.verify_ecdsa(&message, &signature, &public_key); + + Ok(Value::Con(Constant::Bool(valid.is_ok()).into()).into()) +} + +#[cfg(not(feature = "wasm"))] +fn verify_schnorr(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result, Error> { + use secp256k1::{schnorr::Signature, Message, Secp256k1, XOnlyPublicKey}; + + let secp = Secp256k1::verification_only(); + + let public_key = XOnlyPublicKey::from_slice(public_key)?; + + let signature = Signature::from_slice(signature)?; + + let message = Message::from_slice(message)?; + + let valid = secp.verify_schnorr(&signature, &message, &public_key); + + Ok(Value::Con(Constant::Bool(valid.is_ok()).into()).into()) +} + +#[cfg(feature = "wasm")] +fn verify_ecdsa(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result, Error> { + use k256::ecdsa::{self, signature::Verifier}; + + let verifying_key = ecdsa::VerifyingKey::try_from(public_key)?; + + let signature = ecdsa::Signature::try_from(signature)?; + + let valid = verifying_key.verify(message, &signature); + + Ok(Value::Con(Constant::Bool(valid.is_ok()).into()).into()) +} + +#[cfg(feature = "wasm")] +fn verify_schnorr(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result, Error> { + use k256::schnorr::{self, signature::Verifier}; + + let verifying_key = schnorr::VerifyingKey::from_bytes(public_key)?; + + let signature = schnorr::Signature::try_from(signature)?; + + let valid = verifying_key.verify(message, &signature); + + Ok(Value::Con(Constant::Bool(valid.is_ok()).into()).into()) +}