1
- use crate :: { hash:: hkdf_hmac_sha256, SYMMETRIC_KEY_SIZE } ;
1
+ use crate :: { hash:: hkdf_hmac_sha256, SYMMETRIC_KEY_SIZE } ;
2
2
use bc_rand:: RandomNumberGenerator ;
3
- use x25519_dalek:: { PublicKey , StaticSecret } ;
3
+ use x25519_dalek:: { PublicKey , StaticSecret } ;
4
4
5
+ pub const GENERIC_PRIVATE_KEY_SIZE : usize = 32 ;
6
+ pub const GENERIC_PUBLIC_KEY_SIZE : usize = 32 ;
5
7
pub const X25519_PRIVATE_KEY_SIZE : usize = 32 ;
6
8
pub const X25519_PUBLIC_KEY_SIZE : usize = 32 ;
7
9
10
+ /// Derive a 32-byte agreement private key from the given key material.
11
+ ///
12
+ /// May be used for key agreement or key encapsulation.
13
+ ///
14
+ /// Enforces domain separation from signing keys by using the "agreement" salt.
15
+ pub fn derive_agreement_private_key (
16
+ key_material : impl AsRef < [ u8 ] >
17
+ ) -> [ u8 ; GENERIC_PRIVATE_KEY_SIZE ] {
18
+ hkdf_hmac_sha256 ( key_material, "agreement" . as_bytes ( ) , GENERIC_PRIVATE_KEY_SIZE )
19
+ . try_into ( )
20
+ . unwrap ( )
21
+ }
22
+
23
+ /// Derive a 32-byte signing private key from the given key material.
24
+ ///
25
+ /// Enforces domain separation from agreement keys by using the "signing" salt.
26
+ pub fn derive_signing_private_key ( key_material : impl AsRef < [ u8 ] > ) -> [ u8 ; GENERIC_PUBLIC_KEY_SIZE ] {
27
+ hkdf_hmac_sha256 ( key_material, "signing" . as_bytes ( ) , GENERIC_PUBLIC_KEY_SIZE )
28
+ . try_into ( )
29
+ . unwrap ( )
30
+ }
31
+
8
32
/// Create a new X25519 private key using the given random number generator.
9
- pub fn x25519_new_private_key_using ( rng : & mut impl RandomNumberGenerator ) -> [ u8 ; X25519_PRIVATE_KEY_SIZE ] {
33
+ pub fn x25519_new_private_key_using (
34
+ rng : & mut impl RandomNumberGenerator
35
+ ) -> [ u8 ; X25519_PRIVATE_KEY_SIZE ] {
10
36
rng. random_data ( X25519_PRIVATE_KEY_SIZE ) . try_into ( ) . unwrap ( )
11
37
}
12
38
13
39
/// Derive a X25519 public key from a private key.
14
- pub fn x25519_public_key_from_private_key ( x25519_private_key : & [ u8 ; X25519_PRIVATE_KEY_SIZE ] ) -> [ u8 ; X25519_PUBLIC_KEY_SIZE ] {
40
+ pub fn x25519_public_key_from_private_key (
41
+ x25519_private_key : & [ u8 ; X25519_PRIVATE_KEY_SIZE ]
42
+ ) -> [ u8 ; X25519_PUBLIC_KEY_SIZE ] {
15
43
let sk = StaticSecret :: from ( * x25519_private_key) ;
16
44
let pk = PublicKey :: from ( & sk) ;
17
45
pk. as_bytes ( ) . to_owned ( )
18
46
}
19
47
20
- /// Derive an X25519 private key from the given key material.
21
- pub fn x25519_derive_private_key ( key_material : impl AsRef < [ u8 ] > ) -> [ u8 ; X25519_PRIVATE_KEY_SIZE ] {
22
- hkdf_hmac_sha256 ( key_material, "agreement" . as_bytes ( ) , X25519_PRIVATE_KEY_SIZE ) . try_into ( ) . unwrap ( )
23
- }
24
-
25
- /// Derive an X25519 signing private key from the given key material.
26
- pub fn x25519_derive_signing_private_key ( key_material : impl AsRef < [ u8 ] > ) -> [ u8 ; X25519_PRIVATE_KEY_SIZE ] {
27
- hkdf_hmac_sha256 ( key_material, "signing" . as_bytes ( ) , X25519_PRIVATE_KEY_SIZE ) . try_into ( ) . unwrap ( )
28
- }
29
-
30
48
/// Compute the shared symmetric key from the given X25519 private and public keys.
31
- pub fn x25519_shared_key ( x25519_private_key : & [ u8 ; X25519_PRIVATE_KEY_SIZE ] , x25519_public_key : & [ u8 ; X25519_PUBLIC_KEY_SIZE ] ) -> [ u8 ; SYMMETRIC_KEY_SIZE ] {
49
+ pub fn x25519_shared_key (
50
+ x25519_private_key : & [ u8 ; X25519_PRIVATE_KEY_SIZE ] ,
51
+ x25519_public_key : & [ u8 ; X25519_PUBLIC_KEY_SIZE ]
52
+ ) -> [ u8 ; SYMMETRIC_KEY_SIZE ] {
32
53
let sk = StaticSecret :: from ( * x25519_private_key) ;
33
54
let pk = PublicKey :: from ( * x25519_public_key) ;
34
55
let shared_secret = sk. diffie_hellman ( & pk) ;
@@ -40,21 +61,39 @@ mod tests {
40
61
use bc_rand:: make_fake_random_number_generator;
41
62
use hex_literal:: hex;
42
63
43
- use crate :: { x25519_new_private_key_using, x25519_public_key_from_private_key, x25519_derive_private_key, x25519_derive_signing_private_key, x25519_shared_key} ;
64
+ use crate :: {
65
+ derive_agreement_private_key,
66
+ derive_signing_private_key,
67
+ x25519_new_private_key_using,
68
+ x25519_public_key_from_private_key,
69
+ x25519_shared_key,
70
+ } ;
44
71
45
72
#[ test]
46
73
fn test_x25519_keys ( ) {
47
74
let mut rng = make_fake_random_number_generator ( ) ;
48
75
let private_key = x25519_new_private_key_using ( & mut rng) ;
49
- assert_eq ! ( private_key, hex!( "7eb559bbbf6cce2632cf9f194aeb50943de7e1cbad54dcfab27a42759f5e2fed" ) ) ;
76
+ assert_eq ! (
77
+ private_key,
78
+ hex!( "7eb559bbbf6cce2632cf9f194aeb50943de7e1cbad54dcfab27a42759f5e2fed" )
79
+ ) ;
50
80
let public_key = x25519_public_key_from_private_key ( & private_key) ;
51
- assert_eq ! ( public_key, hex!( "f1bd7a7e118ea461eba95126a3efef543ebb78439d1574bedcbe7d89174cf025" ) ) ;
81
+ assert_eq ! (
82
+ public_key,
83
+ hex!( "f1bd7a7e118ea461eba95126a3efef543ebb78439d1574bedcbe7d89174cf025" )
84
+ ) ;
52
85
53
- let derived_x25519_private_key = x25519_derive_private_key ( b"password" ) ;
54
- assert_eq ! ( derived_x25519_private_key, hex!( "7b19769132648ff43ae60cbaa696d5be3f6d53e6645db72e2d37516f0729619f" ) ) ;
86
+ let derived_x25519_private_key = derive_agreement_private_key ( b"password" ) ;
87
+ assert_eq ! (
88
+ derived_x25519_private_key,
89
+ hex!( "7b19769132648ff43ae60cbaa696d5be3f6d53e6645db72e2d37516f0729619f" )
90
+ ) ;
55
91
56
- let derived_signing_private_key = x25519_derive_signing_private_key ( b"password" ) ;
57
- assert_eq ! ( derived_signing_private_key, hex!( "05cc550daa75058e613e606d9898fedf029e395911c43273a208b7e0e88e271b" ) ) ;
92
+ let derived_signing_private_key = derive_signing_private_key ( b"password" ) ;
93
+ assert_eq ! (
94
+ derived_signing_private_key,
95
+ hex!( "05cc550daa75058e613e606d9898fedf029e395911c43273a208b7e0e88e271b" )
96
+ ) ;
58
97
}
59
98
60
99
#[ test]
@@ -67,6 +106,9 @@ mod tests {
67
106
let alice_shared_key = x25519_shared_key ( & alice_private_key, & bob_public_key) ;
68
107
let bob_shared_key = x25519_shared_key ( & bob_private_key, & alice_public_key) ;
69
108
assert_eq ! ( alice_shared_key, bob_shared_key) ;
70
- assert_eq ! ( alice_shared_key, hex!( "1e9040d1ff45df4bfca7ef2b4dd2b11101b40d91bf5bf83f8c83d53f0fbb6c23" ) ) ;
109
+ assert_eq ! (
110
+ alice_shared_key,
111
+ hex!( "1e9040d1ff45df4bfca7ef2b4dd2b11101b40d91bf5bf83f8c83d53f0fbb6c23" )
112
+ ) ;
71
113
}
72
114
}
0 commit comments