1- // Copyright 2021 Shift Crypto AG
1+ // Copyright 2021, 2024 Shift Crypto AG
22//
33// Licensed under the Apache License, Version 2.0 (the "License");
44// you may not use this file except in compliance with the License.
1515use alloc:: vec:: Vec ;
1616
1717use bip32_ed25519:: { Xprv , Xpub , ED25519_EXPANDED_SECRET_KEY_SIZE } ;
18- use sha2:: Sha512 ;
18+
19+ /// Implements the digest traits for Sha512 backing it with the wally_sha512 C function. This is
20+ /// done to avoid using a second sha512 implementation like `sha2::Sha512`, which bloats the binary
21+ /// by an additional ~12.7kB (at the time of writing).
22+ ///
23+ /// This implementation accumulates the data to be hashed in heap, it does **not** hash in a
24+ /// streaming fashion, even when using `update()`. This is okay for the use within this module, as
25+ /// bip32_ed25519 and sign_raw() do not hash a lot of data.
26+ #[ derive( Default , Clone ) ]
27+ pub struct Sha512 ( Vec < u8 > ) ;
28+
29+ impl digest:: HashMarker for Sha512 { }
30+
31+ impl digest:: OutputSizeUser for Sha512 {
32+ type OutputSize = digest:: typenum:: U64 ;
33+ }
34+
35+ impl digest:: FixedOutput for Sha512 {
36+ fn finalize_into ( self , out : & mut digest:: Output < Self > ) {
37+ // use digest::Digest;
38+ // out.copy_from_slice(&sha2::Sha512::digest(&self.0));
39+ out. copy_from_slice ( & bitbox02:: sha512 ( & self . 0 ) ) ;
40+ }
41+ }
42+
43+ impl digest:: Update for Sha512 {
44+ fn update ( & mut self , data : & [ u8 ] ) {
45+ self . 0 . extend ( data) ;
46+ }
47+ }
48+
49+ impl digest:: Reset for Sha512 {
50+ fn reset ( & mut self ) {
51+ self . 0 = vec ! [ ] ;
52+ }
53+ }
54+
55+ impl digest:: core_api:: BlockSizeUser for Sha512 {
56+ type BlockSize = digest:: typenum:: U128 ;
57+ }
1958
2059fn get_seed ( ) -> Result < zeroize:: Zeroizing < Vec < u8 > > , ( ) > {
2160 bitbox02:: keystore:: get_ed25519_seed ( )
2261}
2362
24- fn get_xprv ( keypath : & [ u32 ] ) -> Result < Xprv , ( ) > {
63+ fn get_xprv ( keypath : & [ u32 ] ) -> Result < Xprv < Sha512 > , ( ) > {
2564 let root = get_seed ( ) ?;
26- Ok ( Xprv :: from_normalize (
65+ Ok ( Xprv :: < Sha512 > :: from_normalize (
2766 & root[ ..ED25519_EXPANDED_SECRET_KEY_SIZE ] ,
2867 & root[ ED25519_EXPANDED_SECRET_KEY_SIZE ..] ,
2968 )
3069 . derive_path ( keypath) )
3170}
3271
33- pub fn get_xpub ( keypath : & [ u32 ] ) -> Result < Xpub , ( ) > {
72+ pub fn get_xpub ( keypath : & [ u32 ] ) -> Result < Xpub < Sha512 > , ( ) > {
3473 Ok ( get_xprv ( keypath) ?. public ( ) )
3574}
3675
@@ -57,6 +96,24 @@ mod tests {
5796
5897 use bip32_ed25519:: HARDENED_OFFSET ;
5998 use bitbox02:: testing:: { mock_unlocked, mock_unlocked_using_mnemonic} ;
99+ use digest:: Digest ;
100+
101+ #[ test]
102+ fn test_sha512 ( ) {
103+ assert_eq ! ( Sha512 :: digest( b"foobar" ) , sha2:: Sha512 :: digest( b"foobar" ) ) ;
104+
105+ let mut hasher: Sha512 = Default :: default ( ) ;
106+ hasher. update ( b"foo" ) ;
107+ hasher. update ( b"bar" ) ;
108+ assert_eq ! ( hasher. finalize( ) , sha2:: Sha512 :: digest( b"foobar" ) ) ;
109+
110+ hasher = Default :: default ( ) ;
111+ hasher. update ( b"foo" ) ;
112+ hasher. update ( b"bar" ) ;
113+ hasher. reset ( ) ;
114+ hasher. update ( b"baz" ) ;
115+ assert_eq ! ( hasher. finalize( ) , sha2:: Sha512 :: digest( b"baz" ) ) ;
116+ }
60117
61118 #[ test]
62119 fn test_get_seed ( ) {
0 commit comments