diff --git a/.github/workflows/noir.yml b/.github/workflows/noir.yml index 253c1b6..8fb538a 100644 --- a/.github/workflows/noir.yml +++ b/.github/workflows/noir.yml @@ -19,7 +19,7 @@ jobs: - name: Install Nargo uses: noir-lang/noirup@v0.1.3 with: - toolchain: v0.19.0 + toolchain: v0.36.0 - name: Run nargo test run: | diff --git a/Nargo.toml b/Nargo.toml index 69ed715..b7341ec 100644 --- a/Nargo.toml +++ b/Nargo.toml @@ -1,9 +1,9 @@ [package] authors = ["@colinnielsen"] -compiler_version = ">=0.19.0" +compiler_version = ">=0.30.0" name = "ecrecover" notes = "AMDG" type = "lib" [dependencies] -array_helpers = { tag = "v0.19.0", git = "https://github.com/colinnielsen/noir-array-helpers" } +array_helpers = { tag = "v0.30.0", git = "https://github.com/colinnielsen/noir-array-helpers" } diff --git a/README.md b/README.md index ff9d7ba..f343714 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,14 @@ **This software is unaudited and should not be used in production. Use at your own risk.** +## WARNING! + +**DO NOT use versions of this library < `v0.30.0`** + +This library contained a critical vulnerability found by @olehmisar. The circuits were critically underconstrained, allowing anyone to impersonate public Ethereum addresses. + +See more details [here](https://gist.github.com/olehmisar/4cfe6128eaac2bfbe1fa8eb46f0116d6). +
**ECRecover Noir** includes tools to help prove secp256k1 signatures (Ethereum's curve) in Noir Circuits. @@ -21,7 +29,7 @@ In your `Nargo.toml` file, add the following dependency: ```toml [dependencies] -ecrecover = { tag = "v0.19.0", git = "https://github.com/colinnielsen/ecrecover-noir" } +ecrecover = { tag = "v0.30.0", git = "https://github.com/colinnielsen/ecrecover-noir" } ``` ## Simple Usage diff --git a/src/lib.nr b/src/lib.nr index daa9997..462a7c7 100644 --- a/src/lib.nr +++ b/src/lib.nr @@ -1,8 +1,6 @@ -use dep::std; - mod secp256k1; -fn ecrecover( +pub fn ecrecover( pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64], // clip v value diff --git a/src/secp256k1.nr b/src/secp256k1.nr index 06f0c57..4f2f724 100644 --- a/src/secp256k1.nr +++ b/src/secp256k1.nr @@ -1,13 +1,11 @@ use dep::std; - use dep::array_helpers; -struct PubKey { +pub struct PubKey { pub_x: [u8; 32], pub_y: [u8; 32], } -unconstrained fn split_uncompressed_pub_key( pub_key: [u8; 65] ) -> ([u8; 32], [u8; 32]) { @@ -23,15 +21,15 @@ fn split_uncompressed_pub_key( } impl PubKey { - fn from_xy(pub_x: [u8; 32], pub_y: [u8; 32]) -> PubKey { + pub fn from_xy(pub_x: [u8; 32], pub_y: [u8; 32]) -> PubKey { PubKey { pub_x, pub_y, } } - fn from_unified(pub_key: [u8; 64]) -> PubKey { - let (key_x, key_y) = array_helpers::split_u8_64_unconstrained(pub_key); + pub fn from_unified(pub_key: [u8; 64]) -> PubKey { + let (key_x, key_y) = array_helpers::split_u8_64(pub_key); PubKey { pub_x: key_x, @@ -39,7 +37,7 @@ impl PubKey { } } - fn from_uncompressed(pub_key: [u8; 65]) -> PubKey { + pub fn from_uncompressed(pub_key: [u8; 65]) -> PubKey { assert(pub_key[0] == 0x04); let (key_x, key_y) = split_uncompressed_pub_key(pub_key); @@ -49,12 +47,12 @@ impl PubKey { } } - fn verify_sig(self, signature: [u8; 64], hashed_message: [u8; 32]) -> bool { + pub fn verify_sig(self, signature: [u8; 64], hashed_message: [u8; 32]) -> bool { std::ecdsa_secp256k1::verify_signature(self.pub_x, self.pub_y, signature, hashed_message) } - fn to_eth_address(self) -> Field { - let pub_key = array_helpers::u8_32_to_u8_64_unconstrained(self.pub_x, self.pub_y); + pub fn to_eth_address(self) -> Field { + let pub_key = array_helpers::u8_32_to_u8_64(self.pub_x, self.pub_y); let hashed_pub_key = std::hash::keccak256(pub_key, 64); let mut addr: Field = 0;