16
16
//!
17
17
18
18
use core:: ptr;
19
- use core:: ops:: { FnMut , Deref } ;
19
+ use core:: ops:: Deref ;
20
20
21
21
use key:: { SecretKey , PublicKey } ;
22
22
use ffi:: { self , CPtr } ;
@@ -135,52 +135,52 @@ impl SharedSecret {
135
135
ss. set_len ( 32 ) ; // The default hash function is SHA256, which is 32 bytes long.
136
136
ss
137
137
}
138
+ }
138
139
139
-
140
- /// Creates a new shared secret from a pubkey and secret key with applied custom hash function.
141
- /// The custom hash function must be in the form of `fn(x: [u8;32], y: [u8;32]) -> SharedSecret`
142
- /// `SharedSecret` can be easily created via the `From` impl from arrays.
143
- /// # Examples
144
- /// ```
145
- /// # #[cfg(any(feature = "alloc", features = "std"))] {
146
- /// # use secp256k1::ecdh::SharedSecret;
147
- /// # use secp256k1::{Secp256k1, PublicKey, SecretKey};
148
- /// # fn sha2(_a: &[u8], _b: &[u8]) -> [u8; 32] {[0u8; 32]}
149
- /// # let secp = Secp256k1::signing_only();
150
- /// # let secret_key = SecretKey::from_slice(&[3u8; 32]).unwrap();
151
- /// # let secret_key2 = SecretKey::from_slice(&[7u8; 32]).unwrap();
152
- /// # let public_key = PublicKey::from_secret_key(&secp, &secret_key2);
153
- ///
154
- /// let secret = SharedSecret::new_with_hash(&public_key, &secret_key, |x,y| {
155
- /// let hash: [u8; 32] = sha2(&x,&y);
156
- /// hash.into()
157
- /// });
158
- /// # }
159
- /// ```
160
- pub fn new_with_hash < F > ( point : & PublicKey , scalar : & SecretKey , mut hash_function : F ) -> SharedSecret
161
- where F : FnMut ( [ u8 ; 32 ] , [ u8 ; 32 ] ) -> SharedSecret {
162
- let mut xy = [ 0u8 ; 64 ] ;
163
-
164
- let res = unsafe {
165
- ffi:: secp256k1_ecdh (
166
- ffi:: secp256k1_context_no_precomp,
167
- xy. as_mut_ptr ( ) ,
168
- point. as_ptr ( ) ,
169
- scalar. as_ptr ( ) ,
170
- Some ( c_callback) ,
171
- ptr:: null_mut ( ) ,
172
- )
173
- } ;
174
- // Our callback *always* returns 1.
175
- // and the scalar was verified to be valid(0 > scalar > group_order) via the type system
176
- debug_assert_eq ! ( res, 1 ) ;
177
-
178
- let mut x = [ 0u8 ; 32 ] ;
179
- let mut y = [ 0u8 ; 32 ] ;
180
- x. copy_from_slice ( & xy[ ..32 ] ) ;
181
- y. copy_from_slice ( & xy[ 32 ..] ) ;
182
- hash_function ( x, y)
183
- }
140
+ /// Creates a shared point from public key and secret key.
141
+ ///
142
+ /// Can be used like `SharedSecret` but caller is responsible for then hashing the returned buffer.
143
+ /// This allows for the use of a custom hash function since `SharedSecret` uses SHA256.
144
+ ///
145
+ /// # Returns
146
+ ///
147
+ /// 64 bytes representing the (x,y) co-ordinates of a point on the curve (32 bytes each).
148
+ ///
149
+ /// # Examples
150
+ /// ```
151
+ /// # #[cfg(all(feature = "bitcoin_hashes", feature = "rand-std", feature = "std"))] {
152
+ /// # use secp256k1::{ecdh, Secp256k1, PublicKey, SecretKey};
153
+ /// # use secp256k1::hashes::{Hash, sha512};
154
+ /// # use secp256k1::rand::thread_rng;
155
+ ///
156
+ /// let s = Secp256k1::new();
157
+ /// let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
158
+ /// let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
159
+ ///
160
+ /// let point1 = ecdh::shared_secret_point(&pk2, &sk1);
161
+ /// let secret1 = sha512::Hash::hash(&point1);
162
+ /// let point2 = ecdh::shared_secret_point(&pk1, &sk2);
163
+ /// let secret2 = sha512::Hash::hash(&point2);
164
+ /// assert_eq!(secret1, secret2)
165
+ /// # }
166
+ /// ```
167
+ pub fn shared_secret_point ( point : & PublicKey , scalar : & SecretKey ) -> [ u8 ; 64 ] {
168
+ let mut xy = [ 0u8 ; 64 ] ;
169
+
170
+ let res = unsafe {
171
+ ffi:: secp256k1_ecdh (
172
+ ffi:: secp256k1_context_no_precomp,
173
+ xy. as_mut_ptr ( ) ,
174
+ point. as_ptr ( ) ,
175
+ scalar. as_ptr ( ) ,
176
+ Some ( c_callback) ,
177
+ ptr:: null_mut ( ) ,
178
+ )
179
+ } ;
180
+ // Our callback *always* returns 1.
181
+ // The scalar was verified to be valid (0 > scalar > group_order) via the type system.
182
+ debug_assert_eq ! ( res, 1 ) ;
183
+ xy
184
184
}
185
185
186
186
#[ cfg( test) ]
@@ -207,38 +207,6 @@ mod tests {
207
207
assert ! ( sec_odd != sec2) ;
208
208
}
209
209
210
- #[ test]
211
- #[ cfg( all( feature="std" , feature = "rand-std" ) ) ]
212
- fn ecdh_with_hash ( ) {
213
- let s = Secp256k1 :: signing_only ( ) ;
214
- let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
215
- let ( sk2, pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
216
-
217
- let sec1 = SharedSecret :: new_with_hash ( & pk1, & sk2, |x, _| x. into ( ) ) ;
218
- let sec2 = SharedSecret :: new_with_hash ( & pk2, & sk1, |x, _| x. into ( ) ) ;
219
- let sec_odd = SharedSecret :: new_with_hash ( & pk1, & sk1, |x, _| x. into ( ) ) ;
220
- assert_eq ! ( sec1, sec2) ;
221
- assert_ne ! ( sec_odd, sec2) ;
222
- }
223
-
224
- #[ test]
225
- #[ cfg( all( feature="std" , feature = "rand-std" ) ) ]
226
- fn ecdh_with_hash_callback ( ) {
227
- let s = Secp256k1 :: signing_only ( ) ;
228
- let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
229
- let expect_result: [ u8 ; 64 ] = [ 123 ; 64 ] ;
230
- let mut x_out = [ 0u8 ; 32 ] ;
231
- let mut y_out = [ 0u8 ; 32 ] ;
232
- let result = SharedSecret :: new_with_hash ( & pk1, & sk1, |x, y| {
233
- x_out = x;
234
- y_out = y;
235
- expect_result. into ( )
236
- } ) ;
237
- assert_eq ! ( & expect_result[ ..] , & result[ ..] ) ;
238
- assert_ne ! ( x_out, [ 0u8 ; 32 ] ) ;
239
- assert_ne ! ( y_out, [ 0u8 ; 32 ] ) ;
240
- }
241
-
242
210
#[ test]
243
211
fn test_c_callback ( ) {
244
212
let x = [ 5u8 ; 32 ] ;
0 commit comments