Skip to content

Add RSA and Schnorr Examples #989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Apr 7, 2025
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8e89719
first commit. adds basic rsa
jotabulacios Mar 27, 2025
2bb5991
refactor and update README
jotabulacios Mar 27, 2025
092da1b
finish schnorr signature. rand test not working
nicole-graus Mar 27, 2025
3cef8d2
Resolve merge conflict in Cargo.toml
nicole-graus Mar 27, 2025
adabc52
fix comments
nicole-graus Mar 27, 2025
3adfb16
Change random sampl in groth16. Schnorr worikng
nicole-graus Mar 28, 2025
ba5d518
change sample field elem
nicole-graus Mar 28, 2025
6655e5e
fix clippy
nicole-graus Mar 28, 2025
50f1a0f
fix clippy
nicole-graus Mar 31, 2025
a826411
refactor rsa and update README
jotabulacios Mar 31, 2025
7af1369
Merge branch 'add_examples' of github.com:lambdaclass/lambdaworks int…
jotabulacios Mar 31, 2025
ece68a4
remove comments
jotabulacios Apr 1, 2025
9742be3
refactor schnorr
nicole-graus Apr 1, 2025
ff880da
Merge branch 'add_examples' of github.com:lambdaclass/lambdaworks int…
nicole-graus Apr 1, 2025
9382bfe
fix clippy
nicole-graus Apr 1, 2025
f786398
Merge branch 'main' into add_examples
nicole-graus Apr 1, 2025
213c140
update ubuntu version for ci
jotabulacios Apr 1, 2025
218daa2
Merge branch 'main' into add_examples
diegokingston Apr 4, 2025
1c8bf32
Merge branch 'main' into add_examples
diegokingston Apr 4, 2025
656a9d0
Update README.md
diegokingston Apr 4, 2025
4ad40c7
Update README.md
diegokingston Apr 4, 2025
2d15db8
Merge branch 'main' into add_examples
diegokingston Apr 4, 2025
452acec
change p and q values in the test
jotabulacios Apr 4, 2025
a42fe6c
Merge branch 'add_examples' of github.com:lambdaclass/lambdaworks int…
jotabulacios Apr 4, 2025
287861e
Merge branch 'main' into add_examples
diegokingston Apr 7, 2025
cba2c63
Update README.md
diegokingston Apr 7, 2025
3e5a7b2
Update examples/schnorr-signature/README.md
diegokingston Apr 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/criterion_benchs.yml
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ permissions:
jobs:
criterion_bench:
name: Criterion benches (Ubuntu)
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
steps:
2 changes: 1 addition & 1 deletion .github/workflows/iai_benchs_main.yml
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ on:
jobs:
cache_iai_benchs:
name: Cache iai benchs of main
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Install valgrind
run: |
4 changes: 2 additions & 2 deletions .github/workflows/iai_benchs_pr.yml
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ concurrency:
jobs:
fetch_iai_benchs:
name: Fetch iai benchmarks
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Check cache
id: cache-iai-results
@@ -53,7 +53,7 @@ jobs:
run_iai_benchs:
name: Run iai benchmarks
needs: fetch_iai_benchs
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Install valgrind
run: |
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -18,6 +18,9 @@ members = [
"examples/pinocchio",
"examples/prove-verify-circom",
"examples/baby-snark",
"examples/schnorr-signature",
"examples/rsa",

]
exclude = ["ensure-no_std"]
resolver = "2"
2 changes: 1 addition & 1 deletion crates/provers/groth16/src/common.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ pub type PairingOutput = FieldElement<<Pairing as IsPairing>::OutputField>;
pub const ORDER_R_MINUS_1_ROOT_UNITY: FrElement = FrElement::from_hex_unchecked("7");

