Skip to content

Commit d8164df

Browse files
committed
Merge remote-tracking branch 'origin/main' into rsa-pss
2 parents 61252d9 + 4cc1b2c commit d8164df

File tree

6 files changed

+98
-54
lines changed

6 files changed

+98
-54
lines changed

.github/workflows/nightly-canary.yml

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ on:
88
env:
99
CARGO_TERM_COLOR: always
1010

11+
permissions:
12+
issues: write
13+
1114
jobs:
1215
test:
1316
name: Test on Nargo ${{matrix.toolchain}}

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
toolchain: [nightly, 0.32.0]
19+
toolchain: [nightly, 0.34.0]
2020
steps:
2121
- name: Checkout sources
2222
uses: actions/checkout@v4
@@ -39,7 +39,7 @@ jobs:
3939
- name: Install Nargo
4040
uses: noir-lang/[email protected]
4141
with:
42-
toolchain: 0.32.0
42+
toolchain: 0.34.0
4343

4444
- name: Run formatter
4545
working-directory: ./lib

lib/Nargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "noir_rsa"
33
type = "lib"
44
authors = [""]
5-
compiler_version = ">=0.33.0"
5+
compiler_version = ">=0.34.0"
66

77
[dependencies]
8-
bignum = {tag = "v0.3.0", git = "https://github.com/noir-lang/noir-bignum"}
8+
bignum = {tag = "v0.3.3", git = "https://github.com/noir-lang/noir-bignum"}

lib/src/rsa.nr

+51-22
Original file line numberDiff line numberDiff line change
@@ -224,30 +224,36 @@ impl<BN, BNInstance, let NumBytes: u32> RSA<BN, BNInstance, NumBytes> where BN:
224224
* when converting a BigNum into a byte array, the number of bytes is required and currently cannot be inferred.
225225
* Once numeric generics can be derived by applying operations to other numeric generics the need for this will go away.
226226
*
227-
* @note We assume the public key exponent `e` is 65537
227+
* @note The exponent `e` can be either 65537 or 3 (i.e. the most common values in use for RSA)
228228
* Rough cost: 2,048 bit RSA: 26,888 gates per verification
229229
* 1,024 bit RSA: 11,983 gates per verification
230230
* A circuit that verifies 1 signature (and does nothing else) will cost ~32k due to initialization costs of lookup tables
231231
**/
232-
pub fn verify_sha256_pkcs1v15(_: Self, instance: BNInstance, msg_hash: [u8; 32], sig: BN) -> bool {
233-
// e = 65537 = 1 0000 0000 0000 0001
234-
let mut exponentiated = instance.mul(sig, sig);
235-
exponentiated = instance.mul(exponentiated, exponentiated);
236-
exponentiated = instance.mul(exponentiated, exponentiated);
237-
exponentiated = instance.mul(exponentiated, exponentiated);
238-
exponentiated = instance.mul(exponentiated, exponentiated);
239-
exponentiated = instance.mul(exponentiated, exponentiated);
240-
exponentiated = instance.mul(exponentiated, exponentiated);
241-
exponentiated = instance.mul(exponentiated, exponentiated);
242-
exponentiated = instance.mul(exponentiated, exponentiated);
243-
exponentiated = instance.mul(exponentiated, exponentiated);
244-
exponentiated = instance.mul(exponentiated, exponentiated);
245-
exponentiated = instance.mul(exponentiated, exponentiated);
246-
exponentiated = instance.mul(exponentiated, exponentiated);
247-
exponentiated = instance.mul(exponentiated, exponentiated);
248-
exponentiated = instance.mul(exponentiated, exponentiated);
249-
exponentiated = instance.mul(exponentiated, exponentiated);
250-
exponentiated = instance.mul(exponentiated, sig);
232+
pub fn verify_sha256_pkcs1v15(_: Self, instance: BNInstance, msg_hash: [u8; 32], sig: BN, exponent: u32) -> bool {
233+
assert((exponent == 3) | (exponent == 65537), "Exponent must be 65537 or 3");
234+
let mut exponentiated = instance.mul(sig, sig); // sig^2
235+
236+
if exponent == 65537 {
237+
// e = 65537 = 1 0000 0000 0000 0001
238+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^2 * sig^2 = sig^4
239+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^8
240+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^16
241+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^32
242+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^64
243+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^128
244+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^256
245+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^512
246+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^1024
247+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^2048
248+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^4096
249+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^8192
250+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^16384
251+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^32768
252+
exponentiated = instance.mul(exponentiated, exponentiated); // sig^65536
253+
}
254+
// otherwise, e = 3 = 11
255+
256+
exponentiated = instance.mul(exponentiated, sig); // either sig^2 * sig = sig^3 or sig^65536 * sig = sig^65537
251257

252258
let mut padded_sha256_hash_bytes: [u8; NumBytes] = exponentiated.to_le_bytes();
253259
compare_signature_sha256(padded_sha256_hash_bytes, msg_hash)
@@ -273,7 +279,7 @@ fn test_verify_sha256_pkcs1v15_1024() {
273279
);
274280

275281
let rsa: RSA1024 = RSA {};
276-
assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature));
282+
assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature, 65537));
277283
}
278284

