1010//! Keys used to generate commitment transactions.
1111//! See: <https://github.com/lightning/bolts/blob/master/03-transactions.md#keys>
1212
13- use bitcoin:: hashes:: Hash ;
14- use bitcoin:: hashes:: HashEngine ;
15- use bitcoin:: secp256k1:: Scalar ;
16- use bitcoin:: secp256k1:: SecretKey ;
17- use bitcoin:: secp256k1:: Secp256k1 ;
18- use bitcoin:: secp256k1;
13+ use crate :: io;
1914use crate :: ln:: msgs:: DecodeError ;
2015use crate :: util:: ser:: Readable ;
21- use crate :: io;
22- use crate :: util:: ser:: Writer ;
2316use crate :: util:: ser:: Writeable ;
24- use bitcoin :: secp256k1 :: PublicKey ;
17+ use crate :: util :: ser :: Writer ;
2518use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
19+ use bitcoin:: hashes:: Hash ;
20+ use bitcoin:: hashes:: HashEngine ;
21+ use bitcoin:: secp256k1;
22+ use bitcoin:: secp256k1:: PublicKey ;
23+ use bitcoin:: secp256k1:: Scalar ;
24+ use bitcoin:: secp256k1:: Secp256k1 ;
25+ use bitcoin:: secp256k1:: SecretKey ;
2626
2727macro_rules! doc_comment {
2828 ( $x: expr, $( $tt: tt) * ) => {
@@ -37,15 +37,28 @@ macro_rules! basepoint_impl {
3737 pub fn to_public_key( & self ) -> PublicKey {
3838 self . 0
3939 }
40+
41+ /// Derives a per-commitment-transaction (eg an htlc key or delayed_payment key) private key addition tweak
42+ /// from a basepoint and a per_commitment_point:
43+ /// `privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`
44+ /// This calculates the hash part in the tweak derivation process, which is used to ensure
45+ /// that each key is unique and cannot be guessed by an external party. It is equivalent
46+ /// to the `from_basepoint` method, but without the addition operation, providing just the
47+ /// tweak from the hash of the per_commitment_point and the basepoint.
48+ pub fn derive_add_tweak( & self , per_commitment_point: & PublicKey ) -> [ u8 ; 32 ] {
49+ let mut sha = Sha256 :: engine( ) ;
50+ sha. input( & per_commitment_point. serialize( ) ) ;
51+ sha. input( & self . to_public_key( ) . serialize( ) ) ;
52+ Sha256 :: from_engine( sha) . to_byte_array( )
53+ }
4054 }
4155
4256 impl From <PublicKey > for $BasepointT {
4357 fn from( value: PublicKey ) -> Self {
4458 Self ( value)
4559 }
4660 }
47-
48- }
61+ } ;
4962}
5063macro_rules! key_impl {
5164 ( $BasepointT: ty, $KeyName: expr) => {
@@ -87,11 +100,9 @@ macro_rules! key_read_write {
87100 Ok ( Self ( key) )
88101 }
89102 }
90- }
103+ } ;
91104}
92105
93-
94-
95106/// Base key used in conjunction with a `per_commitment_point` to generate a [`DelayedPaymentKey`].
96107///
97108/// The delayed payment key is used to pay the commitment state broadcaster their
@@ -102,7 +113,6 @@ pub struct DelayedPaymentBasepoint(pub PublicKey);
102113basepoint_impl ! ( DelayedPaymentBasepoint ) ;
103114key_read_write ! ( DelayedPaymentBasepoint ) ;
104115
105-
106116/// A derived key built from a [`DelayedPaymentBasepoint`] and `per_commitment_point`.
107117///
108118/// The delayed payment key is used to pay the commitment state broadcaster their
@@ -150,14 +160,25 @@ key_read_write!(HtlcKey);
150160/// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
151161/// from the base point and the per_commitment_key. This is the public equivalent of
152162/// derive_private_key - using only public keys to derive a public key instead of private keys.
153- fn derive_public_key < T : secp256k1:: Signing > ( secp_ctx : & Secp256k1 < T > , per_commitment_point : & PublicKey , base_point : & PublicKey ) -> PublicKey {
163+ fn derive_public_key < T : secp256k1:: Signing > (
164+ secp_ctx : & Secp256k1 < T > , per_commitment_point : & PublicKey , base_point : & PublicKey ,
165+ ) -> PublicKey {
154166 let mut sha = Sha256 :: engine ( ) ;
155167 sha. input ( & per_commitment_point. serialize ( ) ) ;
156168 sha. input ( & base_point. serialize ( ) ) ;
157169 let res = Sha256 :: from_engine ( sha) . to_byte_array ( ) ;
158170
159- let hashkey = PublicKey :: from_secret_key ( & secp_ctx,
160- & SecretKey :: from_slice ( & res) . expect ( "Hashes should always be valid keys unless SHA-256 is broken" ) ) ;
171+ add_public_key_tweak ( secp_ctx, base_point, & res)
172+ }
173+
174+ pub fn add_public_key_tweak < T : secp256k1:: Signing > (
175+ secp_ctx : & Secp256k1 < T > , base_point : & PublicKey , tweak : & [ u8 ; 32 ] ,
176+ ) -> PublicKey {
177+ let hashkey = PublicKey :: from_secret_key (
178+ & secp_ctx,
179+ & SecretKey :: from_slice ( tweak)
180+ . expect ( "Hashes should always be valid keys unless SHA-256 is broken" ) ,
181+ ) ;
161182 base_point. combine ( & hashkey)
162183 . expect ( "Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key." )
163184}
@@ -169,7 +190,6 @@ pub struct RevocationBasepoint(pub PublicKey);
169190basepoint_impl ! ( RevocationBasepoint ) ;
170191key_read_write ! ( RevocationBasepoint ) ;
171192
172-
173193/// The revocation key is used to allow a channel party to revoke their state - giving their
174194/// counterparty the required material to claim all of their funds if they broadcast that state.
175195///
@@ -192,8 +212,7 @@ impl RevocationKey {
192212 ///
193213 /// [`chan_utils::derive_private_revocation_key`]: crate::ln::chan_utils::derive_private_revocation_key
194214 pub fn from_basepoint < T : secp256k1:: Verification > (
195- secp_ctx : & Secp256k1 < T > ,
196- countersignatory_basepoint : & RevocationBasepoint ,
215+ secp_ctx : & Secp256k1 < T > , countersignatory_basepoint : & RevocationBasepoint ,
197216 per_commitment_point : & PublicKey ,
198217 ) -> Self {
199218 let rev_append_commit_hash_key = {
@@ -227,28 +246,56 @@ impl RevocationKey {
227246}
228247key_read_write ! ( RevocationKey ) ;
229248
230-
231249#[ cfg( test) ]
232250mod test {
233- use bitcoin:: secp256k1:: { Secp256k1 , SecretKey , PublicKey } ;
234- use bitcoin:: hashes:: hex:: FromHex ;
235251 use super :: derive_public_key;
252+ use bitcoin:: hashes:: hex:: FromHex ;
253+ use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
236254
237255 #[ test]
238256 fn test_key_derivation ( ) {
239257 // Test vectors from BOLT 3 Appendix E:
240258 let secp_ctx = Secp256k1 :: new ( ) ;
241259
242- let base_secret = SecretKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
243- let per_commitment_secret = SecretKey :: from_slice ( & <Vec < u8 > >:: from_hex ( "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
260+ let base_secret = SecretKey :: from_slice (
261+ & <Vec < u8 > >:: from_hex (
262+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ,
263+ )
264+ . unwrap ( ) [ ..] ,
265+ )
266+ . unwrap ( ) ;
267+ let per_commitment_secret = SecretKey :: from_slice (
268+ & <Vec < u8 > >:: from_hex (
269+ "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" ,
270+ )
271+ . unwrap ( ) [ ..] ,
272+ )
273+ . unwrap ( ) ;
244274
245275 let base_point = PublicKey :: from_secret_key ( & secp_ctx, & base_secret) ;
246- assert_eq ! ( base_point. serialize( ) [ ..] , <Vec <u8 >>:: from_hex( "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" ) . unwrap( ) [ ..] ) ;
276+ assert_eq ! (
277+ base_point. serialize( ) [ ..] ,
278+ <Vec <u8 >>:: from_hex(
279+ "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2"
280+ )
281+ . unwrap( ) [ ..]
282+ ) ;
247283
248284 let per_commitment_point = PublicKey :: from_secret_key ( & secp_ctx, & per_commitment_secret) ;
249- assert_eq ! ( per_commitment_point. serialize( ) [ ..] , <Vec <u8 >>:: from_hex( "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" ) . unwrap( ) [ ..] ) ;
250-
251- assert_eq ! ( derive_public_key( & secp_ctx, & per_commitment_point, & base_point) . serialize( ) [ ..] ,
252- <Vec <u8 >>:: from_hex( "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5" ) . unwrap( ) [ ..] ) ;
285+ assert_eq ! (
286+ per_commitment_point. serialize( ) [ ..] ,
287+ <Vec <u8 >>:: from_hex(
288+ "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486"
289+ )
290+ . unwrap( ) [ ..]
291+ ) ;
292+
293+ assert_eq ! (
294+ derive_public_key( & secp_ctx, & per_commitment_point, & base_point) . serialize( ) [ ..] ,
295+ <Vec <u8 >>:: from_hex(
296+ "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5"
297+ )
298+ . unwrap( ) [ ..]
299+ ) ;
253300 }
254301}
0 commit comments