5
5
"crypto/aes"
6
6
"crypto/cipher"
7
7
"crypto/sha256"
8
+ "encoding/binary"
8
9
9
10
"github.com/libp2p/go-libp2p/core/peer"
10
11
"github.com/multiformats/go-multihash"
@@ -13,30 +14,39 @@ import (
13
14
const (
14
15
// nonceLen defines length of the nonce to use for AESGCM encryption
15
16
nonceLen = 12
16
- // keysize defines the size of multihash key
17
- keysize = 32
17
+ )
18
+
19
+ var (
20
+ // secondHashPrefix is a prefix that a mulithash is prepended with when calculating a second hash
21
+ secondHashPrefix = []byte ("CR_DOUBLEHASH\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " )
22
+ // deriveKeyPrefix is a prefix that a multihash is prepended with when deriving an encryption key
23
+ deriveKeyPrefix = []byte ("CR_ENCRYPTIONKEY\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " )
24
+ // noncePrefix is a prefix that a multihash is prepended with when calculating a nonce
25
+ noncePrefix = []byte ("CR_NONCE\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " )
18
26
)
19
27
20
28
// SecondSHA returns SHA256 over the payload
21
29
func SHA256 (payload , dest []byte ) []byte {
30
+ return sha256Multiple (dest , payload )
31
+ }
32
+
33
+ func sha256Multiple (dest []byte , payloads ... []byte ) []byte {
22
34
h := sha256 .New ()
23
- h .Write (payload )
35
+ for _ , payload := range payloads {
36
+ h .Write (payload )
37
+ }
24
38
return h .Sum (dest )
25
39
}
26
40
27
41
// SecondMultihash calculates SHA256 over the multihash and wraps it into another multihash with DBL_SHA256 codec
28
42
func SecondMultihash (mh multihash.Multihash ) (multihash.Multihash , error ) {
29
- prefix := []byte ("CR_DOUBLEHASH" )
30
- mh , err := multihash .Sum (append (prefix , mh ... ), multihash .DBL_SHA2_256 , keysize )
31
- if err != nil {
32
- return nil , err
33
- }
34
- return mh , nil
43
+ digest := SHA256 (append (secondHashPrefix , mh ... ), nil )
44
+ return multihash .Encode (digest , multihash .DBL_SHA2_256 )
35
45
}
36
46
37
47
// deriveKey derives encryptioin key from the passphrase using SHA256
38
48
func deriveKey (passphrase []byte ) []byte {
39
- return SHA256 (append ([] byte ( "AESGCM" ) , passphrase ... ), nil )
49
+ return SHA256 (append (deriveKeyPrefix , passphrase ... ), nil )
40
50
}
41
51
42
52
// DecryptAES decrypts AES payload using the nonce and the passphrase
@@ -62,9 +72,11 @@ func EncryptAES(payload, passphrase []byte) ([]byte, []byte, error) {
62
72
derivedKey := deriveKey ([]byte (passphrase ))
63
73
64
74
// Create initialization vector (nonse) to be used during encryption
65
- // Nonce is derived from the mulithash (passpharase) so that encrypted payloads
66
- // for the same multihash can be compared to each other without having to decrypt
67
- nonce := SHA256 (passphrase , nil )[:nonceLen ]
75
+ // Nonce is derived from the passphrase concatenated with the payload so that the encrypted payloads
76
+ // for the same multihash can be compared to each other without having to decrypt them, as it's not possible.
77
+ payloadLen := make ([]byte , 8 )
78
+ binary .LittleEndian .PutUint64 (payloadLen , uint64 (len (payload )))
79
+ nonce := sha256Multiple (nil , noncePrefix , payloadLen , payload , passphrase )[:nonceLen ]
68
80
69
81
// Create cypher and seal the data
70
82
block , err := aes .NewCipher (derivedKey )
@@ -83,13 +95,13 @@ func EncryptAES(payload, passphrase []byte) ([]byte, []byte, error) {
83
95
}
84
96
85
97
// DecryptValueKey decrypts the value key using the passphrase
86
- func DecryptValueKey (valKey , passphrase [] byte ) ([]byte , error ) {
87
- return DecryptAES (valKey [:nonceLen ], valKey [nonceLen :], passphrase )
98
+ func DecryptValueKey (valKey , mh multihash. Multihash ) ([]byte , error ) {
99
+ return DecryptAES (valKey [:nonceLen ], valKey [nonceLen :], mh )
88
100
}
89
101
90
102
// EncryptValueKey encrypts raw value key using the passpharse
91
- func EncryptValueKey (valKey , passphrase [] byte ) ([]byte , error ) {
92
- nonce , encValKey , err := EncryptAES (valKey , passphrase )
103
+ func EncryptValueKey (valKey , mh multihash. Multihash ) ([]byte , error ) {
104
+ nonce , encValKey , err := EncryptAES (valKey , mh )
93
105
if err != nil {
94
106
return nil , err
95
107
}
@@ -98,13 +110,13 @@ func EncryptValueKey(valKey, passphrase []byte) ([]byte, error) {
98
110
}
99
111
100
112
// DecryptMetadata decrypts metdata using the provided passphrase
101
- func DecryptMetadata (encMetadata , passphrase []byte ) ([]byte , error ) {
102
- return DecryptAES (encMetadata [:nonceLen ], encMetadata [nonceLen :], passphrase )
113
+ func DecryptMetadata (encMetadata , valueKey []byte ) ([]byte , error ) {
114
+ return DecryptAES (encMetadata [:nonceLen ], encMetadata [nonceLen :], valueKey )
103
115
}
104
116
105
117
// EncryptMetadata encrypts metadata using the provided passphrase
106
- func EncryptMetadata (metadata , passphrase []byte ) ([]byte , error ) {
107
- nonce , encValKey , err := EncryptAES (metadata , passphrase )
118
+ func EncryptMetadata (metadata , valueKey []byte ) ([]byte , error ) {
119
+ nonce , encValKey , err := EncryptAES (metadata , valueKey )
108
120
if err != nil {
109
121
return nil , err
110
122
}
0 commit comments