Skip to content

Commit

Permalink
Merge pull request #123 from dusk-network/lite
Browse files Browse the repository at this point in the history
  • Loading branch information
xevisalle authored Dec 5, 2024
2 parents 90bc004 + ba35e4d commit 76ef6ec
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 85 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ This repository is structured as follows:

- :computer: [**Core**](core): the core Citadel protocol implementation, containing all the involved data types, the protocol workflows, and the license circuit.
- :pencil: [**License Contract**](contract): The license contract, along with all the required code to test and deploy it.
- :scroll: [**Docs**](docs): A folder where you can find the documentation concerning the our Citadel specific implementation.
- :scroll: [**Docs**](docs): A folder where you can find the documentation concerning our Citadel specific implementation.

**DISCLAIMER**: the code in this repository **has not gone through an exhaustive security analysis**, so it is not intended to be used in a production environment, only for academic purposes.
1 change: 1 addition & 0 deletions contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Changed 'issue_license' by removing the 'pos' argument and self position determination [#1039]
- Fixed `license` tests error when creating `PublicParameters` from a slice
- Moved the `license-contract` to the `Citadel` repository [#122]
- Changed tests to match the new `core` API

## [0.1.0] - 2023-07-13

Expand Down
44 changes: 13 additions & 31 deletions contract/tests/license_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ use std::sync::mpsc;
use dusk_bytes::Serializable;
use dusk_poseidon::{Domain, Hash};
use execution_core::plonk::{Prover, Verifier};
use ff::Field;
use rand::rngs::StdRng;
use rand::{CryptoRng, RngCore, SeedableRng};
use rkyv::{check_archived_root, Deserialize, Infallible};
use zk_citadel::{circuit, gadgets, License, Request, SessionCookie};
use zk_citadel::{circuit, gadgets, License, LicenseCreator, Request, SessionCookie};

const PROVER_BYTES: &[u8] = include_bytes!("../../target/prover");

Expand All @@ -28,8 +27,8 @@ const LICENSE_CONTRACT_BYTECODE: &[u8] =
pub type LicenseOpening = poseidon_merkle::Opening<(), { circuit::DEPTH }>;

use execution_core::{
transfer::phoenix::{PublicKey, SecretKey, StealthAddress, ViewKey},
BlsScalar, ContractId, JubJubAffine, JubJubScalar, GENERATOR_EXTENDED,
transfer::phoenix::{PublicKey, SecretKey, ViewKey},
BlsScalar, ContractId, JubJubAffine, JubJubScalar,
};
use rusk_abi::{ContractData, Session};

Expand All @@ -52,12 +51,12 @@ fn create_test_license<R: RngCore + CryptoRng>(
attr: &JubJubScalar,
sk_lp: &SecretKey,
pk_lp: &PublicKey,
sa_user: &StealthAddress,
k_lic: &JubJubAffine,
sk_user: &SecretKey,
pk_user: &PublicKey,
rng: &mut R,
) -> License {
let request = Request::new(pk_lp, sa_user, k_lic, rng).unwrap();
License::new(attr, sk_lp, &request, rng).unwrap()
let request = Request::new(sk_user, pk_user, pk_lp, rng).unwrap();
License::new(attr, sk_lp, &LicenseCreator::FromRequest(request), rng).unwrap()
}

fn initialize() -> Session {
Expand Down Expand Up @@ -102,21 +101,6 @@ fn find_owned_license(
None
}

/// Creates the Citadel request object
fn create_request<R: RngCore + CryptoRng>(
sk_user: &SecretKey,
pk_lp: &PublicKey,
rng: &mut R,
) -> Request {
let pk = PublicKey::from(sk_user);
let lsa = pk.gen_stealth_address(&JubJubScalar::random(&mut *rng));
let lsk = sk_user.gen_note_sk(&lsa);
let k_lic = JubJubAffine::from(
GENERATOR_EXTENDED * Hash::digest_truncated(Domain::Other, &[(*lsk.as_ref()).into()])[0],
);
Request::new(pk_lp, &lsa, &k_lic, rng).unwrap()
}

fn compute_citadel_parameters(
rng: &mut StdRng,
sk: &SecretKey,
Expand All @@ -140,16 +124,14 @@ fn license_issue_get_merkle() {
// user
let sk_user = SecretKey::random(rng);
let pk_user = PublicKey::from(&sk_user);
let sa_user = pk_user.gen_stealth_address(&JubJubScalar::random(&mut *rng));

// license provider
let sk_lp = SecretKey::random(rng);
let pk_lp = PublicKey::from(&sk_lp);
let k_lic = JubJubAffine::from(GENERATOR_EXTENDED * JubJubScalar::random(&mut *rng));

let attr = JubJubScalar::from(USER_ATTRIBUTES);

let license = create_test_license(&attr, &sk_lp, &pk_lp, &sa_user, &k_lic, rng);
let license = create_test_license(&attr, &sk_lp, &pk_lp, &sk_user, &pk_user, rng);
let license_blob = rkyv::to_bytes::<_, 4096>(&license)
.expect("Request should serialize correctly")
.to_vec();
Expand Down Expand Up @@ -210,7 +192,6 @@ fn multiple_licenses_issue_get_merkle() {
// user
let sk_user = SecretKey::random(rng);
let pk_user = PublicKey::from(&sk_user);
let sa_user = pk_user.gen_stealth_address(&JubJubScalar::random(&mut *rng));

// license provider
let sk_lp = SecretKey::random(rng);
Expand All @@ -220,8 +201,7 @@ fn multiple_licenses_issue_get_merkle() {

const NUM_LICENSES: usize = 4 + 1;
for _ in 0..NUM_LICENSES {
let k_lic = JubJubAffine::from(GENERATOR_EXTENDED * JubJubScalar::random(&mut *rng));
let license = create_test_license(&attr, &sk_lp, &pk_lp, &sa_user, &k_lic, rng);
let license = create_test_license(&attr, &sk_lp, &pk_lp, &sk_user, &pk_user, rng);
let license_blob = rkyv::to_bytes::<_, 4096>(&license)
.expect("Request should serialize correctly")
.to_vec();
Expand Down Expand Up @@ -312,14 +292,16 @@ fn use_license_get_session() {

// user
let sk_user = SecretKey::random(rng);
let pk_user = PublicKey::from(&sk_user);

// license provider
let sk_lp = SecretKey::random(rng);
let pk_lp = PublicKey::from(&sk_lp);

let request = create_request(&sk_user, &pk_lp, rng);
let request =
Request::new(&sk_user, &pk_user, &pk_lp, rng).expect("Request correctly created.");
let attr = JubJubScalar::from(USER_ATTRIBUTES);
let license = License::new(&attr, &sk_lp, &request, rng).unwrap();
let license = License::new(&attr, &sk_lp, &LicenseCreator::FromRequest(request), rng).unwrap();

let license_blob = rkyv::to_bytes::<_, 4096>(&license)
.expect("Request should serialize correctly")
Expand Down
1 change: 1 addition & 0 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Add `circuit` module
- Add `LicenseCreator`

### Changed

Expand Down
23 changes: 10 additions & 13 deletions core/benches/license_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use dusk_jubjub::{JubJubAffine, JubJubScalar, GENERATOR_EXTENDED};
use dusk_jubjub::{JubJubAffine, JubJubScalar};
use dusk_plonk::prelude::*;
use dusk_poseidon::{Domain, Hash};
use ff::Field;
use phoenix_core::{PublicKey, SecretKey};
use poseidon_merkle::{Item, Tree};

use zk_citadel::{circuit, gadgets, License, Request, SessionCookie};
use zk_citadel::{circuit, gadgets, License, LicenseCreator, SessionCookie};

use criterion::{criterion_group, criterion_main, Criterion};
use rand_core::OsRng;
Expand Down Expand Up @@ -46,25 +45,23 @@ impl Circuit for LicenseCircuit {
}

fn license_circuit_benchmark(crit: &mut Criterion) {
// Compute gadget parameters
let sk = SecretKey::random(&mut OsRng);
let pk = PublicKey::from(&sk);
let sk_lp = SecretKey::random(&mut OsRng);
let pk_lp = PublicKey::from(&sk_lp);

let pp = PublicParameters::setup(1 << circuit::CAPACITY, &mut OsRng).unwrap();
let (prover, verifier) =
Compiler::compile::<LicenseCircuit>(&pp, LABEL).expect("failed to compile circuit");

let lsa = pk.gen_stealth_address(&JubJubScalar::random(&mut OsRng));
let lsk = sk.gen_note_sk(&lsa);
let k_lic = JubJubAffine::from(
GENERATOR_EXTENDED * Hash::digest_truncated(Domain::Other, &[(*lsk.as_ref()).into()])[0],
);
let req = Request::new(&pk_lp, &lsa, &k_lic, &mut OsRng).expect("Request correctly computed.");

let attr_data = JubJubScalar::from(ATTRIBUTE_DATA);
let lic =
License::new(&attr_data, &sk_lp, &req, &mut OsRng).expect("License correctly computed.");
let lic = License::new(
&attr_data,
&sk_lp,
&LicenseCreator::FromPublicKey(pk),
&mut OsRng,
)
.expect("License correctly computed.");

let mut tree = Tree::<(), { circuit::DEPTH }>::new();
let lpk = JubJubAffine::from(lic.lsa.note_pk().as_ref());
Expand Down
24 changes: 14 additions & 10 deletions core/src/gadgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use dusk_bytes::Serializable;
use dusk_jubjub::{GENERATOR, GENERATOR_NUMS};
use dusk_jubjub::{GENERATOR_EXTENDED, GENERATOR_NUMS_EXTENDED};
use dusk_jubjub::{dhke, GENERATOR, GENERATOR_EXTENDED, GENERATOR_NUMS, GENERATOR_NUMS_EXTENDED};
use dusk_plonk::prelude::*;
use dusk_poseidon::Hash;
use dusk_poseidon::{Domain, HashGadget};
Expand Down Expand Up @@ -168,12 +167,19 @@ impl<const DEPTH: usize> GadgetParameters<DEPTH> {
merkle_proof: Opening<(), DEPTH>,
) -> Result<(Self, SessionCookie), phoenix_core::Error> {
let lsk = sk.gen_note_sk(&lic.lsa);
let k_lic = JubJubAffine::from(
GENERATOR_EXTENDED
* Hash::digest_truncated(Domain::Other, &[(*lsk.as_ref()).into()])[0],
);

let dec: [u8; LIC_PLAINTEXT_SIZE] = decrypt(&k_lic, &lic.enc)?;
let k_lic = dhke(sk.a(), lic.lsa.R());

let dec: [u8; LIC_PLAINTEXT_SIZE] = match decrypt(&k_lic, &lic.enc) {
Ok(dec) => dec,
Err(_err) => {
let k_lic = JubJubAffine::from(
GENERATOR_EXTENDED
* Hash::digest_truncated(Domain::Other, &[(*lsk.as_ref()).into()])[0],
);

decrypt(&k_lic, &lic.enc)?
}
};

let mut sig_lic_bytes = [0u8; Signature::SIZE];
sig_lic_bytes.copy_from_slice(&dec[..Signature::SIZE]);
Expand All @@ -185,8 +191,6 @@ impl<const DEPTH: usize> GadgetParameters<DEPTH> {
JubJubScalar::from_bytes(&attr_data_bytes).expect("Deserialization was correct.");

let lpk = JubJubAffine::from(*lic.lsa.note_pk().as_ref());

let lsk = sk.gen_note_sk(&lic.lsa);
let lpk_p = JubJubAffine::from(GENERATOR_NUMS_EXTENDED * lsk.as_ref());

let s_0 = BlsScalar::random(&mut rng);
Expand Down
2 changes: 1 addition & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ mod session;
pub mod circuit;
pub mod gadgets;

pub use license::License;
pub use license::{License, LicenseCreator};
pub use request::Request;
pub use session::{Session, SessionCookie};
49 changes: 34 additions & 15 deletions core/src/license.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
use dusk_bytes::Serializable;
use dusk_jubjub::dhke;
use dusk_poseidon::{Domain, Hash};
use ff::Field;
use jubjub_schnorr::{SecretKey as NoteSecretKey, Signature};
use phoenix_core::{
aes::{decrypt, encrypt, ENCRYPTION_EXTRA_SIZE},
Error, SecretKey, StealthAddress,
Error, PublicKey, SecretKey, StealthAddress,
};

use rand_core::{CryptoRng, RngCore};
Expand All @@ -25,6 +26,11 @@ use crate::request::{Request, REQ_PLAINTEXT_SIZE};
pub(crate) const LIC_PLAINTEXT_SIZE: usize = Signature::SIZE + JubJubScalar::SIZE;
const LIC_ENCRYPTION_SIZE: usize = LIC_PLAINTEXT_SIZE + ENCRYPTION_EXTRA_SIZE;

pub enum LicenseCreator {
FromRequest(Request),
FromPublicKey(PublicKey),
}

#[cfg_attr(
feature = "rkyv-impl",
derive(Archive, Serialize, Deserialize),
Expand All @@ -40,27 +46,40 @@ impl License {
pub fn new<R: RngCore + CryptoRng>(
attr_data: &JubJubScalar,
sk_lp: &SecretKey,
req: &Request,
lc: &LicenseCreator,
rng: &mut R,
) -> Result<Self, Error> {
let k_dh = dhke(sk_lp.a(), req.rsa.R());
let dec: [u8; REQ_PLAINTEXT_SIZE] = decrypt(&k_dh, &req.enc)?;
let (lsa, k_lic) = match lc {
LicenseCreator::FromRequest(req) => {
let k_dh = dhke(sk_lp.a(), req.rsa.R());
let dec: [u8; REQ_PLAINTEXT_SIZE] = decrypt(&k_dh, &req.enc)?;

let mut lsa_bytes = [0u8; StealthAddress::SIZE];
lsa_bytes.copy_from_slice(&dec[..StealthAddress::SIZE]);
let lsa =
StealthAddress::from_bytes(&lsa_bytes).expect("Deserialization was correct.");

let mut k_lic_bytes = [0u8; JubJubAffine::SIZE];
k_lic_bytes.copy_from_slice(&dec[StealthAddress::SIZE..]);
let k_lic =
JubJubAffine::from_bytes(k_lic_bytes).expect("Deserialization was correct.");

(lsa, k_lic)
}
LicenseCreator::FromPublicKey(pk_user) => {
let r_dh = JubJubScalar::random(&mut *rng);
let lsa = pk_user.gen_stealth_address(&r_dh);
let k_lic = dhke(&r_dh, pk_user.A());

let mut lsa_bytes = [0u8; StealthAddress::SIZE];
lsa_bytes.copy_from_slice(&dec[..StealthAddress::SIZE]);
let lsa = StealthAddress::from_bytes(&lsa_bytes).expect("Deserialization was correct.");
(lsa, k_lic)
}
};

let mut k_lic_bytes = [0u8; JubJubAffine::SIZE];
k_lic_bytes.copy_from_slice(&dec[StealthAddress::SIZE..]);
let k_lic = JubJubAffine::from_bytes(k_lic_bytes).expect("Deserialization was correct.");
let lpk = JubJubAffine::from(lsa.note_pk().as_ref());

let message = Hash::digest(
Domain::Other,
&[
lsa.note_pk().as_ref().get_u(),
lsa.note_pk().as_ref().get_v(),
BlsScalar::from(*attr_data),
],
&[lpk.get_u(), lpk.get_v(), BlsScalar::from(*attr_data)],
)[0];
let sig_lic = NoteSecretKey::from(sk_lp.a()).sign(rng, message);

Expand Down
16 changes: 12 additions & 4 deletions core/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use dusk_bytes::Serializable;
use dusk_jubjub::dhke;
use dusk_jubjub::{dhke, GENERATOR_EXTENDED};
use dusk_poseidon::{Domain, Hash};
use ff::Field;
use phoenix_core::{
aes::{encrypt, ENCRYPTION_EXTRA_SIZE},
Error, PublicKey, StealthAddress,
Error, PublicKey, SecretKey, StealthAddress,
};

use rand_core::{CryptoRng, RngCore};
Expand All @@ -35,11 +36,18 @@ pub struct Request {

impl Request {
pub fn new<R: RngCore + CryptoRng>(
sk_user: &SecretKey,
pk_user: &PublicKey,
pk_lp: &PublicKey,
lsa: &StealthAddress,
k_lic: &JubJubAffine,
rng: &mut R,
) -> Result<Self, Error> {
let lsa = pk_user.gen_stealth_address(&JubJubScalar::random(&mut *rng));
let lsk = sk_user.gen_note_sk(&lsa);
let k_lic = JubJubAffine::from(
GENERATOR_EXTENDED
* Hash::digest_truncated(Domain::Other, &[(*lsk.as_ref()).into()])[0],
);

let r_dh = JubJubScalar::random(&mut *rng);
let rsa = pk_lp.gen_stealth_address(&r_dh);
let k_dh = dhke(&r_dh, pk_lp.A());
Expand Down
Loading

0 comments on commit 76ef6ec

Please sign in to comment.