pub fn sample_fr_elem() -> FrElement {
let mut rng = rand_chacha::ChaCha20Rng::seed_from_u64(9001);
let mut rng = rand_chacha::ChaCha20Rng::from_entropy();
FrElement::new(U256 {
limbs: [
rng.gen::<u64>(),
2 changes: 2 additions & 0 deletions crates/provers/groth16/src/setup.rs
Original file line number Diff line number Diff line change
@@ -47,6 +47,8 @@ struct ToxicWaste {
}

impl ToxicWaste {
/// This will create a new random ToxicWaste from entropy. Bear in mind this is not safe to use.
/// A proper ceremony, like Powers of Tau should be used in production to get the randomness.
pub fn new() -> Self {
Self {
tau: sample_fr_elem(),
18 changes: 18 additions & 0 deletions examples/rsa/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "rsa"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true

[features]
default = ["alloc"]
alloc = ["lambdaworks-math/alloc"]

[dependencies]
num-bigint = "0.4"
num-traits = "0.2"
num-integer = "0.1"
rand = "0.8"
lambdaworks-math = { workspace = true, features = ["alloc"] }
hex = "0.4"
90 changes: 90 additions & 0 deletions examples/rsa/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# RSA Implementation

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.


## ⚠️ Disclaimer

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.

## Overview

RSA is an asymmetric cryptographic algorithm that uses a pair of keys:
- **Public key**: Used for encryption and is shared openly
- **Private key**: Used for decryption and must be kept secret

The security of RSA relies on the practical difficulty of factoring the product of two large prime numbers.

## Mathematical Background

### Key Generation

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)
2. Compute $n = p \cdot q$
3. Calculate Euler's totient function: $\phi(n) = (p-1) \cdot (q-1)$
4. Choose an integer $e$ such that $1 < e < \phi(n)$ and $\gcd(e, \phi(n)) = 1$
5. Compute $d$ such that $d \cdot e \equiv 1 \pmod{\phi(n)}$

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.

### Encryption and Decryption

- **Encryption**: $c = m^e \pmod{n}$ where $m$ is the message and $c$ is the ciphertext
- **Decryption**: $m = c^d \pmod{n}$

### PKCS#1 v1.5 Padding

For secure encryption of arbitrary byte data, we implement PKCS#1 v1.5 padding:

```
00 || 02 || PS || 00 || M
```

Where:
- `00`: First byte (block type)
- `02`: Second byte (block type for encryption)
- `PS`: Padding string of non-zero random bytes
- `00`: Separator
- `M`: Original message

### Basic Example

```rust
use rsa::RSA;
use lambdaworks_math::unsigned_integer::element::UnsignedInteger;

// Create an RSA instance with primes that ensure e < φ(n)
let p = UnsignedInteger::<16>::from_u64(65539);
let q = UnsignedInteger::<16>::from_u64(65521);
let rsa = RSA::<16>::new(p, q)?;

// Encrypt and decrypt a numeric message
let message = UnsignedInteger::<16>::from_u64(42);
let ciphertext = rsa.encrypt(&message)?;
let decrypted = rsa.decrypt(&ciphertext)?;

assert_eq!(message, decrypted);
```

### Byte Data with Padding

```rust
use rsa::RSA;
use lambdaworks_math::unsigned_integer::element::UnsignedInteger;

// Create an RSA instance with primes that ensure e < φ(n)
let p = UnsignedInteger::<16>::from_u64(65539);
let q = UnsignedInteger::<16>::from_u64(65521);
let rsa = RSA::<16>::new(p, q)?;

// Encrypt and decrypt byte data using PKCS#1 v1.5 padding
let msg_bytes = b"Hello RSA with padding!";
let cipher_bytes = rsa.encrypt_bytes_pkcs1(msg_bytes)?;
let plain_bytes = rsa.decrypt_bytes_pkcs1(&cipher_bytes)?;

assert_eq!(msg_bytes.to_vec(), plain_bytes);
```

---

**Note**: This implementation is for educational purposes. Production systems should use established cryptographic libraries that have undergone security audits.
3 changes: 3 additions & 0 deletions examples/rsa/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod rsa;

pub use rsa::{RSAError, RSA};
Loading