Skip to content

Commit

Permalink
core: Add LicenseCreator
Browse files Browse the repository at this point in the history
  • Loading branch information
xevisalle committed Dec 4, 2024
1 parent b938e9d commit a99ed9c
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 37 deletions.
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};
41 changes: 31 additions & 10 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,19 +46,34 @@ 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.");

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)
}
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 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)
}
};

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

Expand Down
58 changes: 55 additions & 3 deletions core/tests/citadel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use phoenix_core::{PublicKey, SecretKey};
use poseidon_merkle::{Item, Tree};
use rand_core::OsRng;

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

static LABEL: &[u8; 12] = b"dusk-network";

Expand Down Expand Up @@ -45,8 +45,13 @@ fn test_full_citadel() {

// Second, the LP computes these values and grants the License on-chain
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::FromRequest(req),
&mut OsRng,
)
.expect("License correctly computed from request.");

let mut tree = Tree::<(), { circuit::DEPTH }>::new();
let lpk = JubJubAffine::from(lic.lsa.note_pk().as_ref());
Expand Down Expand Up @@ -117,4 +122,51 @@ fn test_full_citadel() {

// So, this should be an error
assert!(session.verify(sc_false).is_err());

// A license issued from a public key should also work
let lic_from_pk = License::new(
&attr_data,
&sk_lp,
&LicenseCreator::FromPublicKey(pk),
&mut OsRng,
)
.expect("License correctly computed from public key.");

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

let item = Item {
hash: Hash::digest(Domain::Other, &[lpk.get_u(), lpk.get_v()])[0],
data: (),
};

tree.insert(pos + 1, item);

let merkle_proof = tree.opening(pos + 1).expect("Tree was read successfully");

let (gp, sc) = gadgets::GadgetParameters::compute_parameters(
&sk,
&lic_from_pk,
&pk_lp,
&pk_sp,
&c,
&mut OsRng,
merkle_proof,
)
.expect("Parameters computed correctly.");

let (proof, public_inputs) = prover
.prove(&mut OsRng, &circuit::LicenseCircuit::new(&gp, &sc))
.expect("failed to prove");
verifier
.verify(&proof, &public_inputs)
.expect("failed to verify proof");

assert_eq!(JubJubAffine::from(pk_lp.A()), sc.pk_lp);
assert_eq!(JubJubAffine::from(pk_sp.A()), sc.pk_sp);
assert_eq!(c, sc.c);
assert_eq!(attr_data, sc.attr_data);

let session = Session::from(&public_inputs);
assert_eq!(session.session_id, sc.session_id);
session.verify(sc).expect("Session verified correctly.");
}

0 comments on commit a99ed9c

Please sign in to comment.