Skip to content

Commit

Permalink
Merge pull request #6 from huitseeker/pr/punwai/460
Browse files Browse the repository at this point in the history
Simplify Aggregation a bit
  • Loading branch information
punwai authored Jul 15, 2022
2 parents 76dd5ae + 798120d commit 23b03a4
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 213 deletions.
50 changes: 5 additions & 45 deletions crypto/src/bls12377/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

use std::fmt::{self, Display};

use crate::traits::{AggregateAuthenticator, EncodeDecodeBase64, ToFromBytes, VerifyingKeyBytes};
use crate::{
pubkey_bytes::PublicKeyBytes,
traits::{AggregateAuthenticator, EncodeDecodeBase64, ToFromBytes},
};
use ::ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_bls12_377::{Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_ec::{AffineCurve, ProjectiveCurve};
Expand All @@ -16,7 +19,6 @@ use celo_bls::{hash_to_curve::try_and_increment, PublicKey};
use once_cell::sync::OnceCell;
use serde::{de, Deserialize, Serialize};
use serde_with::serde_as;
use serde_with::Bytes;
use signature::{Signer, Verifier};

use crate::traits::{Authenticator, KeyPair, SigningKey, VerifyingKey};
Expand All @@ -40,10 +42,7 @@ pub struct BLS12377PublicKey {
pub bytes: OnceCell<[u8; CELO_BLS_PUBLIC_KEY_LENGTH]>,
}

#[readonly::make]
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Copy, Hash)]
pub struct BLS12377PublicKeyBytes(#[serde_as(as = "Bytes")] [u8; CELO_BLS_PUBLIC_KEY_LENGTH]);
pub type BLS12377PublicKeyBytes = PublicKeyBytes<BLS12377PublicKey, { BLS12377PublicKey::LENGTH }>;

#[readonly::make]
#[derive(Debug)]
Expand Down Expand Up @@ -261,7 +260,6 @@ impl<'a> From<&'a BLS12377PrivateKey> for BLS12377PublicKey {
impl VerifyingKey for BLS12377PublicKey {
type PrivKey = BLS12377PrivateKey;
type Sig = BLS12377Signature;
type Bytes = BLS12377PublicKeyBytes;
const LENGTH: usize = CELO_BLS_PUBLIC_KEY_LENGTH;

fn verify_batch(msg: &[u8], pks: &[Self], sigs: &[Self::Sig]) -> Result<(), signature::Error> {
Expand Down Expand Up @@ -395,11 +393,6 @@ impl KeyPair for BLS12377KeyPair {
},
}
}

fn public_key_bytes(&self) -> BLS12377PublicKeyBytes {
BLS12377PublicKeyBytes::from_bytes(self.name.as_ref())
.expect("BLS12-377 serialization invariants violated")
}
}

impl Signer<BLS12377Signature> for BLS12377KeyPair {
Expand Down Expand Up @@ -557,26 +550,6 @@ impl AggregateAuthenticator for BLS12377AggregateSignature {
/// Implement VerifyingKeyBytes
///
impl Default for BLS12377PublicKeyBytes {
fn default() -> Self {
BLS12377PublicKeyBytes([0; CELO_BLS_PUBLIC_KEY_LENGTH])
}
}

impl AsRef<[u8]> for BLS12377PublicKeyBytes {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl Display for BLS12377PublicKeyBytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
let s = hex::encode(&self.0);
write!(f, "k#{}", s)?;
Ok(())
}
}

impl TryInto<BLS12377PublicKey> for BLS12377PublicKeyBytes {
type Error = signature::Error;

Expand All @@ -586,16 +559,3 @@ impl TryInto<BLS12377PublicKey> for BLS12377PublicKeyBytes {
BLS12377PublicKey::from_bytes(self.as_ref()).map_err(|_| Self::Error::new())
}
}

impl ToFromBytes for BLS12377PublicKeyBytes {
fn from_bytes(bytes: &[u8]) -> Result<Self, signature::Error> {
let arr: [u8; CELO_BLS_PUBLIC_KEY_LENGTH] =
bytes.try_into().map_err(|_| signature::Error::new())?;

Ok(BLS12377PublicKeyBytes(arr))
}
}

impl VerifyingKeyBytes for BLS12377PublicKeyBytes {
type PubKey = BLS12377PublicKey;
}
49 changes: 3 additions & 46 deletions crypto/src/bls12381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,18 @@ use blst::min_sig as blst;
use once_cell::sync::OnceCell;
use rand::{rngs::OsRng, RngCore};

use crate::serde_helpers::BlsSignature;
use crate::{pubkey_bytes::PublicKeyBytes, serde_helpers::BlsSignature};
use serde::{
de::{self},
Deserialize, Serialize,
};
use serde_with::serde_as;
use serde_with::Bytes;

use signature::{Signature, Signer, Verifier};

use crate::traits::{
AggregateAuthenticator, Authenticator, EncodeDecodeBase64, KeyPair, SigningKey, ToFromBytes,
VerifyingKey, VerifyingKeyBytes,
VerifyingKey,
};

pub const BLS_PRIVATE_KEY_LENGTH: usize = 32;
Expand All @@ -44,10 +43,7 @@ pub struct BLS12381PublicKey {
pub bytes: OnceCell<[u8; BLS_PUBLIC_KEY_LENGTH]>,
}

#[readonly::make]
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Copy, Hash)]
pub struct BLS12381PublicKeyBytes(#[serde_as(as = "Bytes")] [u8; BLS_PUBLIC_KEY_LENGTH]);
pub type BLS12381PublicKeyBytes = PublicKeyBytes<BLS12381PublicKey, { BLS12381PublicKey::LENGTH }>;

#[readonly::make]
#[derive(Default, Debug)]
Expand Down Expand Up @@ -186,7 +182,6 @@ impl<'a> From<&'a BLS12381PrivateKey> for BLS12381PublicKey {
impl VerifyingKey for BLS12381PublicKey {
type PrivKey = BLS12381PrivateKey;
type Sig = BLS12381Signature;
type Bytes = BLS12381PublicKeyBytes;

const LENGTH: usize = BLS_PUBLIC_KEY_LENGTH;

Expand Down Expand Up @@ -411,11 +406,6 @@ impl KeyPair for BLS12381KeyPair {
},
}
}

fn public_key_bytes(&self) -> BLS12381PublicKeyBytes {
let pk_arr: [u8; BLS_PUBLIC_KEY_LENGTH] = self.name.pubkey.to_bytes();
BLS12381PublicKeyBytes(pk_arr)
}
}

