@@ -2,11 +2,10 @@ package compat
22
33import (
44 "crypto/hmac"
5- "log "
5+ "encoding/base64 "
66 "math/big"
77 "reflect"
88
9- "encoding/base64"
109 "errors"
1110
1211 ecies "github.com/bitcoin-sv/go-sdk/primitives/aescbc"
@@ -20,11 +19,20 @@ import (
2019
2120func EncryptSingle (message string , privateKey * ec.PrivateKey ) (string , error ) {
2221 messageBytes := []byte (message )
23- return ElectrumEncrypt (messageBytes , privateKey .PubKey (), privateKey , false )
22+
23+ decryptedBytes , err := ElectrumEncrypt (messageBytes , privateKey .PubKey (), privateKey , false )
24+ if err != nil {
25+ return "" , err
26+ }
27+ return base64 .StdEncoding .EncodeToString (decryptedBytes ), nil
2428}
2529
2630func DecryptSingle (encryptedData string , privateKey * ec.PrivateKey ) (string , error ) {
27- plainBytes , err := ElectrumDecrypt (encryptedData , privateKey , nil )
31+ encryptedBytes , err := base64 .StdEncoding .DecodeString (encryptedData )
32+ if err != nil {
33+ return "" , err
34+ }
35+ plainBytes , err := ElectrumDecrypt (encryptedBytes , privateKey , nil )
2836 if err != nil {
2937 return "" , err
3038 }
@@ -33,18 +41,30 @@ func DecryptSingle(encryptedData string, privateKey *ec.PrivateKey) (string, err
3341
3442func EncryptShared (message string , toPublicKey * ec.PublicKey , fromPrivateKey * ec.PrivateKey ) (string , error ) {
3543 messageBytes := []byte (message )
36- return ElectrumEncrypt (messageBytes , toPublicKey , nil , false )
44+ decryptedBytes , err := ElectrumEncrypt (messageBytes , toPublicKey , nil , false )
45+ if err != nil {
46+ return "" , err
47+ }
48+ return base64 .StdEncoding .EncodeToString (decryptedBytes ), nil
3749}
3850
3951func DecryptShared (encryptedData string , toPrivateKey * ec.PrivateKey , fromPublicKey * ec.PublicKey ) (string , error ) {
40- plainBytes , err := ElectrumDecrypt (encryptedData , toPrivateKey , fromPublicKey )
52+ encryptedBytes , err := base64 .StdEncoding .DecodeString (encryptedData )
53+ if err != nil {
54+ return "" , err
55+ }
56+ plainBytes , err := ElectrumDecrypt (encryptedBytes , toPrivateKey , fromPublicKey )
4157 if err != nil {
4258 return "" , err
4359 }
4460 return string (plainBytes ), nil
4561}
4662
47- func ElectrumEncrypt (message []byte , toPublicKey * ec.PublicKey , fromPrivateKey * ec.PrivateKey , noKey bool ) (string , error ) {
63+ func ElectrumEncrypt (message []byte ,
64+ toPublicKey * ec.PublicKey ,
65+ fromPrivateKey * ec.PrivateKey ,
66+ noKey bool ,
67+ ) ([]byte , error ) {
4868 // Generate an ephemeral EC private key if fromPrivateKey is nil
4969 var ephemeralPrivateKey * ec.PrivateKey
5070 if fromPrivateKey == nil {
@@ -64,7 +84,7 @@ func ElectrumEncrypt(message []byte, toPublicKey *ec.PublicKey, fromPrivateKey *
6484 // AES encryption
6585 cipherText , err := ecies .AESCBCEncrypt (message , keyE , iv , false )
6686 if err != nil {
67- return "" , err
87+ return nil , err
6888 }
6989
7090 ephemeralPublicKey := ephemeralPrivateKey .PubKey ()
@@ -79,52 +99,48 @@ func ElectrumEncrypt(message []byte, toPublicKey *ec.PublicKey, fromPrivateKey *
7999
80100 mac := c .Sha256HMAC (encrypted , keyM )
81101
82- return base64 . StdEncoding . EncodeToString ( append (encrypted , mac ... ) ), nil
102+ return append (encrypted , mac ... ), nil
83103}
84- func ElectrumDecrypt (encryptedData string , toPrivateKey * ec.PrivateKey , fromPublicKey * ec.PublicKey ) ([]byte , error ) {
85- encrypted , err := base64 .StdEncoding .DecodeString (encryptedData )
86- if err != nil {
87- return nil , err
88- }
89- if len (encrypted ) < 52 { // Minimum length: 4 (magic) + 16 (min cipher) + 32 (mac)
104+ func ElectrumDecrypt (encryptedData []byte , toPrivateKey * ec.PrivateKey , fromPublicKey * ec.PublicKey ) ([]byte , error ) {
105+
106+ if len (encryptedData ) < 52 { // Minimum length: 4 (magic) + 16 (min cipher) + 32 (mac)
90107 return nil , errors .New ("invalid encrypted text: length" )
91108 }
92- magic := encrypted [:4 ]
109+ magic := encryptedData [:4 ]
93110 if string (magic ) != "BIE1" {
94111 return nil , errors .New ("invalid cipher text: invalid magic bytes" )
95112 }
96113
97114 var sharedSecret []byte
98115 var cipherText []byte
99- var ephemeralPublicKey * ec.PublicKey
100116
101117 if fromPublicKey != nil {
102118 // Use counterparty public key to derive shared secret
103119 x , y := toPrivateKey .Curve .ScalarMult (fromPublicKey .X , fromPublicKey .Y , toPrivateKey .D .Bytes ())
104120 sharedSecret = (& ec.PublicKey {X : x , Y : y }).SerializeCompressed ()
105- if len (encrypted ) > 69 { // 4 (magic) + 33 (pubkey) + 32 (mac)
106- cipherText = encrypted [37 : len (encrypted )- 32 ]
121+ if len (encryptedData ) > 69 { // 4 (magic) + 33 (pubkey) + 32 (mac)
122+ cipherText = encryptedData [37 : len (encryptedData )- 32 ]
107123 } else {
108- cipherText = encrypted [4 : len (encrypted )- 32 ]
124+ cipherText = encryptedData [4 : len (encryptedData )- 32 ]
109125 }
110126 } else {
111127 // Use ephemeral public key to derive shared secret
112- ephemeralPublicKey , err = ec .ParsePubKey (encrypted [4 :37 ])
128+ ephemeralPublicKey , err : = ec .ParsePubKey (encryptedData [4 :37 ])
113129 if err != nil {
114130 return nil , err
115131 }
116132 x , y := ephemeralPublicKey .Curve .ScalarMult (ephemeralPublicKey .X , ephemeralPublicKey .Y , toPrivateKey .D .Bytes ())
117133 sharedSecret = (& ec.PublicKey {X : x , Y : y }).SerializeCompressed ()
118- cipherText = encrypted [37 : len (encrypted )- 32 ]
134+ cipherText = encryptedData [37 : len (encryptedData )- 32 ]
119135 }
120136
121137 // Derive key_e, iv and key_m
122138 key := c .Sha512 (sharedSecret )
123139 iv , keyE , keyM := key [0 :16 ], key [16 :32 ], key [32 :]
124140
125141 // Verify mac
126- mac := encrypted [len (encrypted )- 32 :]
127- macRecalculated := c .Sha256HMAC (encrypted [:len (encrypted )- 32 ], keyM )
142+ mac := encryptedData [len (encryptedData )- 32 :]
143+ macRecalculated := c .Sha256HMAC (encryptedData [:len (encryptedData )- 32 ], keyM )
128144 if ! reflect .DeepEqual (mac , macRecalculated ) {
129145 return nil , errors .New ("incorrect password" )
130146 }
@@ -134,69 +150,17 @@ func ElectrumDecrypt(encryptedData string, toPrivateKey *ec.PrivateKey, fromPubl
134150 if err != nil {
135151 return nil , err
136152 }
137- log .Printf ("IV: %x, plain text: %x" , iv , plain )
138153 return plain , nil
139154}
140155
141- // func BitcoreEncrypt(message []byte, publicKey *ec.PublicKey) (string, error) {
142- // // Generate an ephemeral EC private key
143- // ephemeralPrivateKey, err := ec.NewPrivateKey()
144- // if err != nil {
145- // return "", err
146- // }
147-
148- // // Derive shared secret
149- // x, _ := publicKey.Curve.ScalarMult(publicKey.X, publicKey.Y, ephemeralPrivateKey.D.Bytes())
150- // sharedSecret := x.Bytes()
151-
152- // // Key derivation
153- // keyMaterial := c.Sha512(sharedSecret)
154-
155- // keyE := keyMaterial[:32] // AES-256 key
156- // keyM := keyMaterial[32:] // HMAC key
157- // iv := make([]byte, 16) // IV for AES (all zeros in Bitcore)
158-
159- // // Encrypt the message
160- // cipherText, err := aescbc.AESEncryptWithIV(message, keyE, iv)
161- // if err != nil {
162- // return "", err
163- // }
164-
165- // // Prepare the output
166- // ephemeralPublicKey := ephemeralPrivateKey.PubKey().SerializeCompressed()
167- // encryptedData := append(ephemeralPublicKey, cipherText...)
168-
169- // // Calculate HMAC
170- // hmacSum := c.Sha256HMAC(encryptedData, keyM)
171-
172- // // Combine all parts
173- // result := append(encryptedData, hmacSum...)
174-
175- // return base64.StdEncoding.EncodeToString(result), nil
176- // }
177-
178- func BitcoreEncrypt (message []byte , toPublicKey * ec.PublicKey , fromPrivateKey * ec.PrivateKey , iv []byte ) (string , error ) {
179-
180- // JS Implementation
181- // if (!fromPrivateKey) {
182- // fromPrivateKey = PrivateKey.fromRandom()
183- // }
184- // const r = fromPrivateKey
185- // const RPublicKey = fromPrivateKey.toPublicKey()
186- // const RBuf = RPublicKey.encode(true) as number[]
187- // const KB = toPublicKey
188- // const P = KB.mul(r)
189- // const S = P.getX()
190- // const Sbuf = S.toArray('be', 32)
191- // const kEkM = Hash.sha512(Sbuf)
192- // const kE = kEkM.slice(0, 32)
193- // const kM = kEkM.slice(32, 64)
194- // const c = AESCBC.encrypt(messageBuf, kE, ivBuf)
195- // const d = Hash.sha256hmac(kM, [...c])
196- // const encBuf = [...RBuf, ...c, ...d]
197- // return encBuf
198- // If IV is not provided, generate a random one
156+ // BitcoreEncrypt encrypts a message using ECIES
157+ func BitcoreEncrypt (message []byte ,
158+ toPublicKey * ec.PublicKey ,
159+ fromPrivateKey * ec.PrivateKey ,
160+ iv []byte ,
161+ ) ([]byte , error ) {
199162
163+ // If IV is not provided, fill it with zeros
200164 if iv == nil {
201165 iv = make ([]byte , 16 )
202166 }
@@ -206,7 +170,7 @@ func BitcoreEncrypt(message []byte, toPublicKey *ec.PublicKey, fromPrivateKey *e
206170 var err error
207171 fromPrivateKey , err = ec .NewPrivateKey ()
208172 if err != nil {
209- return "" , err
173+ return nil , err
210174 }
211175 }
212176
@@ -219,45 +183,18 @@ func BitcoreEncrypt(message []byte, toPublicKey *ec.PublicKey, fromPrivateKey *e
219183 kM := kEkM [32 :]
220184 cc , err := ecies .AESCBCEncrypt (message , kE , iv , true )
221185 if err != nil {
222- return "" , err
186+ return nil , err
223187 }
224188 d := c .Sha256HMAC (cc , kM )
225189 encBuf := append (RBuf , cc ... )
226190 encBuf = append (encBuf , d ... )
227191
228- log .Printf ("encBuf: %x" , encBuf )
229- result := base64 .StdEncoding .EncodeToString (encBuf )
230- return result , nil
192+ return encBuf , nil
231193}
232194
233- func BitcoreDecrypt (encryptedMessage string , toPrivatKey * ec.PrivateKey ) ([]byte , error ) {
234- // const kB = toPrivateKey
235- // const fromPublicKey = PublicKey.fromString(toHex(encBuf.slice(0, 33)))
236- // const R = fromPublicKey
237- // const P = R.mul(kB)
238- // if (P.eq(new Point(0, 0))) {
239- // throw new Error('P equals 0')
240- // }
241- // const S = P.getX()
242- // const Sbuf = S.toArray('be', 32)
243- // const kEkM = Hash.sha512(Sbuf)
244- // const kE = kEkM.slice(0, 32)
245- // const kM = kEkM.slice(32, 64)
246- // const c = encBuf.slice(33, encBuf.length - 32)
247- // const d = encBuf.slice(encBuf.length - 32, encBuf.length)
248- // const d2 = Hash.sha256hmac(kM, c)
249- // if (toHex(d) !== toHex(d2)) {
250- // throw new Error('Invalid checksum')
251- // }
252- // const messageBuf = AESCBC.decrypt(c, kE)
253- // return [...messageBuf]
254-
255- data , err := base64 .StdEncoding .DecodeString (encryptedMessage )
256- if err != nil {
257- return nil , err
258- }
195+ func BitcoreDecrypt (encryptedMessage []byte , toPrivatKey * ec.PrivateKey ) ([]byte , error ) {
259196
260- fromPublicKey , err := ec .ParsePubKey (data [:33 ])
197+ fromPublicKey , err := ec .ParsePubKey (encryptedMessage [:33 ])
261198 if err != nil {
262199 return nil , err
263200 }
@@ -272,41 +209,12 @@ func BitcoreDecrypt(encryptedMessage string, toPrivatKey *ec.PrivateKey) ([]byte
272209 kE := kEkM [:32 ]
273210 kM := kEkM [32 :]
274211
275- cipherText := data [33 : len (data )- 32 ]
276- mac := data [len (data )- 32 :]
212+ cipherText := encryptedMessage [33 : len (encryptedMessage )- 32 ]
213+ mac := encryptedMessage [len (encryptedMessage )- 32 :]
277214 expectedMAC := c .Sha256HMAC (cipherText , kM )
278215 if ! hmac .Equal (mac , expectedMAC ) {
279216 return nil , errors .New ("invalid ciphertext: HMAC mismatch" )
280217 }
281218 iv := cipherText [:16 ]
282219 return ecies .AESCBCDecrypt (cipherText [16 :], kE , iv )
283-
284- // Derive shared secret
285- // x, _ := privateKey.Curve.ScalarMult(fromPublicKey.X, fromPublicKey.Y, privateKey.D.Bytes())
286- // sharedSecret := x.Bytes()
287-
288- // Key derivation
289- // keyMaterial := c.Sha512(sharedSecret)
290-
291- // keyE := keyMaterial[:32] // AES-256 key
292- // keyM := keyMaterial[32:] // HMAC key
293-
294- // // Verify HMAC
295- // mac := data[len(data)-32:]
296- // encryptedData := data[:len(data)-32]
297- // expectedMAC := c.Sha256HMAC(encryptedData, keyM)
298-
299- // if !hmac.Equal(mac, expectedMAC) {
300- // return nil, errors.New("invalid ciphertext: HMAC mismatch")
301- // }
302-
303- // // Decrypt
304- // iv := make([]byte, 16) // In Bitcore, IV is usually all zeros
305- // cipherText := encryptedData[33:]
306- // plainText, err := ecies.AESCBCDecrypt(cipherText, keyE, iv)
307- // if err != nil {
308- // return nil, err
309- // }
310-
311- // return plainText, nil
312220}
0 commit comments