1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use crate::Error;
/// Wraps the bytes-in/bytes-out [`obcrypt::Key`] with oboron's
/// hex-string constructors and accessors.
///
/// Stays an oboron-internal type โ encoding parsing belongs at this
/// layer, not in `obcrypt`.
pub struct MasterKey {
key: obcrypt::Key,
}
impl MasterKey {
/// Create a MasterKey from 64 raw bytes.
#[inline]
pub fn from_bytes(key_bytes: &[u8; 64]) -> Result<Self, Error> {
Ok(MasterKey {
key: obcrypt::Key::from_bytes(*key_bytes),
})
}
/// Create a MasterKey from a 128-character hex string.
///
/// This is the canonical text encoding for oboron keys.
#[inline]
pub fn from_hex(key_hex: &str) -> Result<Self, Error> {
// Spec ยง3.3: keys MUST be lowercase hex. The `hex` crate decodes
// case-insensitively, so reject any uppercase explicitly.
if key_hex.bytes().any(|b| b.is_ascii_uppercase()) {
return Err(Error::InvalidHex);
}
let key_bytes: [u8; 64] = hex::decode(key_hex)?
.try_into()
.map_err(|_| Error::InvalidKeyLength)?;
Self::from_bytes(&key_bytes)
}
/// Create a MasterKey from a key string.
///
/// The canonical โ and only โ key text encoding is 128-character
/// hex; any other length is rejected with [`Error::InvalidKeyLength`].
/// Equivalent to [`Self::from_hex`]; kept as the length-routing
/// entry point the `new` constructors delegate to.
#[inline]
pub fn from_string(s: &str) -> Result<Self, Error> {
match s.len() {
128 => Self::from_hex(s),
_ => Err(Error::InvalidKeyLength),
}
}
/// Encode the key as a 128-character hex string.
///
/// This is the canonical text encoding for oboron keys.
#[inline]
pub fn key_hex(&self) -> String {
hex::encode(self.key.as_bytes())
}
#[inline]
pub(crate) fn key_bytes(&self) -> &[u8; 64] {
self.key.as_bytes()
}
/// Borrow the underlying `obcrypt::Key` for direct handoff to obcrypt
/// without a 64-byte copy.
#[inline(always)]
pub(crate) fn obcrypt_key(&self) -> &obcrypt::Key {
&self.key
}
}