yubihsm/authentication/
key.rs1use super::{Error, ErrorKind};
4use rand_core::{OsRng, RngCore};
5use std::fmt::{self, Debug};
6use zeroize::Zeroize;
7
8#[cfg(feature = "pbkdf2")]
9use pbkdf2::pbkdf2_hmac;
10
11#[cfg(feature = "sha2")]
12use sha2::Sha256;
13
14pub const SIZE: usize = 32;
16
17pub const DEFAULT_PASSWORD: &[u8] = b"password";
19
20pub const PBKDF2_SALT: &[u8] = b"Yubico";
24
25pub const PBKDF2_ITERATIONS: u32 = 10_000;
28
29#[derive(Clone)]
32pub struct Key(pub(crate) [u8; SIZE]);
33
34impl Key {
35 pub fn random() -> Self {
37 let mut challenge = [0u8; SIZE];
38 OsRng.fill_bytes(&mut challenge);
39 Key(challenge)
40 }
41
42 #[cfg(feature = "passwords")]
47 pub fn derive_from_password(password: &[u8]) -> Self {
48 let mut kdf_output = [0u8; SIZE];
49 pbkdf2_hmac::<Sha256>(password, PBKDF2_SALT, PBKDF2_ITERATIONS, &mut kdf_output);
50 Self::new(kdf_output)
51 }
52
53 pub fn from_slice(key_slice: &[u8]) -> Result<Self, Error> {
56 ensure!(
57 key_slice.len() == SIZE,
58 ErrorKind::KeySizeInvalid,
59 "expected {}-byte key, got {}",
60 SIZE,
61 key_slice.len()
62 );
63
64 let mut key_bytes = [0u8; SIZE];
65 key_bytes.copy_from_slice(key_slice);
66
67 Ok(Key(key_bytes))
68 }
69
70 pub fn new(key_bytes: [u8; SIZE]) -> Self {
72 Key(key_bytes)
73 }
74
75 pub fn as_secret_slice(&self) -> &[u8] {
77 &self.0
78 }
79
80 pub(crate) fn enc_key(&self) -> &[u8] {
82 &self.0[..16]
83 }
84
85 pub(crate) fn mac_key(&self) -> &[u8] {
87 &self.0[16..]
88 }
89}
90
91impl Debug for Key {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 write!(f, "yubihsm::authentication::Key(...)")
95 }
96}
97
98#[cfg(feature = "passwords")]
100impl Default for Key {
101 fn default() -> Self {
102 Key::derive_from_password(DEFAULT_PASSWORD)
103 }
104}
105
106impl Drop for Key {
107 fn drop(&mut self) {
108 self.0.zeroize();
109 }
110}
111
112impl From<[u8; SIZE]> for Key {
113 fn from(key_bytes: [u8; SIZE]) -> Key {
114 Key::new(key_bytes)
115 }
116}
117
118impl_array_serializers!(Key, SIZE);