1
- // Copyright 2021 Shift Crypto AG
1
+ // Copyright 2021, 2024 Shift Crypto AG
2
2
//
3
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
4
// you may not use this file except in compliance with the License.
15
15
use alloc:: vec:: Vec ;
16
16
17
17
use 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
+ }
19
58
20
59
fn get_seed ( ) -> Result < zeroize:: Zeroizing < Vec < u8 > > , ( ) > {
21
60
bitbox02:: keystore:: get_ed25519_seed ( )
22
61
}
23
62
24
- fn get_xprv ( keypath : & [ u32 ] ) -> Result < Xprv , ( ) > {
63
+ fn get_xprv ( keypath : & [ u32 ] ) -> Result < Xprv < Sha512 > , ( ) > {
25
64
let root = get_seed ( ) ?;
26
- Ok ( Xprv :: from_normalize (
65
+ Ok ( Xprv :: < Sha512 > :: from_normalize (
27
66
& root[ ..ED25519_EXPANDED_SECRET_KEY_SIZE ] ,
28
67
& root[ ED25519_EXPANDED_SECRET_KEY_SIZE ..] ,
29
68
)
30
69
. derive_path ( keypath) )
31
70
}
32
71
33
- pub fn get_xpub ( keypath : & [ u32 ] ) -> Result < Xpub , ( ) > {
72
+ pub fn get_xpub ( keypath : & [ u32 ] ) -> Result < Xpub < Sha512 > , ( ) > {
34
73
Ok ( get_xprv ( keypath) ?. public ( ) )
35
74
}
36
75
@@ -57,6 +96,24 @@ mod tests {
57
96
58
97
use bip32_ed25519:: HARDENED_OFFSET ;
59
98
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
+ }
60
117
61
118
#[ test]
62
119
fn test_get_seed ( ) {
0 commit comments