Skip to content

Commit

Permalink
Switch from ed25519 representations to a cannonical representation
Browse files Browse the repository at this point in the history
This should make it easier to interact with Ristretto crates like
slingshot.  See  #34  and  #9
  • Loading branch information
burdges committed May 12, 2019
1 parent 6208d44 commit 79486b3
Showing 1 changed file with 55 additions and 29 deletions.
84 changes: 55 additions & 29 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,16 +355,13 @@ impl From<&MiniSecretKey> for SecretKey {
}

impl SecretKey {
const DESCRIPTION : &'static str = "An ed25519 expanded secret key as 64 bytes, as specified in RFC8032.";
const DESCRIPTION : &'static str = "An ed25519-like expanded secret key as 64 bytes, as specified in RFC8032.";

/// Convert this `SecretKey` into an array of 64 bytes, corresponding to
/// an Ed25519 expanded secreyt key.
///
/// # Returns
/// Convert this `SecretKey` into an array of 64 bytes with.
///
/// An array of 64 bytes. The first 32 bytes represent the "expanded"
/// secret key, and the last 32 bytes represent the "domain-separation"
/// "nonce".
/// Returns an array of 64 bytes, with the first 32 bytes being
/// the secret scalar represented cannonically, and the last
/// 32 bytes being the seed for nonces.
///
/// # Examples
///
Expand All @@ -389,28 +386,13 @@ impl SecretKey {
#[inline]
pub fn to_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
let mut bytes: [u8; 64] = [0u8; 64];
let mut key = self.key.to_bytes();
// We multiply by the cofactor to improve ed25519 compatability,
// while our internally using a scalar mod l.
scalars::multiply_scalar_bytes_by_cofactor(&mut key);
bytes[..32].copy_from_slice(&key[..]);
bytes[..32].copy_from_slice(&self.key.to_bytes()[..]);
bytes[32..].copy_from_slice(&self.nonce[..]);
bytes
}

/// Convert this `SecretKey` into an Ed25519 expanded secreyt key.
pub fn to_ed25519_expanded_secret_key(&self) -> ::ed25519_dalek::ExpandedSecretKey {
::ed25519_dalek::ExpandedSecretKey::from_bytes(&self.to_bytes()[..])
.expect("Improper serialisation of Ed25519 secret key!")
}

/// Construct an `SecretKey` from a slice of bytes.
///
/// # Returns
///
/// A `Result` whose okay value is an EdDSA `SecretKey` or whose
/// error value is an `SignatureError` describing the error that occurred.
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -445,22 +427,66 @@ impl SecretKey {
});
}

let mut key: [u8; 32] = [0u8; 32];
key.copy_from_slice(&bytes[00..32]);
let key = Scalar::from_canonical_bytes(key).ok_or(SignatureError::ScalarFormatError) ?;

let mut nonce: [u8; 32] = [0u8; 32];
nonce.copy_from_slice(&bytes[32..64]);

Ok(SecretKey{ key, nonce })
}

/// Convert this `SecretKey` into an array of 64 bytes, corresponding to
/// an Ed25519 expanded secreyt key.
///
/// Returns an array of 64 bytes, with the first 32 bytes being
/// the secret scalar shifted ed25519 style, and the last 32 bytes
/// being the seed for nonces.
#[inline]
pub fn to_ed25519_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
let mut bytes: [u8; 64] = [0u8; 64];
let mut key = self.key.to_bytes();
// We multiply by the cofactor to improve ed25519 compatability,
// while our internally using a scalar mod l.
scalars::multiply_scalar_bytes_by_cofactor(&mut key);
bytes[..32].copy_from_slice(&key[..]);
bytes[32..].copy_from_slice(&self.nonce[..]);
bytes
}

/// Convert this `SecretKey` into an Ed25519 expanded secreyt key.
pub fn to_ed25519_expanded_secret_key(&self) -> ::ed25519_dalek::ExpandedSecretKey {
::ed25519_dalek::ExpandedSecretKey::from_bytes(&self.to_ed25519_bytes()[..])
.expect("Improper serialisation of Ed25519 secret key!")
}

/// Construct an `SecretKey` from a slice of bytes, corresponding to
/// an Ed25519 expanded secret key.
#[inline]
pub fn from_ed25519_bytes(bytes: &[u8]) -> SignatureResult<SecretKey> {
if bytes.len() != SECRET_KEY_LENGTH {
return Err(SignatureError::BytesLengthError{
name: "SecretKey",
description: SecretKey::DESCRIPTION,
length: SECRET_KEY_LENGTH,
});
}

let mut key: [u8; 32] = [0u8; 32];
key.copy_from_slice(&bytes[00..32]);
// TODO: We should consider making sure the scalar is valid,
// maybe by zering the high bit, orp referably by checking < l.
// maybe by zering the high bit, or preferably by checking < l.
// key[31] &= 0b0111_1111;
// We devide by the cofactor to internally keep a clean
// representation mod l.
scalars::divide_scalar_bytes_by_cofactor(&mut key);
let key = Scalar::from_bits(key);

let mut nonce: [u8; 32] = [0u8; 32];
nonce.copy_from_slice(&bytes[32..64]);

Ok(SecretKey{
key: Scalar::from_bits(key),
nonce,
})
Ok(SecretKey{ key, nonce })
}

/// Generate an "unbiased" `SecretKey` directly, bypassing the
Expand Down

0 comments on commit 79486b3

Please sign in to comment.