impl Signer<BLS12381Signature> for BLS12381KeyPair {
Expand Down Expand Up @@ -574,26 +564,6 @@ impl AggregateAuthenticator for BLS12381AggregateSignature {
/// Implement VerifyingKeyBytes
///
impl Default for BLS12381PublicKeyBytes {
fn default() -> Self {
BLS12381PublicKeyBytes([0; BLS_PUBLIC_KEY_LENGTH])
}
}

impl AsRef<[u8]> for BLS12381PublicKeyBytes {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl Display for BLS12381PublicKeyBytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
let s = hex::encode(&self.0);
write!(f, "k#{}", s)?;
Ok(())
}
}

impl TryInto<BLS12381PublicKey> for BLS12381PublicKeyBytes {
type Error = signature::Error;

Expand All @@ -603,16 +573,3 @@ impl TryInto<BLS12381PublicKey> for BLS12381PublicKeyBytes {
BLS12381PublicKey::from_bytes(self.as_ref()).map_err(|_| Self::Error::new())
}
}

impl ToFromBytes for BLS12381PublicKeyBytes {
fn from_bytes(bytes: &[u8]) -> Result<Self, signature::Error> {
let arr: [u8; BLS_PUBLIC_KEY_LENGTH] =
bytes.try_into().map_err(|_| signature::Error::new())?;

Ok(BLS12381PublicKeyBytes(arr))
}
}

impl VerifyingKeyBytes for BLS12381PublicKeyBytes {
type PubKey = BLS12381PublicKey;
}
46 changes: 3 additions & 43 deletions crypto/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use signature::{Signature, Signer, Verifier};
use std::fmt::{self, Display};
use std::str::FromStr;

use crate::pubkey_bytes::PublicKeyBytes;
use crate::traits::{
AggregateAuthenticator, Authenticator, EncodeDecodeBase64, KeyPair, SigningKey, ToFromBytes,
VerifyingKey, VerifyingKeyBytes,
VerifyingKey,
};

///
Expand All @@ -20,8 +21,7 @@ use crate::traits::{
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ed25519PublicKey(pub ed25519_dalek::PublicKey);

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd, Copy, Hash)]
pub struct Ed25519PublicKeyBytes([u8; ed25519_dalek::PUBLIC_KEY_LENGTH]);
pub type Ed25519PublicKeyBytes = PublicKeyBytes<Ed25519PublicKey, { Ed25519PublicKey::LENGTH }>;