279285
#[test]
@@ -293,7 +299,30 @@ fn test_verify_sha256_pkcs1v15_2048() {
293299
]
294300
);
295301
let rsa: RSA2048 = RSA {};
296-
assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature));
302+
assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature, 65537));
303+
}
304+
305+
#[test]
306+
fn test_verify_sha256_pkcs1v15_2048_exponent_3() {
307+
let sha256_hash: [u8; 32] = dep::std::hash::sha256("Hello World! This is Noir-RSA".as_bytes());
308+
309+
let BNInstance: BNInst2048 = BigNumInstance::new(
310+
[
311+
0xc6a1c5e80ce354c6b00ccf20cf3a1d, 0x178d135f925a03eceb25f79bab56ee, 0x13ab3d6d8a5c5586752b5a3bc74ec3, 0x3d13b47b152367e3e2fc014d03d19f, 0xe89a7278a2945b4a672011691db30f, 0x5b4c1b061378143629dbb29dea1e4, 0x26a48b6f4e8df1472fd4fc12b17c18, 0xc7c92ead0ce810520cf3a8267254c1, 0x806b8cdba93909e9d9a71ee1bcdac2, 0x703ef80f8eb703b84c201366dff1c7, 0x7361034bb2c4c081aad8b1bcca83de, 0xb23c7e1109e65e6d08fa72cc862008, 0x750bc927874455782cd2d6fd5a51f6, 0xf0b83665fbf8cb5cf31cee9f89848e, 0x20d447b08953c7ce3330197938a8ae, 0x11a08bb5a2241c6a2a69f930d8b28b, 0xef5bca8dd582570a44705cb123d09e, 0xb7
312+
],
313+
[
314+
0xbc93ee57c1c8adc53f0a995a6221ca, 0x2a9b43587534b20dd85a5233329f10, 0xc587fd488f64eed02adc1f462f7448, 0xf1484d37676bb0e800996757382522, 0xc2126c48221aa61c9f52c6b918bab3, 0x8660c861dd52ed958beaf6c6c2cff0, 0x5edd9dc4f02a000f350948c70bdf94, 0x6f3b9603149272e9b232a379a017bb, 0x950fd85cffbdf4476b1cb66c1f63d6, 0xee459417b1a56b6f7ef3b89e385ac, 0x48daeef6d1a055f3746ab71058e137, 0x3cbc0ba96d541feee92dd27f9d0306, 0x6a2a42384cc388fa113ee80317e0a0, 0x43b4f89c508a42d309f295c0d9f3a5, 0x8d8c28b05f71b962b40ea906ff407f, 0x390a7989eb9cecc5827cb00e1ca693, 0x4cbf158eabf7e96ef7f2586d0ce613, 0x164
315+
]
316+
);
317+
318+
let signature: BN2048 = BigNum::from_array(
319+
[
320+
0x19772b9af8a031170a7844ce4f3d7c, 0x4808e817258f57805a7326f70bcd74, 0xca8f3f98e374d52100115bfa645a7d, 0x49547189edff3b683fee267e717b7f, 0x96f263b47e96925f3b5898a7389ceb, 0x4cc50a893da91d0e085fc6656b30bc, 0x67e84ff92d88c0ad2c17ad2701309e, 0x095326818578173289665fcd9ad788, 0x775c6e85b745065db9411b9d579763, 0xad0f20c8a5265dfca4080ca877a2b8, 0xbfd199372f1680b3bc583a08bd8ba9, 0x663476ca3e5ede3e5976887db2c4e5, 0x531192309d0d49fed47c0216c27f9e, 0x37d26d31c86b951ca1c17b517063b7, 0x3cdb362ed5dfd06568eb9a9bbb6a91, 0x14520b9c23f583314729a9d858bca9, 0x5e0505067ada1026721d45997bf2c4, 0x3e
321+
]
322+
);
323+
324+
let rsa: RSA2048 = RSA {};
325+
assert(rsa.verify_sha256_pkcs1v15(BNInstance, sha256_hash, signature, 3));
297326
}
298327

299328
#[test]

signature_gen/.DS_Store

-6 KB
Binary file not shown.

signature_gen/src/main.rs

+40-28
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
use num_bigint::BigUint;
22
use rsa::pkcs1v15::Signature;
3-
use rsa::pkcs1v15::VerifyingKey;
43
use rsa::{RsaPrivateKey, RsaPublicKey};
54
use signature::Keypair;
65
use signature::RandomizedSignerMut;
76
use std::env;
87
use toml::Value;
98

