Skip to content

Commit

Permalink
Merge pull request #158 from iotaledger/feat/account-crypto
Browse files Browse the repository at this point in the history
Composable Crypto
  • Loading branch information
l1h3r authored Mar 18, 2021
2 parents 4b545ff + e8009f4 commit 6d7edc4
Show file tree
Hide file tree
Showing 25 changed files with 712 additions and 650 deletions.
3 changes: 1 addition & 2 deletions identity-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ homepage = "https://www.iota.org"
base64 = { version = "0.13", default-features = false, features = ["std"] }
bs58 = { version = "0.4", default-features = false, features = ["std"] }
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
erased-serde = { version = "0.3", default-features = false, features = ["alloc"] }
hex = { version = "0.4", default-features = false }
identity-diff = { version = "=0.2.0", path = "../identity-diff", default-features = false }
roaring = { version = "0.6", default-features = false }
Expand All @@ -29,7 +28,7 @@ zeroize = { version = "1.2", default-features = false }

[dependencies.iota-crypto]
git = "https://github.com/iotaledger/crypto.rs"
rev = "c3bf565eba62d0b81144174c2ff917bfde282e49"
rev = "b849861b86c3f7357b7477de4253b7352b363627"
default-features = false
features = ["blake2b", "ed25519", "random", "sha"]

Expand Down
14 changes: 7 additions & 7 deletions identity-core/src/convert/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
use crypto::hashes::sha::Sha256;
use crypto::hashes::Digest;
use crypto::hashes::Output;
use erased_serde::Serialize;
use serde::Deserialize;
use serde::Serialize;

use crate::error::Error;
use crate::error::Result;
Expand All @@ -14,28 +14,28 @@ use crate::error::Result;
pub trait ToJson: Serialize + Sized {
/// Serialize `self` as a string of JSON.
fn to_json(&self) -> Result<String> {
serde_json::to_string(self as &dyn Serialize).map_err(Error::EncodeJSON)
serde_json::to_string(self).map_err(Error::EncodeJSON)
}

/// Serialize `self` as a JSON byte vector.
fn to_json_vec(&self) -> Result<Vec<u8>> {
serde_json::to_vec(self as &dyn Serialize).map_err(Error::EncodeJSON)
serde_json::to_vec(self).map_err(Error::EncodeJSON)
}

/// Serialize `self` as a [`serde_json::Value`].
fn to_json_value(&self) -> Result<serde_json::Value> {
serde_json::to_value(self as &dyn Serialize).map_err(Error::EncodeJSON)
serde_json::to_value(self).map_err(Error::EncodeJSON)
}

/// Serialize `self` as a pretty-printed string of JSON.
fn to_json_pretty(&self) -> Result<String> {
serde_json::to_string_pretty(self as &dyn Serialize).map_err(Error::EncodeJSON)
serde_json::to_string_pretty(self).map_err(Error::EncodeJSON)
}

/// Serialize `self` as a JSON byte vector, normalized using JSON
/// Canonicalization Scheme (JCS).
fn to_jcs(&self) -> Result<Vec<u8>> {
serde_jcs::to_vec(self as &dyn Serialize).map_err(Error::EncodeJSON)
serde_jcs::to_vec(self).map_err(Error::EncodeJSON)
}

/// Returns the given `data` serialized using JSON Canonicalization Scheme and
Expand All @@ -45,7 +45,7 @@ pub trait ToJson: Serialize + Sized {
}
}

impl<T> ToJson for T where T: serde::Serialize {}
impl<T> ToJson for T where T: Serialize {}

// =============================================================================
// =============================================================================
Expand Down
36 changes: 10 additions & 26 deletions identity-core/src/crypto/key/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ use core::slice::Iter;
use core::slice::SliceIndex;
use std::vec::IntoIter;

use crate::crypto::merkle_key::DynSigner;
use crate::crypto::merkle_key::DynVerifier;
use crate::crypto::merkle_key::MerkleDigest;
use crate::crypto::merkle_key::SigningKey;
use crate::crypto::merkle_tree::compute_merkle_proof;
use crate::crypto::merkle_tree::compute_merkle_root;
use crate::crypto::merkle_tree::DigestExt;
use crate::crypto::merkle_tree::Hash;
use crate::crypto::merkle_tree::Proof;
use crate::crypto::JcsEd25519Signature2020 as Ed25519;
use crate::crypto::KeyPair;
use crate::crypto::KeyRef;
use crate::crypto::KeyType;
Expand Down Expand Up @@ -147,40 +145,26 @@ impl KeyCollection {
compute_merkle_proof(&self.public, index)
}

