Skip to content

Commit

Permalink
Add documentation and simplify API.
Browse files Browse the repository at this point in the history
  • Loading branch information
isislovecruft committed Jun 18, 2020
1 parent 23a6292 commit 28f159c
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 61 deletions.
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,57 @@ I'm likely not _your_ cryptographer. Use at your own risk.
Usage
-------

XXX
```rust
extern crate aeonflux;
extern crate curve25519_dalek;
extern crate rand;

use aeonflux::amacs::Attribute;
use aeonflux::issuer::Issuer;
use aeonflux::parameters::IssuerParameters;
use aeonflux::parameters::SystemParameters;
use aeonflux::symmetric::Plaintext;
use aeonflux::symmetric::Keypair as SymmetricKeypair;

use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;

use rand::thread_rng;

// First we set up an anonymous credential issuer. We have to specify
// the number of attributes the credentials will have (here, eight),
// but not their type.
let mut rng = thread_rng();
let system_parameters = SystemParameters::generate(&mut rng, 8).unwrap();
let issuer = Issuer::new(&system_parameters, &mut rng);

// Our user creates a request for a new credential with some revealed
// attributes and sends it to the issuer.
let plaintext: Plaintext = b"This is a tsunami alert test..".into();

let mut attributes = Vec::new();

attributes.push(Attribute::SecretPoint(plaintext));
attributes.push(Attribute::SecretScalar(Scalar::random(&mut rng)));
attributes.push(Attribute::SecretScalar(Scalar::random(&mut rng)));
attributes.push(Attribute::PublicScalar(Scalar::random(&mut rng)));
attributes.push(Attribute::PublicPoint(RistrettoPoint::random(&mut rng)));
attributes.push(Attribute::SecretScalar(Scalar::random(&mut rng)));
attributes.push(Attribute::PublicScalar(Scalar::random(&mut rng)));
attributes.push(Attribute::PublicPoint(RistrettoPoint::random(&mut rng)));

let credential = issuer.issue(attributes, &mut rng).unwrap();

// Optionally, upon showing the credential, the user can create a
// keypair and encrypt some or all of the attributes. The master secret
// can be stored to regenerate the full keypair later on. Encryption
// keys can be rotated to rerandomise the encrypted attributes.
let (keypair, master_secret) = SymmetricKeypair::generate(&system_parameters, &mut rng);
let proof = credential.show(&system_parameters, &issuer.issuer_parameters, Some(&keypair), &mut rng);

assert!(proof.is_ok());

let verification = proof.unwrap().verify(&issuer, &credential);

assert!(verification.is_ok());
```
59 changes: 49 additions & 10 deletions src/amacs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ use crate::errors::MacError;
use crate::parameters::SystemParameters;
use crate::symmetric::Plaintext;

/// Determine the size of a [`SecretKey`], in bytes.
pub(crate) fn sizeof_secret_key(number_of_attributes: u8) -> usize {
32 * (6 + number_of_attributes) as usize
}

/// An AMAC secret key is \(( (w, w', x_0, x_1, \vec{y_{n}}, W ) \in \mathbb{Z}_q \))
/// where \(( W := G_w * w \)). (The \(( G_w \)) is one of the orthogonal generators
/// from the [`SystemParameters`].)
Expand Down Expand Up @@ -101,12 +106,12 @@ impl SecretKey {
}

