Skip to content

Commit ca84326

Browse files
nicole-grausjotabulaciosdiegokingstonpablodeymo
authored
Add RSA and Schnorr Examples (#989)
* first commit. adds basic rsa * refactor and update README * finish schnorr signature. rand test not working * fix comments * Change random sampl in groth16. Schnorr worikng * change sample field elem * fix clippy * fix clippy * refactor rsa and update README * remove comments * refactor schnorr * fix clippy * update ubuntu version for ci * Update README.md * Update README.md * change p and q values in the test * Update README.md * Update examples/schnorr-signature/README.md Co-authored-by: Pablo Deymonnaz <deymonnaz@gmail.com> --------- Co-authored-by: jotabulacios <jbulacios@fi.uba.ar> Co-authored-by: Diego K <43053772+diegokingston@users.noreply.github.com> Co-authored-by: Pablo Deymonnaz <deymonnaz@gmail.com>
1 parent 7fe890e commit ca84326

File tree

15 files changed

+764
-5
lines changed

15 files changed

+764
-5
lines changed

.github/workflows/criterion_benchs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ permissions:
1313
jobs:
1414
criterion_bench:
1515
name: Criterion benches (Ubuntu)
16-
runs-on: ubuntu-20.04
16+
runs-on: ubuntu-latest
1717
env:
1818
CARGO_TERM_COLOR: always
1919
steps:

.github/workflows/iai_benchs_main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
jobs:
88
cache_iai_benchs:
99
name: Cache iai benchs of main
10-
runs-on: ubuntu-20.04
10+
runs-on: ubuntu-latest
1111
steps:
1212
- name: Install valgrind
1313
run: |

.github/workflows/iai_benchs_pr.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ concurrency:
1111
jobs:
1212
fetch_iai_benchs:
1313
name: Fetch iai benchmarks
14-
runs-on: ubuntu-20.04
14+
runs-on: ubuntu-latest
1515
steps:
1616
- name: Check cache
1717
id: cache-iai-results
@@ -53,7 +53,7 @@ jobs:
5353
run_iai_benchs:
5454
name: Run iai benchmarks
5555
needs: fetch_iai_benchs
56-
runs-on: ubuntu-20.04
56+
runs-on: ubuntu-latest
5757
steps:
5858
- name: Install valgrind
5959
run: |

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ members = [
1818
"examples/pinocchio",
1919
"examples/prove-verify-circom",
2020
"examples/baby-snark",
21+
"examples/schnorr-signature",
22+
"examples/rsa",
23+
2124
]
2225
exclude = ["ensure-no_std"]
2326
resolver = "2"

crates/provers/groth16/src/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub type PairingOutput = FieldElement<<Pairing as IsPairing>::OutputField>;
2626
pub const ORDER_R_MINUS_1_ROOT_UNITY: FrElement = FrElement::from_hex_unchecked("7");
2727

2828
pub fn sample_fr_elem() -> FrElement {
29-
let mut rng = rand_chacha::ChaCha20Rng::seed_from_u64(9001);
29+
let mut rng = rand_chacha::ChaCha20Rng::from_entropy();
3030
FrElement::new(U256 {
3131
limbs: [
3232
rng.gen::<u64>(),

crates/provers/groth16/src/setup.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ struct ToxicWaste {
4747
}
4848

4949
impl ToxicWaste {
50+
/// This will create a new random ToxicWaste from entropy. Bear in mind this is not safe to use.
51+
/// A proper ceremony, like Powers of Tau should be used in production to get the randomness.
5052
pub fn new() -> Self {
5153
Self {
5254
tau: sample_fr_elem(),

examples/rsa/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "rsa"
3+
version.workspace = true
4+
edition.workspace = true
5+
license.workspace = true
6+
repository.workspace = true
7+
8+
[features]
9+
default = ["alloc"]
10+
alloc = ["lambdaworks-math/alloc"]
11+
12+
[dependencies]
13+
num-bigint = "0.4"
14+
num-traits = "0.2"
15+
num-integer = "0.1"
16+
rand = "0.8"
17+
lambdaworks-math = { workspace = true, features = ["alloc"] }
18+
hex = "0.4"

examples/rsa/README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# RSA Implementation
2+
3+
This is an implementation of the RSA cryptographic algorithm in Rust. RSA is one of the first public-key cryptosystems widely used for secure data transmission.
4+
5+
6+
## ⚠️ Disclaimer
7+
8+
This implementation is not cryptographically secure due to non-constant time operations and other considerations, so it must not be used in production. It is intended to be just an educational example.
9+
10+
## Overview
11+
12+
RSA is an asymmetric cryptographic algorithm that uses a pair of keys:
13+
- **Public key**: Used for encryption and is shared openly
14+
- **Private key**: Used for decryption and must be kept secret
15+
16+
The security of RSA relies on the practical difficulty of factoring the product of two large prime numbers.
17+
18+
## Mathematical Background
19+
20+
### Key Generation
21+
22+
1. Choose two distinct prime numbers $p$ and $q$ (these should be randomly generated, should be sufficiently large, and their magnitudes should not be similar)
23+
2. Compute $n = p \cdot q$
24+
3. Calculate Euler's totient function: $\phi(n) = (p-1) \cdot (q-1)$
25+
4. Choose an integer $e$ such that $1 < e < \phi(n)$ and $\gcd(e, \phi(n)) = 1$
26+
5. Compute $d$ such that $d \cdot e \equiv 1 \pmod{\phi(n)}$
27+
28+
The public key is $(e, n)$, and the private key is $d$. In practice, $e$ is chosen as a number with low Hamming weight (such as Fermat primes) and $d$ is computed by finding the inverse.
29+
30+
### Encryption and Decryption
31+
32+
- **Encryption**: $c = m^e \pmod{n}$ where $m$ is the message and $c$ is the ciphertext
33+
- **Decryption**: $m = c^d \pmod{n}$
34+
35+
### PKCS#1 v1.5 Padding
36+
37+
For secure encryption of arbitrary byte data, we implement PKCS#1 v1.5 padding:
38+
39+
```
40+
00 || 02 || PS || 00 || M
41+
```
42+
43+
Where:
44+
- `00`: First byte (block type)
45+
- `02`: Second byte (block type for encryption)
46+
- `PS`: Padding string of non-zero random bytes
47+
- `00`: Separator
48+
- `M`: Original message
49+
50+
### Basic Example
51+
52+
```rust
53+
use rsa::RSA;
54+
use lambdaworks_math::unsigned_integer::element::UnsignedInteger;
55+
56+
// Create an RSA instance with primes that ensure e < φ(n)
57+
let p = UnsignedInteger::<16>::from_u64(65539);
58+
let q = UnsignedInteger::<16>::from_u64(65521);
59+
let rsa = RSA::<16>::new(p, q)?;
60+
61+
// Encrypt and decrypt a numeric message
62+
let message = UnsignedInteger::<16>::from_u64(42);
63+
let ciphertext = rsa.encrypt(&message)?;
64+
let decrypted = rsa.decrypt(&ciphertext)?;
65+
66+
assert_eq!(message, decrypted);
67+
```
68+
69+
### Byte Data with Padding
70+
71+
```rust
72+
use rsa::RSA;
73+
use lambdaworks_math::unsigned_integer::element::UnsignedInteger;
74+
75+
// Create an RSA instance with primes that ensure e < φ(n)
76+
let p = UnsignedInteger::<16>::from_u64(65539);
77+
let q = UnsignedInteger::<16>::from_u64(65521);
78+
let rsa = RSA::<16>::new(p, q)?;
79+
80+
// Encrypt and decrypt byte data using PKCS#1 v1.5 padding
81+
let msg_bytes = b"Hello RSA with padding!";
82+
let cipher_bytes = rsa.encrypt_bytes_pkcs1(msg_bytes)?;
83+
let plain_bytes = rsa.decrypt_bytes_pkcs1(&cipher_bytes)?;
84+
85+
assert_eq!(msg_bytes.to_vec(), plain_bytes);
86+
```
87+
88+
---
89+
90+
**Note**: This implementation is for educational purposes. Production systems should use established cryptographic libraries that have undergone security audits.

examples/rsa/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod rsa;
2+
3+
pub use rsa::{RSAError, RSA};

0 commit comments

Comments
 (0)