10-
use rand;
11-
use rsa::signature::{SignatureEncoding, Signer, Verifier};
9+
use rsa::signature::{SignatureEncoding, Signer};
1210
use rsa::traits::PublicKeyParts;
1311
use sha2::{Digest, Sha256};
1412

@@ -33,7 +31,7 @@ fn format_limbs_as_toml_value(limbs: &Vec<BigUint>) -> Vec<Value> {
3331
.collect()
3432
}
3533

36-
fn generate_2048_bit_signature_parameters(msg: &str, as_toml: bool, pss: bool) {
34+
fn generate_2048_bit_signature_parameters(msg: &str, as_toml: bool, exponent: u32, pss: bool) {
3735
let mut hasher = Sha256::new();
3836
hasher.update(msg.as_bytes());
3937
let hashed_message = hasher.finalize();
@@ -47,7 +45,8 @@ fn generate_2048_bit_signature_parameters(msg: &str, as_toml: bool, pss: bool) {
4745
let mut rng: rand::prelude::ThreadRng = rand::thread_rng();
4846
let bits: usize = 2048;
4947
let priv_key: RsaPrivateKey =
50-
RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
48+
RsaPrivateKey::new_with_exp(&mut rng, bits, &BigUint::from(exponent))
49+
.expect("failed to generate a key");
5150
let pub_key: RsaPublicKey = priv_key.clone().into();
5251

5352
let sig_bytes = if pss {
@@ -70,8 +69,6 @@ fn generate_2048_bit_signature_parameters(msg: &str, as_toml: bool, pss: bool) {
7069
);
7170

7271
if as_toml {
73-
let hash_toml = toml::to_vec(&hashed_as_bytes).unwrap();
74-
7572
let sig_limbs = split_into_120_bit_limbs(&sig_uint.clone(), 2048);
7673
let signature_toml = Value::Array(format_limbs_as_toml_value(&sig_limbs));
7774

@@ -120,33 +117,48 @@ fn main() {
120117
.long("pss")
121118
.help("Use RSA PSS"),
122119
)
120+
.arg(
121+
Arg::with_name("exponent")
122+
.short("e")
123+
.long("exponent")
124+
.takes_value(true)
125+
.help("Exponent to use for the key")
126+
.default_value("65537"),
127+
)
123128
.get_matches();
124129

125130
let msg = matches.value_of("msg").unwrap();
126131
let as_toml = matches.is_present("toml");
127132
let pss = matches.is_present("pss");
128-
129-
generate_2048_bit_signature_parameters(msg, as_toml, pss);
130-
}
133+
let e: u32 = matches.value_of("exponent").unwrap().parse().unwrap();
131134

132-
fn test_signature_generation_impl() {
133-
let mut rng = rand::thread_rng();
134-
let bits = 2048;
135-
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
136-
let pub_key: RsaPublicKey = priv_key.clone().into();
137-
let text: &str = "hello world";
138-
let signing_key = rsa::pkcs1v15::SigningKey::<Sha256>::new(priv_key);
139-
let sig: Vec<u8> = signing_key.sign(text.as_bytes()).to_vec();
140-
let verifying_key = VerifyingKey::<Sha256>::new(pub_key);
141-
142-
let result = verifying_key.verify(
143-
text.as_bytes(),
144-
&Signature::try_from(sig.as_slice()).unwrap(),
145-
);
146-
result.expect("failed to verify");
135+
generate_2048_bit_signature_parameters(msg, as_toml, e, pss);
147136
}
148137

149-
#[test]
150-
fn test_signature_generation() {
151-
test_signature_generation_impl();
138+
#[cfg(test)]
139+
mod tests {
140+
use super::*;
141+
use rand::thread_rng;
142+
use rsa::pkcs1v15::Signature;
143+
use rsa::signature::{Signer, Verifier};
144+
use rsa::{pkcs1v15::VerifyingKey, RsaPrivateKey, RsaPublicKey};
145+
use sha2::Sha256;
146+
147+
#[test]
148+
fn test_signature_generation() {
149+
let mut rng = thread_rng();
150+
let bits = 2048;
151+
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
152+
let pub_key: RsaPublicKey = priv_key.clone().into();
153+
let text: &str = "hello world";
154+
let signing_key = rsa::pkcs1v15::SigningKey::<Sha256>::new(priv_key);
155+
let sig: Vec<u8> = signing_key.sign(text.as_bytes()).to_vec();
156+
let verifying_key = VerifyingKey::<Sha256>::new(pub_key);
157+
158+
let result = verifying_key.verify(
159+
text.as_bytes(),
160+
&Signature::try_from(sig.as_slice()).unwrap(),
161+
);
162+
result.expect("failed to verify");
163+
}
152164
}

0 commit comments

Comments
 (0)