From 4a3e45564f5dd5aa14256a3e0334a0085fa9bde0 Mon Sep 17 00:00:00 2001 From: codeesura Date: Sun, 28 Jul 2024 01:43:20 +0300 Subject: [PATCH 1/6] refactor and format test function --- signature_gen/src/main.rs | 63 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/signature_gen/src/main.rs b/signature_gen/src/main.rs index 4143a55..be6145c 100644 --- a/signature_gen/src/main.rs +++ b/signature_gen/src/main.rs @@ -1,14 +1,10 @@ use num_bigint::BigUint; use rsa::pkcs1v15::Signature; -use rsa::pkcs1v15::VerifyingKey; use rsa::{RsaPrivateKey, RsaPublicKey}; +use rsa::signature::{SignatureEncoding, Signer}; use rsa::traits::PublicKeyParts; use sha2::Sha256; -use rsa::signature::{ - SignatureEncoding, Signer, Verifier, -}; -use rand; use noir_bignum_paramgen::{bn_limbs, bn_runtime_instance}; @@ -27,41 +23,44 @@ fn generate_2048_bit_signature_parameters() { let sig_uint: BigUint = BigUint::from_bytes_be(sig_bytes); - let sig_str = bn_limbs(sig_uint.clone(), 2048); - println!("let signature: BigNum<18, Params2048> = BigNum::from_array({});", sig_str.as_str()); + println!( + "let signature: BigNum<18, Params2048> = BigNum::from_array({});", + sig_str.as_str() + ); let r = bn_runtime_instance(pub_key.n().clone(), 2048, String::from("BNInstance")); println!("{}", r.as_str()); } - fn main() { generate_2048_bit_signature_parameters(); } - - -fn test_signature_generation_impl() { - let mut rng = rand::thread_rng(); - let bits = 2048; - let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); - let pub_key: RsaPublicKey = priv_key.clone().into(); - let text: &str = "hello world"; - let signing_key = rsa::pkcs1v15::SigningKey::::new(priv_key); - let sig: Vec = signing_key.sign(text.as_bytes()).to_vec(); - let verifying_key = VerifyingKey::::new(pub_key); - - let result = verifying_key.verify( - text.as_bytes(), - &Signature::try_from(sig.as_slice()).unwrap(), - ); - result.expect("failed to verify"); - +#[cfg(test)] +mod tests { + use super::*; + use rand::thread_rng; + use rsa::pkcs1v15::Signature; + use rsa::signature::{Signer, Verifier}; + use rsa::{pkcs1v15::VerifyingKey, RsaPrivateKey, RsaPublicKey}; + use sha2::Sha256; + + #[test] + fn test_signature_generation() { + let mut rng = thread_rng(); + let bits = 2048; + let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); + let pub_key: RsaPublicKey = priv_key.clone().into(); + let text: &str = "hello world"; + let signing_key = rsa::pkcs1v15::SigningKey::::new(priv_key); + let sig: Vec = signing_key.sign(text.as_bytes()).to_vec(); + let verifying_key = VerifyingKey::::new(pub_key); + + let result = verifying_key.verify( + text.as_bytes(), + &Signature::try_from(sig.as_slice()).unwrap(), + ); + result.expect("failed to verify"); + } } - -#[test] -fn test_signature_generation() -{ - test_signature_generation_impl(); -} \ No newline at end of file From 43810d70f537813cb1b946402952b43461fa7154 Mon Sep 17 00:00:00 2001 From: codeesura <120671243+codeesura@users.noreply.github.com> Date: Sun, 28 Jul 2024 01:44:34 +0300 Subject: [PATCH 2/6] Delete signature_gen/.DS_Store --- signature_gen/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 signature_gen/.DS_Store diff --git a/signature_gen/.DS_Store b/signature_gen/.DS_Store deleted file mode 100644 index 6d6450171ab05407b5386718b108c3a4bfc1f1ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ8DBQ5S)!oFr;yrQdh_ggmF%g3nZ~k8iOHr`d9f}Ia+2v1e?c$G-=E%tVUYx zNN9?;ZvoiqYx@K&0W9c_IQuX*-*+F`T}2$t&)DqW4~IRcxF01?1e`m=5uey>kC*%t z-WdGA4yVhFiDML&0#ZN Date: Wed, 4 Sep 2024 10:41:39 +0100 Subject: [PATCH 3/6] feat: add support for public exponent 3 --- lib/Nargo.toml | 2 +- lib/src/rsa.nr | 71 +++++++++++++++++++++++++++------------ signature_gen/src/main.rs | 15 +++++++-- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/lib/Nargo.toml b/lib/Nargo.toml index 21db88b..988aedb 100644 --- a/lib/Nargo.toml +++ b/lib/Nargo.toml @@ -5,4 +5,4 @@ authors = [""] compiler_version = ">=0.32.0" [dependencies] -bignum = {tag = "v0.3.0", git = "https://github.com/noir-lang/noir-bignum"} +bignum = {tag = "v0.3.2", git = "https://github.com/noir-lang/noir-bignum"} diff --git a/lib/src/rsa.nr b/lib/src/rsa.nr index ca2f520..fd55bd6 100644 --- a/lib/src/rsa.nr +++ b/lib/src/rsa.nr @@ -53,30 +53,36 @@ impl RSA where BN: * when converting a BigNum into a byte array, the number of bytes is required and currently cannot be inferred. * Once numeric generics can be derived by applying operations to other numeric generics the need for this will go away. * - * @note We assume the public key exponent `e` is 65537 + * @note The exponent `e` can be either 65537 or 3 (i.e. the most common values in use for RSA) * Rough cost: 2,048 bit RSA: 26,888 gates per verification * 1,024 bit RSA: 11,983 gates per verification * A circuit that verifies 1 signature (and does nothing else) will cost ~32k due to initialization costs of lookup tables **/ - pub fn verify_sha256_pkcs1v15(_: Self, instance: BNInstance, msg_hash: [u8; 32], sig: BN) -> bool { + pub fn verify_sha256_pkcs1v15(_: Self, instance: BNInstance, msg_hash: [u8; 32], sig: BN, exponent: u32) -> bool { + assert((exponent == 3) | (exponent == 65537), "Exponent must be 65537 or 3"); // e = 65537 = 1 0000 0000 0000 0001 - let mut exponentiated = instance.mul(sig, sig); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, exponentiated); - exponentiated = instance.mul(exponentiated, sig); + let mut exponentiated = instance.mul(sig, sig); // sig^2 + + if exponent == 3 { + exponentiated = instance.mul(exponentiated, sig); // sig^2 * sig = sig^3 + } else if exponent == 65537 { + exponentiated = instance.mul(exponentiated, exponentiated); // sig^2 * sig^2 = sig^4 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^8 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^16 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^32 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^64 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^128 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^256 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^512 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^1024 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^2048 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^4096 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^8192 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^16384 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^32768 + exponentiated = instance.mul(exponentiated, exponentiated); // sig^65536 + exponentiated = instance.mul(exponentiated, sig); // sig^65537 + } let mut padded_sha256_hash_bytes: [u8; NumBytes] = exponentiated.to_le_bytes(); compare_signature_sha256(padded_sha256_hash_bytes, msg_hash) @@ -102,7 +108,7 @@ fn test_verify_sha256_pkcs1v15_1024() { ); let rsa: RSA1024 = RSA {}; - assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature)); + assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature, 65537)); } #[test] @@ -122,5 +128,28 @@ fn test_verify_sha256_pkcs1v15_2048() { ] ); let rsa: RSA2048 = RSA {}; - assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature)); + assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature, 65537)); +} + +#[test] +fn test_verify_sha256_pkcs1v15_2048_exponent_3() { + let sha256_hash: [u8; 32] = dep::std::hash::sha256("Hello World! This is Noir-RSA".as_bytes()); + + let BNInstance: BNInst2048 = BigNumInstance::new( + [ + 0xc6a1c5e80ce354c6b00ccf20cf3a1d, 0x178d135f925a03eceb25f79bab56ee, 0x13ab3d6d8a5c5586752b5a3bc74ec3, 0x3d13b47b152367e3e2fc014d03d19f, 0xe89a7278a2945b4a672011691db30f, 0x5b4c1b061378143629dbb29dea1e4, 0x26a48b6f4e8df1472fd4fc12b17c18, 0xc7c92ead0ce810520cf3a8267254c1, 0x806b8cdba93909e9d9a71ee1bcdac2, 0x703ef80f8eb703b84c201366dff1c7, 0x7361034bb2c4c081aad8b1bcca83de, 0xb23c7e1109e65e6d08fa72cc862008, 0x750bc927874455782cd2d6fd5a51f6, 0xf0b83665fbf8cb5cf31cee9f89848e, 0x20d447b08953c7ce3330197938a8ae, 0x11a08bb5a2241c6a2a69f930d8b28b, 0xef5bca8dd582570a44705cb123d09e, 0xb7 + ], + [ + 0xbc93ee57c1c8adc53f0a995a6221ca, 0x2a9b43587534b20dd85a5233329f10, 0xc587fd488f64eed02adc1f462f7448, 0xf1484d37676bb0e800996757382522, 0xc2126c48221aa61c9f52c6b918bab3, 0x8660c861dd52ed958beaf6c6c2cff0, 0x5edd9dc4f02a000f350948c70bdf94, 0x6f3b9603149272e9b232a379a017bb, 0x950fd85cffbdf4476b1cb66c1f63d6, 0xee459417b1a56b6f7ef3b89e385ac, 0x48daeef6d1a055f3746ab71058e137, 0x3cbc0ba96d541feee92dd27f9d0306, 0x6a2a42384cc388fa113ee80317e0a0, 0x43b4f89c508a42d309f295c0d9f3a5, 0x8d8c28b05f71b962b40ea906ff407f, 0x390a7989eb9cecc5827cb00e1ca693, 0x4cbf158eabf7e96ef7f2586d0ce613, 0x164 + ] + ); + + let signature: BN2048 = BigNum::from_array( + [ + 0x19772b9af8a031170a7844ce4f3d7c, 0x4808e817258f57805a7326f70bcd74, 0xca8f3f98e374d52100115bfa645a7d, 0x49547189edff3b683fee267e717b7f, 0x96f263b47e96925f3b5898a7389ceb, 0x4cc50a893da91d0e085fc6656b30bc, 0x67e84ff92d88c0ad2c17ad2701309e, 0x095326818578173289665fcd9ad788, 0x775c6e85b745065db9411b9d579763, 0xad0f20c8a5265dfca4080ca877a2b8, 0xbfd199372f1680b3bc583a08bd8ba9, 0x663476ca3e5ede3e5976887db2c4e5, 0x531192309d0d49fed47c0216c27f9e, 0x37d26d31c86b951ca1c17b517063b7, 0x3cdb362ed5dfd06568eb9a9bbb6a91, 0x14520b9c23f583314729a9d858bca9, 0x5e0505067ada1026721d45997bf2c4, 0x3e + ] + ); + + let rsa: RSA2048 = RSA {}; + assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature, 3)); } diff --git a/signature_gen/src/main.rs b/signature_gen/src/main.rs index a5a4d2e..afa0ff9 100644 --- a/signature_gen/src/main.rs +++ b/signature_gen/src/main.rs @@ -31,7 +31,7 @@ fn format_limbs_as_toml_value(limbs: &Vec) -> Vec { .collect() } -fn generate_2048_bit_signature_parameters(msg: &str, as_toml: bool) { +fn generate_2048_bit_signature_parameters(msg: &str, as_toml: bool, exponent: u32) { let mut hasher = Sha256::new(); hasher.update(msg.as_bytes()); let hashed_message = hasher.finalize(); @@ -45,7 +45,7 @@ fn generate_2048_bit_signature_parameters(msg: &str, as_toml: bool) { let mut rng: rand::prelude::ThreadRng = rand::thread_rng(); let bits: usize = 2048; let priv_key: RsaPrivateKey = - RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); + RsaPrivateKey::new_with_exp(&mut rng, bits, &BigUint::from(exponent)).expect("failed to generate a key"); let pub_key: RsaPublicKey = priv_key.clone().into(); let signing_key = rsa::pkcs1v15::SigningKey::::new(priv_key); @@ -108,12 +108,21 @@ fn main() { .long("toml") .help("Print output in TOML format"), ) + .arg( + Arg::with_name("exponent") + .short("e") + .long("exponent") + .takes_value(true) + .help("Exponent to use for the key") + .default_value("65537"), + ) .get_matches(); let msg = matches.value_of("msg").unwrap(); let as_toml = matches.is_present("toml"); + let e: u32 = matches.value_of("exponent").unwrap().parse().unwrap(); - generate_2048_bit_signature_parameters(msg, as_toml); + generate_2048_bit_signature_parameters(msg, as_toml, e); } fn test_signature_generation_impl() { From 9e2dbd327a00e0ab2413bdeb3fd71dce74631a7b Mon Sep 17 00:00:00 2001 From: Theo Madzou Date: Wed, 4 Sep 2024 13:49:51 +0100 Subject: [PATCH 4/6] feat(optimization): simplification of `verify_sha256_pkcs1v15` logic --- lib/src/rsa.nr | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/rsa.nr b/lib/src/rsa.nr index fd55bd6..d512c5c 100644 --- a/lib/src/rsa.nr +++ b/lib/src/rsa.nr @@ -60,12 +60,10 @@ impl RSA where BN: **/ pub fn verify_sha256_pkcs1v15(_: Self, instance: BNInstance, msg_hash: [u8; 32], sig: BN, exponent: u32) -> bool { assert((exponent == 3) | (exponent == 65537), "Exponent must be 65537 or 3"); - // e = 65537 = 1 0000 0000 0000 0001 let mut exponentiated = instance.mul(sig, sig); // sig^2 - if exponent == 3 { - exponentiated = instance.mul(exponentiated, sig); // sig^2 * sig = sig^3 - } else if exponent == 65537 { + if exponent == 65537 { + // e = 65537 = 1 0000 0000 0000 0001 exponentiated = instance.mul(exponentiated, exponentiated); // sig^2 * sig^2 = sig^4 exponentiated = instance.mul(exponentiated, exponentiated); // sig^8 exponentiated = instance.mul(exponentiated, exponentiated); // sig^16 @@ -81,8 +79,10 @@ impl RSA where BN: exponentiated = instance.mul(exponentiated, exponentiated); // sig^16384 exponentiated = instance.mul(exponentiated, exponentiated); // sig^32768 exponentiated = instance.mul(exponentiated, exponentiated); // sig^65536 - exponentiated = instance.mul(exponentiated, sig); // sig^65537 } + // otherwise, e = 3 = 11 + + exponentiated = instance.mul(exponentiated, sig); // either sig^2 * sig = sig^3 or sig^65536 * sig = sig^65537 let mut padded_sha256_hash_bytes: [u8; NumBytes] = exponentiated.to_le_bytes(); compare_signature_sha256(padded_sha256_hash_bytes, msg_hash) From 5b77859a9e59ded92602653228caae6d6d2ec397 Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 13 Sep 2024 17:22:10 +0100 Subject: [PATCH 5/6] . --- .github/workflows/test.yml | 4 ++-- lib/Nargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1fc842d..94ba9b6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - toolchain: [nightly, 0.32.0] + toolchain: [nightly, 0.34.0] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -39,7 +39,7 @@ jobs: - name: Install Nargo uses: noir-lang/noirup@v0.1.3 with: - toolchain: 0.32.0 + toolchain: 0.34.0 - name: Run formatter working-directory: ./lib diff --git a/lib/Nargo.toml b/lib/Nargo.toml index 988aedb..cf9de63 100644 --- a/lib/Nargo.toml +++ b/lib/Nargo.toml @@ -2,7 +2,7 @@ name = "noir_rsa" type = "lib" authors = [""] -compiler_version = ">=0.32.0" +compiler_version = ">=0.34.0" [dependencies] -bignum = {tag = "v0.3.2", git = "https://github.com/noir-lang/noir-bignum"} +bignum = {tag = "v0.3.3", git = "https://github.com/noir-lang/noir-bignum"} From 4cc1b2c81900656b52369c16a54d0cd9d9c69fd4 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 13 Sep 2024 17:47:04 +0100 Subject: [PATCH 6/6] chore: fix canary (#12) --- .github/workflows/nightly-canary.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/nightly-canary.yml b/.github/workflows/nightly-canary.yml index 1a310fb..f8fac80 100644 --- a/.github/workflows/nightly-canary.yml +++ b/.github/workflows/nightly-canary.yml @@ -8,6 +8,9 @@ on: env: CARGO_TERM_COLOR: always +permissions: + issues: write + jobs: test: name: Test on Nargo ${{matrix.toolchain}}