/// DOCDOC
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, MacError> {
pub(crate) fn from_bytes(bytes: &[u8]) -> Result<SecretKey, MacError> {
unimplemented!()
}

/// DOCDOC
pub fn to_bytes(&self) -> Vec<u8> {
pub(crate) fn to_bytes(&self) -> Vec<u8> {
unimplemented!()
}
}
Expand All @@ -120,20 +125,54 @@ impl_serde_with_to_bytes_and_from_bytes!(SecretKey, "A valid byte sequence repre
/// When a `Credential` is shown, its attributes may be either revealed or
/// hidden from the credential issuer. These represent all the valid attribute
/// types.
#[derive(Clone)]
pub enum Attribute {
/// A scalar attribute which is revealed upon credential presentation.
PublicScalar(Scalar),
/// A scalar attribute which is hidden upon credential presentation.
SecretScalar(Scalar),
/// A group element attribute which is revealed upon credential presentation.
PublicPoint(RistrettoPoint),
/// A group element attribute which is hidden upon credential presentation.
SecretPoint(Plaintext),
}

// XXX impl Drop for Attribute?
// We can't derive this because generally in elliptic curve cryptography group
// elements aren't used as secrets, thus curve25519-dalek doesn't impl Zeroize
// for RistrettoPoint.
impl Zeroize for Attribute {
fn zeroize(&mut self) {
match self {
Attribute::SecretScalar(x) => x.zeroize(),
Attribute::SecretPoint(x) => x.zeroize(),
_ => return,
}
}
}

/// Overwrite the secret attributes with zeroes (and the identity element)
/// when it drops out of scope.
impl Drop for Attribute {
fn drop(&mut self) {
self.zeroize();
}
}

/// DOCDOC

/// These are the form of the attributes during credential presentation, when
/// some may be be hidden either by commiting to them and proving them in
/// zero-knowledge (as is the case for hidden scalar attributes) or by
/// encrypting them and proving the ciphertext's validity in zero-knowledge (as
/// is the case for the hidden group element attributes).
#[derive(Clone)]
pub enum EncryptedAttribute {
/// A scalar attribute which is revealed upon credential presentation.
PublicScalar(Scalar),
/// A scalar attribute which is hidden upon credential presentation.
SecretScalar,
/// A group element attribute which is revealed upon credential presentation.
PublicPoint(RistrettoPoint),
/// A group element attribute which is hidden upon credential presentation.
SecretPoint,
}

Expand Down Expand Up @@ -163,10 +202,10 @@ impl Messages {
}

/// An algebraic message authentication code, \(( (t,U,V) \in \mathbb{Z}_q \times \mathbb{G} \times \mathbb{G} \)).
pub struct Amac {
pub t: Scalar,
pub U: RistrettoPoint,
pub V: RistrettoPoint,
pub(crate) struct Amac {
pub(crate) t: Scalar,
pub(crate) U: RistrettoPoint,
pub(crate) V: RistrettoPoint,
}

impl Amac {
Expand All @@ -191,7 +230,7 @@ impl Amac {

/// Compute an algebraic message authentication code with a secret key for a
/// vector of messages.
pub fn tag<R>(
pub(crate) fn tag<R>(
csprng: &mut R,
system_parameters: &SystemParameters,
secret_key: &SecretKey,
Expand All @@ -213,7 +252,7 @@ impl Amac {
}

/// Verify this algebraic MAC w.r.t. a secret key and vector of messages.
pub fn verify(
pub(crate) fn verify(
&self,
system_parameters: &SystemParameters,
secret_key: &SecretKey,
Expand Down
25 changes: 25 additions & 0 deletions src/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,35 @@ use alloc::vec::Vec;
#[cfg(all(not(feature = "alloc"), feature = "std"))]
use std::vec::Vec;

use rand_core::CryptoRng;
use rand_core::RngCore;

use crate::amacs::Amac;
use crate::amacs::Attribute;
use crate::errors::CredentialError;
use crate::parameters::IssuerParameters;
use crate::parameters::SystemParameters;
use crate::nizk::ProofOfValidCredential;
use crate::symmetric::Keypair as SymmetricKeypair;

/// An anonymous credential.
pub struct AnonymousCredential {
pub(crate) amac: Amac,
pub(crate) attributes: Vec<Attribute>,
}

impl AnonymousCredential {
/// Present this credential to an issuer.
pub fn show<C>(
&self,
system_parameters: &SystemParameters,
issuer_parameters: &IssuerParameters,
keypair: Option<&SymmetricKeypair>,
csprng: &mut C,
) -> Result<ProofOfValidCredential, CredentialError>
where
C: CryptoRng + RngCore,
{
ProofOfValidCredential::prove(&system_parameters, &issuer_parameters, &self, keypair, csprng)
}
}
4 changes: 3 additions & 1 deletion src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// Authors:
// - isis agora lovecruft <[email protected]>

//! Errors which may occur during anonymous credential issuance and verification.
#[cfg(feature = "std")]
use std::convert::From;
#[cfg(feature = "std")]
Expand All @@ -32,7 +34,7 @@ use core::option::NoneError;
use zkp::ProofError;

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum MacError {
pub(crate) enum MacError {
KeypairDeserialisation,
PointDecompressionError,
ScalarFormatError,
Expand Down
61 changes: 56 additions & 5 deletions src/issuer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ use std::vec::Vec;
use rand_core::CryptoRng;
use rand_core::RngCore;

use serde::de::Deserialize;
use serde::de::Deserializer;
use serde::de::Visitor;
use serde::ser::Serialize;
use serde::ser::Serializer;

use crate::amacs::sizeof_secret_key;
use crate::amacs::Amac;
use crate::amacs::Attribute;
use crate::amacs::SecretKey;
use crate::credential::AnonymousCredential;
use crate::errors::CredentialError;
use crate::parameters::sizeof_system_parameters;
use crate::parameters::IssuerParameters;
use crate::parameters::SystemParameters;

Expand All @@ -33,16 +41,30 @@ pub struct Issuer {
}

impl Issuer {
pub fn new(
/// Create a new anonymous credential issuer and verifier.
///
/// # Inputs
///
/// * Some previously generated [`SystemParameters`].
/// * A cryptographically secure PRNG.
///
/// # Returns
///
/// An new issuer.
pub fn new<C>(
system_parameters: &SystemParameters,
issuer_parameters: &IssuerParameters,
amacs_key: &SecretKey
csprng: &mut C,
) -> Issuer
where
C: CryptoRng + RngCore,
{
let amacs_key = SecretKey::generate(csprng, &system_parameters);
let issuer_parameters = IssuerParameters::generate(&system_parameters, &amacs_key);

Issuer {
system_parameters: system_parameters.clone(),
issuer_parameters: issuer_parameters.clone(),
amacs_key: amacs_key.clone(),
issuer_parameters: issuer_parameters,
amacs_key: amacs_key,
}
}

Expand Down Expand Up @@ -76,3 +98,32 @@ impl Issuer {
}
}
}

impl Issuer {
/// Create an [`Issuer`] from bytes.
pub fn from_bytes(bytes: &[u8]) -> Result<Issuer, CredentialError> {
let system_parameters = SystemParameters::from_bytes(&bytes)?;
let offset = sizeof_system_parameters(system_parameters.NUMBER_OF_ATTRIBUTES);
let issuer_parameters = IssuerParameters::from_bytes(&bytes[offset..offset+64])?;
let amacs_key = SecretKey::from_bytes(&bytes[offset+64..])?;

Ok(Issuer { system_parameters, issuer_parameters, amacs_key })
}

/// Serialise this [`Issuer`] to a byte array.
pub fn to_bytes(&self) -> Vec<u8> {
let size = 64 +
sizeof_system_parameters(self.system_parameters.NUMBER_OF_ATTRIBUTES) +
sizeof_secret_key(self.system_parameters.NUMBER_OF_ATTRIBUTES);

let mut bytes: Vec<u8> = Vec::with_capacity(size);

bytes.extend(self.system_parameters.to_bytes());
bytes.extend(self.issuer_parameters.to_bytes());
bytes.extend(self.amacs_key.to_bytes());

bytes
}
}

impl_serde_with_to_bytes_and_from_bytes!(Issuer, "A valid byte sequence representing an Issuer");
15 changes: 12 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@

#![no_std]

#![cfg_attr(feature = "nightly", feature(external_doc))]
#![cfg_attr(feature = "nightly", feature(doc_cfg))]

// Refuse to compile if documentation is missing, but only on nightly.
//
// This means that missing docs will still fail CI, but means we can use
// README.md as the crate documentation.
//#![cfg_attr(feature = "nightly", deny(missing_docs))]

#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]

// TODO Get rid of the syntax that uses the nightly-only try_trait.
#![feature(try_trait)]
// We denote group elements with capital and scalars with lowercased names.
Expand All @@ -35,17 +46,15 @@ extern crate zkp;

// The macros have to come first.
#[macro_use]
pub mod macros;
mod macros;

pub mod amacs;
pub mod credential;
pub mod encoding;
pub mod errors;
pub mod issuer;
pub mod nizk;
//pub mod nonces;
pub mod parameters;
//pub mod pedersen;
pub mod prelude;
pub mod symmetric;
//pub mod user;
1 change: 0 additions & 1 deletion src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// Authors:
// - isis agora lovecruft <[email protected]>

#[macro_export]
macro_rules! impl_serde_with_to_bytes_and_from_bytes {
($t:tt, $expecting:expr) => {
impl Serialize for $t {
Expand Down
Loading

0 comments on commit 28f159c

Please sign in to comment.