11import crypto from 'node:crypto'
22import { newInstance , ChaCha20Poly1305 } from '@chainsafe/as-chacha20poly1305'
33import { digest } from '@chainsafe/as-sha256'
4+ import { Uint8ArrayList } from 'uint8arraylist'
45import { isElectronMain } from 'wherearewe'
56import { pureJsCrypto } from './js.js'
67import type { KeyPair } from '../@types/libp2p.js'
@@ -13,50 +14,105 @@ const PKCS8_PREFIX = Buffer.from([0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06
1314const X25519_PREFIX = Buffer . from ( [ 0x30 , 0x2a , 0x30 , 0x05 , 0x06 , 0x03 , 0x2b , 0x65 , 0x6e , 0x03 , 0x21 , 0x00 ] )
1415const nodeCrypto : Pick < ICryptoInterface , 'hashSHA256' | 'chaCha20Poly1305Encrypt' | 'chaCha20Poly1305Decrypt' > = {
1516 hashSHA256 ( data ) {
16- return crypto . createHash ( 'sha256' ) . update ( data ) . digest ( )
17+ const hash = crypto . createHash ( 'sha256' )
18+
19+ if ( data instanceof Uint8Array ) {
20+ return hash . update ( data ) . digest ( )
21+ }
22+
23+ for ( const buf of data ) {
24+ hash . update ( buf )
25+ }
26+
27+ return hash . digest ( )
1728 } ,
1829
1930 chaCha20Poly1305Encrypt ( plaintext , nonce , ad , k ) {
2031 const cipher = crypto . createCipheriv ( CHACHA_POLY1305 , k , nonce , {
2132 authTagLength : 16
2233 } )
2334 cipher . setAAD ( ad , { plaintextLength : plaintext . byteLength } )
24- const updated = cipher . update ( plaintext )
35+
36+ if ( plaintext instanceof Uint8Array ) {
37+ const updated = cipher . update ( plaintext )
38+ const final = cipher . final ( )
39+ const tag = cipher . getAuthTag ( )
40+
41+ return Buffer . concat ( [ updated , tag , final ] , updated . byteLength + tag . byteLength + final . byteLength )
42+ }
43+
44+ const output = new Uint8ArrayList ( )
45+
46+ for ( const buf of plaintext ) {
47+ output . append ( cipher . update ( buf ) )
48+ }
49+
2550 const final = cipher . final ( )
26- const tag = cipher . getAuthTag ( )
2751
28- const encrypted = Buffer . concat ( [ updated , tag , final ] , updated . byteLength + tag . byteLength + final . byteLength )
29- return encrypted
52+ if ( final . byteLength > 0 ) {
53+ output . append ( final )
54+ }
55+
56+ output . append ( cipher . getAuthTag ( ) )
57+
58+ return output
3059 } ,
3160
3261 chaCha20Poly1305Decrypt ( ciphertext , nonce , ad , k , _dst ) {
3362 const authTag = ciphertext . subarray ( ciphertext . length - 16 )
34- const text = ciphertext . subarray ( 0 , ciphertext . length - 16 )
3563 const decipher = crypto . createDecipheriv ( CHACHA_POLY1305 , k , nonce , {
3664 authTagLength : 16
3765 } )
66+
67+ let text : Uint8Array | Uint8ArrayList
68+
69+ if ( ciphertext instanceof Uint8Array ) {
70+ text = ciphertext . subarray ( 0 , ciphertext . length - 16 )
71+ } else {
72+ text = ciphertext . sublist ( 0 , ciphertext . length - 16 )
73+ }
74+
3875 decipher . setAAD ( ad , {
3976 plaintextLength : text . byteLength
4077 } )
4178 decipher . setAuthTag ( authTag )
42- const updated = decipher . update ( text )
79+
80+ if ( text instanceof Uint8Array ) {
81+ const output = decipher . update ( text )
82+ const final = decipher . final ( )
83+
84+ if ( final . byteLength > 0 ) {
85+ return Buffer . concat ( [ output , final ] , output . byteLength + final . byteLength )
86+ }
87+
88+ return output
89+ }
90+
91+ const output = new Uint8ArrayList ( )
92+
93+ for ( const buf of text ) {
94+ output . append ( decipher . update ( buf ) )
95+ }
96+
4397 const final = decipher . final ( )
98+
4499 if ( final . byteLength > 0 ) {
45- return Buffer . concat ( [ updated , final ] , updated . byteLength + final . byteLength )
100+ output . append ( final )
46101 }
47- return updated
102+
103+ return output
48104 }
49105}
50106
51107const asCrypto : Pick < ICryptoInterface , 'hashSHA256' | 'chaCha20Poly1305Encrypt' | 'chaCha20Poly1305Decrypt' > = {
52108 hashSHA256 ( data ) {
53- return digest ( data )
109+ return digest ( data . subarray ( ) )
54110 } ,
55111 chaCha20Poly1305Encrypt ( plaintext , nonce , ad , k ) {
56- return asImpl . seal ( k , nonce , plaintext , ad )
112+ return asImpl . seal ( k , nonce , plaintext . subarray ( ) , ad )
57113 } ,
58114 chaCha20Poly1305Decrypt ( ciphertext , nonce , ad , k , dst ) {
59- return asImpl . open ( k , nonce , ciphertext , ad , dst )
115+ return asImpl . open ( k , nonce , ciphertext . subarray ( ) , ad , dst )
60116 }
61117}
62118
@@ -69,13 +125,13 @@ export const defaultCrypto: ICryptoInterface = {
69125 return nodeCrypto . hashSHA256 ( data )
70126 } ,
71127 chaCha20Poly1305Encrypt ( plaintext , nonce , ad , k ) {
72- if ( plaintext . length < 1200 ) {
128+ if ( plaintext . byteLength < 1200 ) {
73129 return asCrypto . chaCha20Poly1305Encrypt ( plaintext , nonce , ad , k )
74130 }
75131 return nodeCrypto . chaCha20Poly1305Encrypt ( plaintext , nonce , ad , k )
76132 } ,
77133 chaCha20Poly1305Decrypt ( ciphertext , nonce , ad , k , dst ) {
78- if ( ciphertext . length < 1200 ) {
134+ if ( ciphertext . byteLength < 1200 ) {
79135 return asCrypto . chaCha20Poly1305Decrypt ( ciphertext , nonce , ad , k , dst )
80136 }
81137 return nodeCrypto . chaCha20Poly1305Decrypt ( ciphertext , nonce , ad , k , dst )
@@ -118,16 +174,26 @@ export const defaultCrypto: ICryptoInterface = {
118174 privateKey : seed
119175 }
120176 } ,
121- generateX25519SharedKey ( privateKey : Uint8Array , publicKey : Uint8Array ) : Uint8Array {
122- publicKey = Buffer . concat ( [
123- X25519_PREFIX ,
124- publicKey
125- ] , X25519_PREFIX . byteLength + publicKey . byteLength )
126-
127- privateKey = Buffer . concat ( [
128- PKCS8_PREFIX ,
129- privateKey
130- ] , PKCS8_PREFIX . byteLength + privateKey . byteLength )
177+ generateX25519SharedKey ( privateKey : Uint8Array | Uint8ArrayList , publicKey : Uint8Array | Uint8ArrayList ) : Uint8Array {
178+ if ( publicKey instanceof Uint8Array ) {
179+ publicKey = Buffer . concat ( [
180+ X25519_PREFIX ,
181+ publicKey
182+ ] , X25519_PREFIX . byteLength + publicKey . byteLength )
183+ } else {
184+ publicKey . prepend ( X25519_PREFIX )
185+ publicKey = publicKey . subarray ( )
186+ }
187+
188+ if ( privateKey instanceof Uint8Array ) {
189+ privateKey = Buffer . concat ( [
190+ PKCS8_PREFIX ,
191+ privateKey
192+ ] , PKCS8_PREFIX . byteLength + privateKey . byteLength )
193+ } else {
194+ privateKey . prepend ( PKCS8_PREFIX )
195+ privateKey = privateKey . subarray ( )
196+ }
131197
132198 return crypto . diffieHellman ( {
133199 publicKey : crypto . createPublicKey ( {
0 commit comments