Skip to content

Commit

Permalink
Wrap SecretArrayFactory internals in a SecretBox
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Jun 19, 2021
1 parent a458dc8 commit 4f4f110
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 25 deletions.
51 changes: 27 additions & 24 deletions umbral-pre/src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,9 @@ impl CanBeZeroizedOnDrop for BackendSecretKey<CurveType> {
}

/// A secret key.
#[derive(Clone)] // No Debug derivation, to avoid exposing the key accidentally.
#[derive(Clone)]
pub struct SecretKey(SecretBox<BackendSecretKey<CurveType>>);

impl PartialEq for SecretKey {
fn eq(&self, other: &Self) -> bool {
self.to_secret_scalar().as_secret() == other.to_secret_scalar().as_secret()
}
}

impl SecretKey {
fn new(sk: BackendSecretKey<CurveType>) -> Self {
Self(SecretBox::new(sk))
Expand Down Expand Up @@ -106,6 +100,13 @@ impl SecretKey {
}
}

#[cfg(test)]
impl PartialEq for SecretKey {
fn eq(&self, other: &Self) -> bool {
self.to_secret_scalar().as_secret() == other.to_secret_scalar().as_secret()
}
}

impl RepresentableAsArray for SecretKey {
type Size = <CurveScalar as RepresentableAsArray>::Size;
}
Expand Down Expand Up @@ -142,7 +143,6 @@ fn digest_for_signing(message: &[u8]) -> BackendDigest {

/// An object used to sign messages.
/// For security reasons cannot be serialized.
// No Debug derivation, to avoid exposing the key accidentally.
#[derive(Clone)]
pub struct Signer(SecretKey);

Expand Down Expand Up @@ -255,14 +255,14 @@ type SecretKeyFactoryDerivedSize = U64; // the size of the derived key (before h

/// This class handles keyring material for Umbral, by allowing deterministic
/// derivation of `SecretKey` objects based on labels.
#[derive(Clone, Copy, PartialEq)] // No Debug derivation, to avoid exposing the key accidentally.
pub struct SecretKeyFactory(GenericArray<u8, SecretKeyFactorySeedSize>);
#[derive(Clone)]
pub struct SecretKeyFactory(SecretBox<GenericArray<u8, SecretKeyFactorySeedSize>>);

impl SecretKeyFactory {
/// Creates a random factory.
pub fn random() -> Self {
let mut bytes = GenericArray::<u8, SecretKeyFactorySeedSize>::default();
OsRng.fill_bytes(&mut bytes);
let mut bytes = SecretBox::new(GenericArray::<u8, SecretKeyFactorySeedSize>::default());
OsRng.fill_bytes(&mut bytes.as_mut_secret());
Self(bytes)
}

Expand All @@ -274,7 +274,7 @@ impl SecretKeyFactory {
.cloned()
.chain(label.iter().cloned())
.collect();
let key = kdf::<SecretKeyFactoryDerivedSize>(&self.0, None, Some(&info));
let key = kdf::<SecretKeyFactoryDerivedSize>(self.0.as_secret(), None, Some(&info));
let scalar = ScalarDigest::new_with_dst(&info)
.chain_bytes(&key)
.finalize();
Expand All @@ -283,20 +283,26 @@ impl SecretKeyFactory {
}
}

#[cfg(test)]
impl PartialEq for SecretKeyFactory {
fn eq(&self, other: &Self) -> bool {
self.0.as_secret() == other.0.as_secret()
}
}

impl RepresentableAsArray for SecretKeyFactory {
type Size = SecretKeyFactorySeedSize;
}

impl SerializableToArray for SecretKeyFactory {
fn to_array(&self) -> GenericArray<u8, Self::Size> {
// TODO (#8): a copy of secret data is created.
self.0
impl SerializableToSecretArray for SecretKeyFactory {
fn to_secret_array(&self) -> SecretBox<GenericArray<u8, Self::Size>> {
self.0.clone()
}
}

impl DeserializableFromArray for SecretKeyFactory {
fn from_array(arr: &GenericArray<u8, Self::Size>) -> Result<Self, ConstructionError> {
Ok(Self(*arr))
Ok(Self(SecretBox::new(*arr)))
}
}

Expand All @@ -323,17 +329,14 @@ mod tests {
let sk = SecretKey::random();
let sk_arr = sk.to_secret_array();
let sk_back = SecretKey::from_array(sk_arr.as_secret()).unwrap();
assert_eq!(
sk.to_secret_scalar().as_secret(),
sk_back.to_secret_scalar().as_secret()
);
assert!(sk == sk_back);
}

#[test]
fn test_serialize_secret_key_factory() {
let skf = SecretKeyFactory::random();
let skf_arr = skf.to_array();
let skf_back = SecretKeyFactory::from_array(&skf_arr).unwrap();
let skf_arr = skf.to_secret_array();
let skf_back = SecretKeyFactory::from_array(skf_arr.as_secret()).unwrap();
assert!(skf == skf_back);
}

Expand Down
6 changes: 5 additions & 1 deletion umbral-pre/src/secret_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ where
/// Makes the usage of secret data explicit and easy to track,
/// prevents the secret data from being put on stack,
/// and zeroizes the contents on drop.
#[derive(Clone)]
#[derive(Clone)] // No Debug derivation, to avoid exposing the secret data accidentally.
pub struct SecretBox<T>(Box<T>)
where
T: CanBeZeroizedOnDrop + Clone;
Expand All @@ -77,6 +77,10 @@ where
pub fn as_secret(&self) -> &T {
self.0.as_ref()
}

pub fn as_mut_secret(&mut self) -> &mut T {
self.0.as_mut()
}
}

impl<T> Drop for SecretBox<T>
Expand Down

0 comments on commit 4f4f110

Please sign in to comment.