Add another ExpandedKey derivation for Offers
[rust-lightning] / lightning / src / util / crypto.rs
1 use bitcoin::hashes::{Hash, HashEngine};
2 use bitcoin::hashes::hmac::{Hmac, HmacEngine};
3 use bitcoin::hashes::sha256::Hash as Sha256;
4 use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature, Signing};
5
6 macro_rules! hkdf_extract_expand {
7         ($salt: expr, $ikm: expr) => {{
8                 let mut hmac = HmacEngine::<Sha256>::new($salt);
9                 hmac.input($ikm);
10                 let prk = Hmac::from_engine(hmac).into_inner();
11                 let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
12                 hmac.input(&[1; 1]);
13                 let t1 = Hmac::from_engine(hmac).into_inner();
14                 let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
15                 hmac.input(&t1);
16                 hmac.input(&[2; 1]);
17                 (t1, Hmac::from_engine(hmac).into_inner(), prk)
18         }};
19         ($salt: expr, $ikm: expr, 2) => {{
20                 let (k1, k2, _) = hkdf_extract_expand!($salt, $ikm);
21                 (k1, k2)
22         }};
23         ($salt: expr, $ikm: expr, 4) => {{
24                 let (k1, k2, prk) = hkdf_extract_expand!($salt, $ikm);
25
26                 let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
27                 hmac.input(&k2);
28                 hmac.input(&[3; 1]);
29                 let k3 = Hmac::from_engine(hmac).into_inner();
30
31                 let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
32                 hmac.input(&k3);
33                 hmac.input(&[4; 1]);
34                 (k1, k2, k3, Hmac::from_engine(hmac).into_inner())
35         }}
36 }
37
38 pub fn hkdf_extract_expand_twice(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
39         hkdf_extract_expand!(salt, ikm, 2)
40 }
41
42 pub fn hkdf_extract_expand_4x(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32]) {
43         hkdf_extract_expand!(salt, ikm, 4)
44 }
45
46 #[inline]
47 pub fn sign<C: Signing>(ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey) -> Signature {
48         #[cfg(feature = "grind_signatures")]
49         let sig = ctx.sign_ecdsa_low_r(msg, sk);
50         #[cfg(not(feature = "grind_signatures"))]
51         let sig = ctx.sign_ecdsa(msg, sk);
52         sig
53 }