/// Returns a Merkle Key [`Signer`][`DynSigner`] for the secret key at the
/// specified index.
pub fn merkle_key_signer<'key, D>(&'key self, index: usize) -> Option<DynSigner<'static, 'key, D>>
/// Returns a Merkle Key [`SigningKey`] for the key pair at the
/// specified `index`.
pub fn merkle_key<D>(&self, index: usize) -> Option<SigningKey<'_, D>>
where
D: MerkleDigest,
{
match self.type_() {
KeyType::Ed25519 => {
let proof: Proof<D> = self.merkle_proof(index)?;
let public: &'key PublicKey = self.public(index)?;
let proof: Proof<D> = self.merkle_proof(index)?;
let public: &PublicKey = self.public(index)?;
let secret: &SecretKey = self.secret(index)?;

Some(DynSigner::from_owned(Box::new(Ed25519), public, proof))
}
}
}

/// Returns a Merkle Key [`Verifier`][`DynVerifier`] for the Merkle root of
/// the key collection.
pub fn merkle_key_verifier<D>(&self) -> DynVerifier<'static, D>
where
D: MerkleDigest,
{
match self.type_() {
KeyType::Ed25519 => DynVerifier::from_owned(self.encode_key::<D>(), Box::new(Ed25519)),
}
Some(SigningKey::from_owned(public, secret, proof))
}

/// Creates a DID Document public key value for the Merkle root of
/// the key collection.
pub fn encode_key<D>(&self) -> Vec<u8>
pub fn encode_merkle_key<D>(&self) -> Vec<u8>
where
D: MerkleDigest,
{
self.type_.encode_key::<D>(&self.merkle_root())
self.type_.encode_merkle_key::<D>(&self.merkle_root())
}
}

Expand Down
8 changes: 4 additions & 4 deletions identity-core/src/crypto/key/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use core::str::FromStr;
use crate::crypto::merkle_key::MerkleDigest;
use crate::crypto::merkle_key::MerkleKey;
use crate::crypto::merkle_tree::Hash;
use crate::crypto::JcsEd25519Signature2020 as Ed25519;
use crate::crypto::Ed25519;
use crate::error::Error;
use crate::error::Result;

Expand All @@ -26,13 +26,13 @@ impl KeyType {
}
}

/// Creates a DID Document public key value for the given Merkle tree `root`.
pub fn encode_key<D>(&self, root: &Hash<D>) -> Vec<u8>
/// Creates a DID Document public key value for the given Merkle `root`.
pub fn encode_merkle_key<D>(&self, root: &Hash<D>) -> Vec<u8>
where
D: MerkleDigest,
{
match self {
Self::Ed25519 => MerkleKey::encode_key::<_, D>(&Ed25519, root),
Self::Ed25519 => MerkleKey::encode_key::<D, Ed25519>(root),
}
}
}
Expand Down
59 changes: 32 additions & 27 deletions identity-core/src/crypto/merkle_key/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::crypto::merkle_key::MerkleDigest;
use crate::crypto::merkle_key::MerkleSignature;
use crate::crypto::merkle_key::MerkleTag;
use crate::crypto::merkle_tree::Hash;
use crate::crypto::JcsEd25519Signature2020 as Ed25519;
use crate::error::Error;
use crate::error::Result;

