Skip to content

Commit

Permalink
add elgamal encryption to utils; add pvss module; check that the secp…
Browse files Browse the repository at this point in the history
…256k1 group order is prime, and also (order - 1)/2 which is sadly not
  • Loading branch information
xoloki committed Dec 9, 2024
1 parent c4c6e69 commit 59ea57e
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ aes-gcm = "0.10"
bs58 = "0.5"
hashbrown = { version = "0.14", features = ["serde"] }
hex = "0.4.3"
is_prime = { git = "https://github.com/xoloki/is_prime.git" }
num-bigint = "0.4"
num-traits = "0.2"
polynomial = { version = "0.2.5", features = ["serde"] }
primitive-types = "0.12"
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![deny(missing_docs)]
#![doc = include_str!("../README.md")]

/// PVSS
pub mod PVSS;

Check failure on line 5 in src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

file not found for module `PVSS`

Check failure on line 5 in src/lib.rs

View workflow job for this annotation

GitHub Actions / check

file not found for module `PVSS`

Check failure on line 5 in src/lib.rs

View workflow job for this annotation

GitHub Actions / test-all

file not found for module `PVSS`
/// Types which are common to both v1 and v2
#[allow(clippy::op_ref)]
pub mod common;
Expand Down
38 changes: 38 additions & 0 deletions src/pvss.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use is_prime;
use rand_core::{CryptoRng, RngCore};

use crate::curve::scalar::Scalar;

/// A publicly verifiable secret share algorithm
pub struct PVSS {
R: Vec<Scalar>,
c: Scalar,
}

impl PVSS {
/// Construct a random polynomial of the passed degree `n`
pub fn new<RNG: RngCore + CryptoRng>(rng: &mut RNG) -> PVSS {
let R = Vec::new();
let c = Scalar::random(rng);
PVSS { R, c }
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::curve::{point::Point, scalar::Scalar};

use num_bigint::BigUint;

#[test]
fn is_p_minus_1_over_2_prime() {
let p = BigUint::from_bytes_be(crate::curve::point::N.as_slice());

assert!(is_prime::is_biguint_prime(p.clone()));

let p12 = (p - 1u32) / 2u32;

assert!(is_prime::is_biguint_prime(p12.clone()));
}
}
49 changes: 47 additions & 2 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,34 @@ pub fn decrypt(key: &[u8; 32], data: &[u8]) -> Result<Vec<u8>, AesGcmError> {
cipher.decrypt(nonce, cipher_vec.as_ref())
}

/// An El-Gamal encryption packet
struct ElGamal {
c1: Scalar,
c2: Scalar,
}

/// encrypt using a scalar based El-Gamal
pub fn encrypt_elgamal<RNG: RngCore + CryptoRng>(
generator: Scalar,
message: Scalar,
public_key: Scalar,
rng: &mut RNG,
) -> Result<ElGamal, String> {
// ephemeral key
let k = Scalar::random(rng);

let c1 = generator ^ k;
let c2 = (message.invert()) * (public_key ^ k);

Ok(ElGamal { c1, c2 })
}

/// encrypt using a scalar based El-Gamal
pub fn decrypt_elgamal(elgamal: &ElGamal, private_key: Scalar) -> Result<Scalar, String> {
let message = (elgamal.c1 ^ private_key) * (elgamal.c2.invert());
Ok(message)
}

/// Creates a new random number generator.
pub fn create_rng() -> impl RngCore + CryptoRng {
OsRng
Expand All @@ -94,7 +122,7 @@ mod test {

#[test]
#[allow(non_snake_case)]
fn test_shared_secret() {
fn shared_secret() {
let mut rng = create_rng();

let x = Scalar::random(&mut rng);
Expand All @@ -111,7 +139,7 @@ mod test {

#[test]
#[allow(non_snake_case)]
fn test_encrypt_decrypt() {
fn encrypt_decrypt() {
let mut rng = create_rng();
let msg = "It was many and many a year ago, in a kingdom by the sea...";

Expand All @@ -129,4 +157,21 @@ mod test {

assert_eq!(msg.as_bytes(), &plain);
}

#[test]
fn elgamal() {
let mut rng = create_rng();
let generator = Scalar::random(&mut rng);
let private_key = Scalar::random(&mut rng);
let public_key = generator ^ private_key;
let message = Scalar::random(&mut rng);

let elgamal = encrypt_elgamal(generator, message, public_key, &mut rng).unwrap();
let decrypted_message = decrypt_elgamal(&elgamal, private_key).unwrap();

assert_eq!(message, decrypted_message);
}

#[test]
fn pvss() {}
}

0 comments on commit 59ea57e

Please sign in to comment.