#[derive(Debug)]
pub struct Ed25519PrivateKey(pub ed25519_dalek::SecretKey);
Expand Down Expand Up @@ -59,7 +59,6 @@ impl<'a> From<&'a Ed25519PrivateKey> for Ed25519PublicKey {
impl VerifyingKey for Ed25519PublicKey {
type PrivKey = Ed25519PrivateKey;
type Sig = Ed25519Signature;
type Bytes = Ed25519PublicKeyBytes;
const LENGTH: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;

fn verify_batch(msg: &[u8], pks: &[Self], sigs: &[Self::Sig]) -> Result<(), signature::Error> {
Expand Down Expand Up @@ -346,11 +345,6 @@ impl KeyPair for Ed25519KeyPair {
secret: Ed25519PrivateKey(kp.secret),
}
}

fn public_key_bytes(&self) -> Ed25519PublicKeyBytes {
let pk_arr: [u8; ed25519_dalek::PUBLIC_KEY_LENGTH] = self.name.0.to_bytes();
Ed25519PublicKeyBytes(pk_arr)
}
}

impl FromStr for Ed25519KeyPair {
Expand Down Expand Up @@ -388,27 +382,6 @@ impl Signer<Ed25519Signature> for Ed25519KeyPair {
///
/// Implement VerifyingKeyBytes
///
impl Default for Ed25519PublicKeyBytes {
fn default() -> Self {
Ed25519PublicKeyBytes([0; ed25519_dalek::PUBLIC_KEY_LENGTH])
}
}

impl AsRef<[u8]> for Ed25519PublicKeyBytes {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl Display for Ed25519PublicKeyBytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
let s = hex::encode(&self.0);
write!(f, "k#{}", s)?;
Ok(())
}
}

impl TryInto<Ed25519PublicKey> for Ed25519PublicKeyBytes {
type Error = signature::Error;

Expand All @@ -418,16 +391,3 @@ impl TryInto<Ed25519PublicKey> for Ed25519PublicKeyBytes {
Ed25519PublicKey::from_bytes(self.as_ref()).map_err(|_| Self::Error::new())
}
}

impl ToFromBytes for Ed25519PublicKeyBytes {
fn from_bytes(bytes: &[u8]) -> Result<Self, signature::Error> {
let arr: [u8; ed25519_dalek::PUBLIC_KEY_LENGTH] =
bytes.try_into().map_err(|_| signature::Error::new())?;

Ok(Ed25519PublicKeyBytes(arr))
}
}

impl VerifyingKeyBytes for Ed25519PublicKeyBytes {
type PubKey = Ed25519PublicKey;
}
63 changes: 63 additions & 0 deletions crypto/src/hkdf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
use crate::traits::{KeyPair, SigningKey, ToFromBytes, DEFAULT_DOMAIN};
use digest::{
block_buffer::Eager,
consts::U256,
core_api::{BlockSizeUser, BufferKindUser, CoreProxy, FixedOutputCore, UpdateCore},
typenum::{IsLess, Le, NonZero, Unsigned},
HashMarker, OutputSizeUser,
};
use hkdf::hmac::Hmac;

/// Creation of a keypair using the [RFC 5869](https://tools.ietf.org/html/rfc5869) HKDF specification.
/// This requires choosing an HMAC function of the correct length (conservatively, the size of a private key for this curve).
/// Despite the unsightly generics (which aim to ensure this works for a wide range of hash functions), this is straightforward to use.
///
/// Example:
/// ```rust
/// use sha3::Sha3_256;
/// use crypto::ed25519::Ed25519KeyPair;
/// use crypto::traits::hkdf_generate_from_ikm;
/// # fn main() {
/// let ikm = b"some_ikm";
/// let domain = b"my_app";
/// let salt = b"some_salt";
/// let my_keypair = hkdf_generate_from_ikm::<Sha3_256, Ed25519KeyPair>(ikm, salt, Some(domain));
///
/// let my_keypair_default_domain = hkdf_generate_from_ikm::<Sha3_256, Ed25519KeyPair>(ikm, salt, None);
/// # }
/// ```
pub fn hkdf_generate_from_ikm<'a, H: OutputSizeUser, K: KeyPair>(
ikm: &[u8], // IKM (32 bytes)
salt: &[u8], // Optional salt
info: Option<&'a [u8]>, // Optional domain
) -> Result<K, signature::Error>
where
// This is a tad tedious, because of hkdf's use of a sealed trait. But mostly harmless.
H: CoreProxy + OutputSizeUser,
H::Core: HashMarker
+ UpdateCore
+ FixedOutputCore
+ BufferKindUser<BufferKind = Eager>
+ Default
+ Clone,
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
let info = info.unwrap_or(&DEFAULT_DOMAIN);
let hk = hkdf::Hkdf::<H, Hmac<H>>::new(Some(salt), ikm);
// we need the HKDF to be able to expand precisely to the byte length of a Private key for the chosen KeyPair parameter.
// This check is a tad over constraining (check Hkdf impl for a more relaxed variant) but is always correct.
if H::OutputSize::USIZE != K::PrivKey::LENGTH {
return Err(signature::Error::from_source(hkdf::InvalidLength));
}
let mut okm = vec![0u8; K::PrivKey::LENGTH];
hk.expand(info, &mut okm)
.map_err(|_| signature::Error::new())?;

let secret_key = K::PrivKey::from_bytes(&okm[..]).map_err(|_| signature::Error::new())?;

let keypair = K::from(secret_key);
Ok(keypair)
}
2 changes: 2 additions & 0 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub mod bls12381_tests;

pub mod bls12381;
pub mod ed25519;
pub mod hkdf;
pub mod pubkey_bytes;
pub mod serde_helpers;
pub mod traits;

Expand Down
Loading

0 comments on commit 23b03a4

Please sign in to comment.