Expand All @@ -22,35 +21,26 @@ impl MerkleKey {

/// Extracts the signature and digest algorithm tags from the public key value.
pub fn extract_tags(data: &[u8]) -> Result<(MerkleTag, MerkleTag)> {
let tag_s: MerkleTag = Self::__tag(data, 0)?;
let tag_d: MerkleTag = Self::__tag(data, 1)?;
let tag_s: MerkleTag = Self::tag(data, 0)?;
let tag_d: MerkleTag = Self::tag(data, 1)?;

Ok((tag_s, tag_d))
}

/// Creates a DID Document public key value for the given Merkle tree `root`.
pub fn encode_key<S, D>(suite: &S, root: &Hash<D>) -> Vec<u8>
pub fn encode_key<D, S>(root: &Hash<D>) -> Vec<u8>
where
S: MerkleSignature,
D: MerkleDigest,
S: MerkleSignature,
{
let mut output: Vec<u8> = Vec::with_capacity(2 + D::OUTPUT_SIZE);
output.push(suite.tag().into());
output.push(D::new().tag().into());
output.push(S::TAG.into());
output.push(D::TAG.into());
output.extend_from_slice(root.as_slice());
output
}

/// Creates a DID Document public key value for the given Merkle tree `root`
/// with `Ed25519` as the signature algorithm.
pub fn encode_ed25519_key<D>(root: &Hash<D>) -> Vec<u8>
where
D: MerkleDigest,
{
Self::encode_key(&Ed25519, root)
}

fn __tag(data: &[u8], index: usize) -> Result<MerkleTag> {
fn tag(data: &[u8], index: usize) -> Result<MerkleTag> {
data
.get(index)
.copied()
Expand All @@ -61,21 +51,36 @@ impl MerkleKey {

#[cfg(test)]
mod tests {
use crypto::hashes::sha::Sha256;

use crate::crypto::merkle_key::Blake2b256;
use crate::crypto::merkle_key::MerkleDigest;
use crate::crypto::merkle_key::MerkleKey;
use crate::crypto::merkle_key::MerkleSignature;
use crate::crypto::merkle_key::MerkleTag;
use crate::crypto::merkle_tree::Digest;
use crate::crypto::merkle_tree::DigestExt;
use crate::crypto::merkle_key::Sha256;
use crate::crypto::merkle_tree::Hash;
use crate::crypto::Ed25519;

#[test]
fn test_tags() {
let root: Hash<Sha256> = Sha256::new().hash_leaf(b"Merkle Key Collection");
let data: Vec<u8> = MerkleKey::encode_ed25519_key::<Sha256>(&root);
fn assert_tag<D, S>()
where
D: MerkleDigest,
S: MerkleSignature,
{
let mut digest: D = D::new();
let root: Hash<D> = digest.hash_leaf(b"Merkle Key Collection");
let data: Vec<u8> = MerkleKey::encode_key::<D, S>(&root);
let tags: (MerkleTag, MerkleTag) = MerkleKey::extract_tags(&data).unwrap();

assert_eq!(tags.0, MerkleTag::ED25519);
assert_eq!(tags.1, MerkleTag::SHA256);
assert_eq!(tags.0, S::TAG);
assert_eq!(tags.1, D::TAG);
}

#[test]
fn test_blake2b_tag() {
assert_tag::<Blake2b256, Ed25519>();
}

#[test]
fn test_sha256_tag() {
assert_tag::<Sha256, Ed25519>();
}
}
41 changes: 5 additions & 36 deletions identity-core/src/crypto/merkle_key/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,19 @@ pub use crypto::hashes::blake2b::Blake2b256;
use crate::crypto::merkle_key::MerkleDigest;
use crate::crypto::merkle_key::MerkleSignature;
use crate::crypto::merkle_key::MerkleTag;
use crate::crypto::JcsEd25519Signature2020;
use crate::crypto::KeyRef;
use crate::crypto::KeyType;
use crate::crypto::Ed25519;

// Add support for using SHA-256 as a Merkle Key Collection digest algorithm.
impl MerkleDigest for Sha256 {
fn tag(&self) -> MerkleTag {
MerkleTag::SHA256
}
const TAG: MerkleTag = MerkleTag::SHA256;
}

// Add support for using Blake2b-256 as a Merkle Key Collection digest algorithm.
impl MerkleDigest for Blake2b256 {
fn tag(&self) -> MerkleTag {
MerkleTag::BLAKE2B_256
}
const TAG: MerkleTag = MerkleTag::BLAKE2B_256;
}

// Add support for using Ed25519 as a Merkle Key Collection signature algorithm.
//
// Note that we use the `JcsEd25519Signature2020` type which implements the
// exact same signature algorithm as the Merkle Key Collection spec - other
// implementations may not be so fortunate.
impl MerkleSignature for JcsEd25519Signature2020 {
fn tag(&self) -> MerkleTag {
MerkleTag::ED25519
}
}

// Add an implementation for `KeyType` because we know the signature type.
//
// TODO: May need to expand this if/when `KeyType` has values we don't want
// to support with Merkle Key Collections
impl MerkleSignature for KeyType {
fn tag(&self) -> MerkleTag {
match self {
Self::Ed25519 => MerkleTag::ED25519,
}
}
}

// Add an implementation for `KeyRef` - we just delegate to the key type.
impl<'key> MerkleSignature for KeyRef<'key> {
fn tag(&self) -> MerkleTag {
self.kty().tag()
}
impl<T: ?Sized> MerkleSignature for Ed25519<T> {
const TAG: MerkleTag = MerkleTag::ED25519;
}
12 changes: 7 additions & 5 deletions identity-core/src/crypto/merkle_key/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@
mod base;
mod impls;
mod signer;
mod tag;
mod traits;
mod verifier;

pub use self::base::MerkleKey;
pub use self::impls::Blake2b256;
pub use self::impls::Sha256;
pub use self::signer::DynSigner;
pub use self::signer::Signer;
pub use self::signer::MerkleSigner;
pub use self::signer::MerkleSigningKey;
pub use self::signer::SigningKey;
pub use self::tag::MerkleTag;
pub use self::traits::MerkleDigest;
pub use self::traits::MerkleSignature;
pub use self::traits::MerkleTag;
pub use self::verifier::DynVerifier;
pub use self::verifier::Verifier;
pub use self::verifier::MerkleVerifier;
pub use self::verifier::VerificationKey;

#[cfg(test)]
mod tests;
Loading

0 comments on commit 6d7edc4

Please sign in to comment.