mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-23 14:54:45 +00:00
Improve bls::SecretKey privacy (#1164)
* Improve bls::SecretKey privacy * Add missed file * Remove more methods from bls::SecretKey * Add as_bytes() to SecretKey, remove as_raw * Remove as_raw * Add back as_raw * Address review comments
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
use super::{PublicKey, SecretKey};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone)]
|
||||
pub struct Keypair {
|
||||
pub sk: SecretKey,
|
||||
pub pk: PublicKey,
|
||||
|
||||
@@ -4,6 +4,7 @@ extern crate ssz;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod keypair;
|
||||
mod plain_text;
|
||||
mod public_key_bytes;
|
||||
mod secret_key;
|
||||
mod signature_bytes;
|
||||
@@ -14,6 +15,7 @@ pub use crate::public_key_bytes::PublicKeyBytes;
|
||||
pub use crate::secret_key::SecretKey;
|
||||
pub use crate::signature_bytes::SignatureBytes;
|
||||
pub use milagro_bls::{compress_g2, hash_to_curve_g2};
|
||||
pub use plain_text::PlainText;
|
||||
pub use signature_set::{verify_signature_sets, SignatureSet};
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
|
||||
40
crypto/bls/src/plain_text.rs
Normal file
40
crypto/bls/src/plain_text.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// Provides wrapper around `Vec<u8>` that implements `Zeroize`.
|
||||
#[derive(Zeroize, Clone, PartialEq)]
|
||||
#[zeroize(drop)]
|
||||
pub struct PlainText(Vec<u8>);
|
||||
|
||||
impl PlainText {
|
||||
/// Instantiate self with `len` zeros.
|
||||
pub fn zero(len: usize) -> Self {
|
||||
Self(vec![0; len])
|
||||
}
|
||||
|
||||
/// The byte-length of `self`
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
/// Returns a reference to the underlying bytes.
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the underlying bytes.
|
||||
pub fn as_mut_bytes(&mut self) -> &mut [u8] {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for PlainText {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for PlainText {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,18 @@
|
||||
extern crate rand;
|
||||
|
||||
use super::BLS_SECRET_KEY_BYTE_SIZE;
|
||||
use hex::encode as hex_encode;
|
||||
use crate::PlainText;
|
||||
use milagro_bls::SecretKey as RawSecretKey;
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use serde_hex::PrefixedHexVisitor;
|
||||
use ssz::{ssz_encode, Decode, DecodeError, Encode};
|
||||
use ssz::DecodeError;
|
||||
|
||||
/// A single BLS signature.
|
||||
///
|
||||
/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ
|
||||
/// serialization).
|
||||
#[derive(Debug, PartialEq, Clone, Eq)]
|
||||
#[derive(Clone)]
|
||||
pub struct SecretKey(RawSecretKey);
|
||||
|
||||
impl SecretKey {
|
||||
/// Generate a new `Self` using `rand::thread_rng`.
|
||||
pub fn random() -> Self {
|
||||
SecretKey(RawSecretKey::random(&mut rand::thread_rng()))
|
||||
}
|
||||
@@ -24,9 +21,13 @@ impl SecretKey {
|
||||
Self(raw)
|
||||
}
|
||||
|
||||
/// Returns the underlying point as compressed bytes.
|
||||
fn as_bytes(&self) -> Vec<u8> {
|
||||
self.as_raw().as_bytes()
|
||||
/// Returns the secret key as a byte array (wrapped in `PlainText` wrapper so it is zeroized on
|
||||
/// `Drop`).
|
||||
///
|
||||
/// Extreme care should be taken not to leak these bytes as they are the unencrypted secret
|
||||
/// key.
|
||||
pub fn as_bytes(&self) -> PlainText {
|
||||
self.as_raw().as_bytes().into()
|
||||
}
|
||||
|
||||
/// Instantiate a SecretKey from existing bytes.
|
||||
@@ -42,40 +43,14 @@ impl SecretKey {
|
||||
}
|
||||
|
||||
/// Returns the underlying secret key.
|
||||
pub fn as_raw(&self) -> &RawSecretKey {
|
||||
pub(crate) fn as_raw(&self) -> &RawSecretKey {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl_ssz!(SecretKey, BLS_SECRET_KEY_BYTE_SIZE, "SecretKey");
|
||||
|
||||
impl_tree_hash!(SecretKey, BLS_SECRET_KEY_BYTE_SIZE);
|
||||
|
||||
impl Serialize for SecretKey {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&hex_encode(ssz_encode(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SecretKey {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
|
||||
let secret_key = SecretKey::from_ssz_bytes(&bytes[..])
|
||||
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
|
||||
Ok(secret_key)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ssz::ssz_encode;
|
||||
|
||||
#[test]
|
||||
pub fn test_ssz_round_trip() {
|
||||
@@ -85,9 +60,9 @@ mod tests {
|
||||
];
|
||||
let original = SecretKey::from_bytes(&byte_key).unwrap();
|
||||
|
||||
let bytes = ssz_encode(&original);
|
||||
let decoded = SecretKey::from_ssz_bytes(&bytes).unwrap();
|
||||
let bytes = original.as_bytes();
|
||||
let decoded = SecretKey::from_bytes(bytes.as_ref()).unwrap();
|
||||
|
||||
assert_eq!(original, decoded);
|
||||
assert!(original.as_bytes() == decoded.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user