Skip to content

Commit effb1b1

Browse files
feat(age): add Identity::from_secret_bytes
1 parent 2094f60 commit effb1b1

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

age/src/x25519.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ impl Identity {
6262
Identity(StaticSecret::random_from_rng(rng))
6363
}
6464

65+
/// Deserializes this secret key from a 32-byte array.
66+
///
67+
/// # Security
68+
///
69+
/// The `bytes` argument **must** be a high-entropy value, such as a key generated by a CSPRNG
70+
/// or derived from a high-entropy seed (e.g. using BIP39 or scrypt).
71+
///
72+
/// **Do not** use this method with low-entropy input (like a simple string cast to bytes),
73+
/// as this will result in a weak key that is trivial to crack.
74+
pub fn from_secret_bytes(bytes: [u8; 32]) -> Self {
75+
Identity(StaticSecret::from(bytes))
76+
}
77+
6578
/// Serializes this secret key as a string.
6679
pub fn to_string(&self) -> SecretString {
6780
let mut sk_bytes = self.0.to_bytes();
@@ -263,6 +276,14 @@ pub(crate) mod tests {
263276
assert_eq!(key.to_public().to_string(), TEST_PK);
264277
}
265278

279+
#[test]
280+
fn identity_from_secret_bytes() {
281+
let (_, bytes) = crate::util::parse_bech32(TEST_SK).expect("TEST_SK is valid Bech32");
282+
let bytes: [u8; 32] = bytes.try_into().expect("TEST_SK is 32 bytes");
283+
let key = Identity::from_secret_bytes(bytes);
284+
assert_eq!(key.to_string().expose_secret(), TEST_SK);
285+
}
286+
266287
proptest! {
267288
#[test]
268289
fn wrap_and_unwrap(sk_bytes in proptest::collection::vec(any::<u8>(), ..=32)) {

0 commit comments

Comments
 (0)