@alessiofrittoli/crypto-cipher 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -188
- package/dist/index-D2HlPPn6.d.cts +361 -0
- package/dist/index-D2HlPPn6.d.mts +361 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -4
- package/dist/index.mjs +1 -1
- package/dist/types/index.d.cts +2 -0
- package/dist/types/index.d.mts +2 -0
- package/dist/types/index.mjs +1 -0
- package/package.json +116 -122
- package/dist/index-DWiR3kkc.d.mts +0 -364
- package/dist/index-DWiR3kkc.d.ts +0 -364
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -1
- package/dist/types.d.mts +0 -4
- package/dist/types.d.ts +0 -4
- package/dist/types.js +0 -1
- /package/dist/{types.mjs → types/index.cjs} +0 -0
package/README.md
CHANGED
|
@@ -1,18 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">Crypto Cipher 🔐</h1>
|
|
2
|
+
<p align="center">
|
|
3
|
+
Node.js Cipher cryptograph utility library
|
|
4
|
+
</p>
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://npmjs.org/package/@alessiofrittoli/crypto-cipher">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@alessiofrittoli/crypto-cipher" alt="Latest version"/>
|
|
8
|
+
</a>
|
|
9
|
+
<a href="https://coveralls.io/github/alessiofrittoli/crypto-cipher">
|
|
10
|
+
<img src="https://coveralls.io/repos/github/alessiofrittoli/crypto-cipher/badge.svg" alt="Test coverage"/>
|
|
11
|
+
</a>
|
|
12
|
+
<a href="https://socket.dev/npm/package/@alessiofrittoli/crypto-cipher/overview">
|
|
13
|
+
<img src="https://socket.dev/api/badge/npm/package/@alessiofrittoli/crypto-cipher" alt="Socket Security score"/>
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://npmjs.org/package/@alessiofrittoli/crypto-cipher">
|
|
16
|
+
<img src="https://img.shields.io/npm/dm/@alessiofrittoli/crypto-cipher.svg" alt="npm downloads"/>
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://bundlephobia.com/package/@alessiofrittoli/crypto-cipher">
|
|
19
|
+
<img src="https://badgen.net/bundlephobia/dependency-count/@alessiofrittoli/crypto-cipher" alt="Dependencies"/>
|
|
20
|
+
</a>
|
|
21
|
+
<a href="https://libraries.io/npm/%40alessiofrittoli%2Fcrypto-cipher">
|
|
22
|
+
<img src="https://img.shields.io/librariesio/release/npm/@alessiofrittoli/crypto-cipher" alt="Dependencies status"/>
|
|
23
|
+
</a>
|
|
24
|
+
</p>
|
|
25
|
+
<p align="center">
|
|
26
|
+
<a href="https://bundlephobia.com/package/@alessiofrittoli/crypto-cipher">
|
|
27
|
+
<img src="https://badgen.net/bundlephobia/min/@alessiofrittoli/crypto-cipher" alt="minified"/>
|
|
28
|
+
</a>
|
|
29
|
+
<a href="https://bundlephobia.com/package/@alessiofrittoli/crypto-cipher">
|
|
30
|
+
<img src="https://badgen.net/bundlephobia/minzip/@alessiofrittoli/crypto-cipher" alt="minizipped"/>
|
|
31
|
+
</a>
|
|
32
|
+
<a href="https://bundlephobia.com/package/@alessiofrittoli/crypto-cipher">
|
|
33
|
+
<img src="https://badgen.net/bundlephobia/tree-shaking/@alessiofrittoli/crypto-cipher" alt="Tree shakable"/>
|
|
34
|
+
</a>
|
|
35
|
+
</p>
|
|
36
|
+
<p align="center">
|
|
37
|
+
<a href="https://github.com/sponsors/alessiofrittoli">
|
|
38
|
+
<img src="https://img.shields.io/static/v1?label=Fund%20this%20package&message=%E2%9D%A4&logo=GitHub&color=%23DB61A2" alt="Fund this package"/>
|
|
39
|
+
</a>
|
|
40
|
+
</p>
|
|
2
41
|
|
|
3
|
-
[![NPM Latest Version][version-badge]][npm-url] [![Coverage Status][coverage-badge]][coverage-url] [![Socket Status][socket-badge]][socket-url] [![NPM Monthly Downloads][downloads-badge]][npm-url] [![Dependencies][deps-badge]][deps-url]
|
|
4
|
-
|
|
5
|
-
[![GitHub Sponsor][sponsor-badge]][sponsor-url]
|
|
6
|
-
|
|
7
|
-
[version-badge]: https://img.shields.io/npm/v/%40alessiofrittoli%2Fcrypto-cipher
|
|
8
|
-
[npm-url]: https://npmjs.org/package/%40alessiofrittoli%2Fcrypto-cipher
|
|
9
|
-
[coverage-badge]: https://coveralls.io/repos/github/alessiofrittoli/crypto-cipher/badge.svg
|
|
10
|
-
[coverage-url]: https://coveralls.io/github/alessiofrittoli/crypto-cipher
|
|
11
|
-
[socket-badge]: https://socket.dev/api/badge/npm/package/@alessiofrittoli/crypto-cipher
|
|
12
|
-
[socket-url]: https://socket.dev/npm/package/@alessiofrittoli/crypto-cipher/overview
|
|
13
|
-
[downloads-badge]: https://img.shields.io/npm/dm/%40alessiofrittoli%2Fcrypto-cipher.svg
|
|
14
|
-
[deps-badge]: https://img.shields.io/librariesio/release/npm/%40alessiofrittoli%2Fcrypto-cipher
|
|
15
|
-
[deps-url]: https://libraries.io/npm/%40alessiofrittoli%2Fcrypto-cipher
|
|
16
42
|
[sponsor-badge]: https://img.shields.io/static/v1?label=Fund%20this%20package&message=%E2%9D%A4&logo=GitHub&color=%23DB61A2
|
|
17
43
|
[sponsor-url]: https://github.com/sponsors/alessiofrittoli
|
|
18
44
|
|
|
@@ -44,10 +70,12 @@
|
|
|
44
70
|
- [File based data stream encryption/decryption](#file-based-data-stream-encryptiondecryption)
|
|
45
71
|
- [File based data stream with hybrid encryption/decryption](#file-based-data-stream-with-hybrid-encryptiondecryption)
|
|
46
72
|
- [Development](#development)
|
|
47
|
-
- [
|
|
48
|
-
- [
|
|
49
|
-
- [
|
|
50
|
-
- [
|
|
73
|
+
- [Local development](#local-development)
|
|
74
|
+
- [Production build](#production-build)
|
|
75
|
+
- [Unit tests](#unit-tests)
|
|
76
|
+
- [Run tests with coverage](#run-tests-with-coverage)
|
|
77
|
+
- [Contributing](#contributing)
|
|
78
|
+
- [Security](#security)
|
|
51
79
|
- [Credits](#made-with-)
|
|
52
80
|
|
|
53
81
|
---
|
|
@@ -124,13 +152,13 @@ Is now renamed to **`Cipher.Decrypt()`**. It's API implementation remain the sam
|
|
|
124
152
|
**Before**
|
|
125
153
|
|
|
126
154
|
```ts
|
|
127
|
-
await Cipher.streamEncrypt(password, { input, output }).encrypt()
|
|
155
|
+
await Cipher.streamEncrypt(password, { input, output }).encrypt()
|
|
128
156
|
```
|
|
129
157
|
|
|
130
158
|
**Now**
|
|
131
159
|
|
|
132
160
|
```ts
|
|
133
|
-
await Cipher.stream.Encrypt(password, { input, output })
|
|
161
|
+
await Cipher.stream.Encrypt(password, { input, output })
|
|
134
162
|
```
|
|
135
163
|
|
|
136
164
|
---
|
|
@@ -140,15 +168,15 @@ await Cipher.stream.Encrypt(password, { input, output });
|
|
|
140
168
|
**Before**
|
|
141
169
|
|
|
142
170
|
```ts
|
|
143
|
-
const { decrypt } = await Cipher.streamDecrypt(password, { input, output })
|
|
171
|
+
const { decrypt } = await Cipher.streamDecrypt(password, { input, output })
|
|
144
172
|
|
|
145
|
-
await decrypt()
|
|
173
|
+
await decrypt()
|
|
146
174
|
```
|
|
147
175
|
|
|
148
176
|
**Now**
|
|
149
177
|
|
|
150
178
|
```ts
|
|
151
|
-
await Cipher.stream.Decrypt(password, { input, output })
|
|
179
|
+
await Cipher.stream.Decrypt(password, { input, output })
|
|
152
180
|
```
|
|
153
181
|
|
|
154
182
|
---
|
|
@@ -163,17 +191,17 @@ const { encrypt } = Cipher.hybridEncrypt(
|
|
|
163
191
|
{
|
|
164
192
|
key: keyPair.publicKey,
|
|
165
193
|
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
166
|
-
oaepHash:
|
|
194
|
+
oaepHash: 'SHA-256',
|
|
167
195
|
},
|
|
168
|
-
{ input, output }
|
|
169
|
-
)
|
|
170
|
-
await encrypt()
|
|
196
|
+
{ input, output },
|
|
197
|
+
)
|
|
198
|
+
await encrypt()
|
|
171
199
|
```
|
|
172
200
|
|
|
173
201
|
**Now**
|
|
174
202
|
|
|
175
203
|
```ts
|
|
176
|
-
await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output })
|
|
204
|
+
await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output })
|
|
177
205
|
```
|
|
178
206
|
|
|
179
207
|
---
|
|
@@ -188,33 +216,38 @@ const { decrypt } = await Cipher.hybridDecrypt(
|
|
|
188
216
|
key: keyPair.privateKey,
|
|
189
217
|
passphrase: passphrase,
|
|
190
218
|
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
191
|
-
oaepHash:
|
|
219
|
+
oaepHash: 'SHA-256',
|
|
192
220
|
},
|
|
193
|
-
{ input, output, rsaKeyLength }
|
|
194
|
-
)
|
|
221
|
+
{ input, output, rsaKeyLength },
|
|
222
|
+
)
|
|
195
223
|
|
|
196
|
-
await decrypt()
|
|
224
|
+
await decrypt()
|
|
197
225
|
```
|
|
198
226
|
|
|
199
227
|
**Now**
|
|
200
228
|
|
|
201
229
|
```ts
|
|
202
|
-
await Cipher.stream.HybridDecrypt(
|
|
203
|
-
{ key: keyPair.privateKey, passphrase },
|
|
204
|
-
{ input, output }
|
|
205
|
-
);
|
|
230
|
+
await Cipher.stream.HybridDecrypt({ key: keyPair.privateKey, passphrase }, { input, output })
|
|
206
231
|
```
|
|
207
232
|
|
|
208
233
|
**Or even**
|
|
209
234
|
|
|
210
235
|
```ts
|
|
211
|
-
await Cipher.stream.HybridDecrypt(keyPair.privateKey, { input, output })
|
|
236
|
+
await Cipher.stream.HybridDecrypt(keyPair.privateKey, { input, output })
|
|
212
237
|
```
|
|
213
238
|
|
|
214
239
|
---
|
|
215
240
|
|
|
216
241
|
### API Reference
|
|
217
242
|
|
|
243
|
+
> [!WARNING]
|
|
244
|
+
>
|
|
245
|
+
> Requires the following packages to be installed:
|
|
246
|
+
>
|
|
247
|
+
> - [`@alessiofrittoli/crypto-buffer`](https://npmjs.com/package/@alessiofrittoli/crypto-buffer)
|
|
248
|
+
> - [`@alessiofrittoli/stream-reader`](https://npmjs.com/package/@alessiofrittoli/stream-reader)
|
|
249
|
+
> - [`@alessiofrittoli/math-utils`](https://npmjs.com/package/@alessiofrittoli/math-utils)
|
|
250
|
+
|
|
218
251
|
#### Constants
|
|
219
252
|
|
|
220
253
|
##### `Cipher.SALT_LENGTH`
|
|
@@ -795,14 +828,14 @@ The simpliest way to encrypt/decrypt in-memory data buffers.
|
|
|
795
828
|
|
|
796
829
|
```ts
|
|
797
830
|
// encrypt
|
|
798
|
-
const data =
|
|
799
|
-
const password =
|
|
831
|
+
const data = 'my top-secret data'
|
|
832
|
+
const password = 'my-very-strong-password'
|
|
800
833
|
|
|
801
|
-
const encrypted = Cipher.Encrypt(data, password)
|
|
834
|
+
const encrypted = Cipher.Encrypt(data, password)
|
|
802
835
|
|
|
803
836
|
// decrypt
|
|
804
|
-
const decrypted = Cipher.Decrypt(encrypted, password)
|
|
805
|
-
console.log(decrypted)
|
|
837
|
+
const decrypted = Cipher.Decrypt(encrypted, password)
|
|
838
|
+
console.log(decrypted) // Outputs: my top-secret data
|
|
806
839
|
```
|
|
807
840
|
|
|
808
841
|
---
|
|
@@ -824,41 +857,41 @@ Hybrid encryption offers an higher level of security since only the RSA Private
|
|
|
824
857
|
##### Keypair
|
|
825
858
|
|
|
826
859
|
```ts
|
|
827
|
-
import { Cipher } from
|
|
860
|
+
import { Cipher } from '@alessiofrittoli/crypto-cipher'
|
|
828
861
|
|
|
829
|
-
const keyPair = crypto.generateKeyPairSync(
|
|
862
|
+
const keyPair = crypto.generateKeyPairSync('rsa', {
|
|
830
863
|
modulusLength: 512 * 8, // 4096 bits
|
|
831
|
-
publicKeyEncoding: { type:
|
|
832
|
-
privateKeyEncoding: { type:
|
|
833
|
-
})
|
|
864
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
865
|
+
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
|
|
866
|
+
})
|
|
834
867
|
|
|
835
868
|
// or you can optionally set a custom passphrase
|
|
836
|
-
const passphrase =
|
|
869
|
+
const passphrase = 'custompassphrase'
|
|
837
870
|
|
|
838
|
-
const keyPair = crypto.generateKeyPairSync(
|
|
871
|
+
const keyPair = crypto.generateKeyPairSync('rsa', {
|
|
839
872
|
modulusLength: 512 * 8, // 4096 bits
|
|
840
|
-
publicKeyEncoding: { type:
|
|
873
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
841
874
|
privateKeyEncoding: {
|
|
842
|
-
type:
|
|
843
|
-
format:
|
|
875
|
+
type: 'pkcs1',
|
|
876
|
+
format: 'pem',
|
|
844
877
|
passphrase,
|
|
845
878
|
cipher: Cipher.ALGORITHM.CHACHA_20_POLY,
|
|
846
879
|
},
|
|
847
|
-
})
|
|
880
|
+
})
|
|
848
881
|
```
|
|
849
882
|
|
|
850
883
|
```ts
|
|
851
|
-
import { Cipher } from
|
|
884
|
+
import { Cipher } from '@alessiofrittoli/crypto-cipher'
|
|
852
885
|
|
|
853
886
|
// encrypt
|
|
854
|
-
const data =
|
|
855
|
-
const encrypted = Cipher.HybridEncrypt(data, keypair.publicKey)
|
|
887
|
+
const data = 'my top-secret data'
|
|
888
|
+
const encrypted = Cipher.HybridEncrypt(data, keypair.publicKey)
|
|
856
889
|
|
|
857
890
|
// decrypt
|
|
858
891
|
const decrypted = Cipher.HybridDecrypt(encrypted, {
|
|
859
892
|
key: keypair.privateKey,
|
|
860
893
|
passphrase,
|
|
861
|
-
})
|
|
894
|
+
})
|
|
862
895
|
```
|
|
863
896
|
|
|
864
897
|
---
|
|
@@ -872,43 +905,43 @@ The in-memory data stream comes pretty handy when, for example, we need to strea
|
|
|
872
905
|
```ts
|
|
873
906
|
// /api/stream-encrypt
|
|
874
907
|
|
|
875
|
-
import {
|
|
876
|
-
import {
|
|
908
|
+
import { Stream } from '@alessiofrittoli/stream-writer'
|
|
909
|
+
import { Readable, Writable } from 'stream'
|
|
877
910
|
|
|
878
911
|
const routeHandler = () => {
|
|
879
|
-
const password =
|
|
880
|
-
const stream = new Stream()
|
|
881
|
-
const headers = new Headers(stream.headers)
|
|
912
|
+
const password = 'my-very-strong-password'
|
|
913
|
+
const stream = new Stream()
|
|
914
|
+
const headers = new Headers(stream.headers)
|
|
882
915
|
|
|
883
916
|
const input = Readable.from([
|
|
884
|
-
Buffer.from(
|
|
885
|
-
Buffer.from(
|
|
886
|
-
Buffer.from(
|
|
887
|
-
Buffer.from(
|
|
888
|
-
])
|
|
917
|
+
Buffer.from('Chunk n.1'),
|
|
918
|
+
Buffer.from('Chunk n.2'),
|
|
919
|
+
Buffer.from('Chunk n.3'),
|
|
920
|
+
Buffer.from('Chunk n.4'),
|
|
921
|
+
])
|
|
889
922
|
|
|
890
923
|
// `Writable` Stream where encrypted data is written
|
|
891
924
|
const output = new Writable({
|
|
892
925
|
async write(chunk, encoding, callback) {
|
|
893
|
-
await new Promise(
|
|
894
|
-
await stream.write(chunk)
|
|
895
|
-
callback()
|
|
926
|
+
await new Promise(resolve => setTimeout(resolve, 2000))
|
|
927
|
+
await stream.write(chunk)
|
|
928
|
+
callback()
|
|
896
929
|
},
|
|
897
930
|
async final(callback) {
|
|
898
|
-
await stream.close()
|
|
899
|
-
callback()
|
|
931
|
+
await stream.close()
|
|
932
|
+
callback()
|
|
900
933
|
},
|
|
901
|
-
})
|
|
934
|
+
})
|
|
902
935
|
|
|
903
936
|
Cipher.stream.Encrypt(password, { input, output }).catch(async () => {
|
|
904
|
-
await stream.close()
|
|
905
|
-
})
|
|
937
|
+
await stream.close()
|
|
938
|
+
})
|
|
906
939
|
|
|
907
940
|
return (
|
|
908
941
|
// encrypted stream
|
|
909
942
|
new Response(stream.readable, { headers })
|
|
910
|
-
)
|
|
911
|
-
}
|
|
943
|
+
)
|
|
944
|
+
}
|
|
912
945
|
```
|
|
913
946
|
|
|
914
947
|
##### Decrypting received stream
|
|
@@ -916,59 +949,59 @@ const routeHandler = () => {
|
|
|
916
949
|
```ts
|
|
917
950
|
// /api/stream-decrypt
|
|
918
951
|
|
|
919
|
-
import {
|
|
920
|
-
import { Cipher } from
|
|
921
|
-
import {
|
|
952
|
+
import { StreamReader } from '@alessiofrittoli/stream-reader'
|
|
953
|
+
import { Cipher } from '@alessiofrittoli/crypto-cipher'
|
|
954
|
+
import { Transform, Writable } from 'stream'
|
|
922
955
|
|
|
923
|
-
const password =
|
|
956
|
+
const password = 'my-very-strong-password'
|
|
924
957
|
|
|
925
958
|
const routeHandler = () =>
|
|
926
|
-
fetch(
|
|
959
|
+
fetch('/api/stream-encrypt').then(response => {
|
|
927
960
|
if (!response.body) {
|
|
928
|
-
return new Respone(null, { status: 400 })
|
|
961
|
+
return new Respone(null, { status: 400 })
|
|
929
962
|
}
|
|
930
963
|
|
|
931
964
|
// web stream where decrypted data is written
|
|
932
965
|
const stream = new Stream<Buffer, string>({
|
|
933
966
|
transform(chunk, controller) {
|
|
934
|
-
controller.enqueue(chunk.toString())
|
|
967
|
+
controller.enqueue(chunk.toString())
|
|
935
968
|
},
|
|
936
|
-
})
|
|
937
|
-
const headers = new Headers(stream.headers)
|
|
969
|
+
})
|
|
970
|
+
const headers = new Headers(stream.headers)
|
|
938
971
|
|
|
939
|
-
headers.set(
|
|
972
|
+
headers.set('Content-Type', 'text/html')
|
|
940
973
|
|
|
941
974
|
const reader = new StreamReader<Uint8Array, Buffer, false>(response.body, {
|
|
942
975
|
inMemory: false,
|
|
943
976
|
transform: Buffer.from,
|
|
944
|
-
})
|
|
977
|
+
})
|
|
945
978
|
|
|
946
|
-
const input = new Transform()
|
|
979
|
+
const input = new Transform()
|
|
947
980
|
|
|
948
|
-
reader.on(
|
|
949
|
-
reader.on(
|
|
981
|
+
reader.on('data', chunk => input.push(chunk))
|
|
982
|
+
reader.on('close', () => input.end())
|
|
950
983
|
|
|
951
|
-
reader.read()
|
|
984
|
+
reader.read()
|
|
952
985
|
|
|
953
986
|
// `Writable` Stream where encrypted data is written
|
|
954
987
|
const output = new Writable({
|
|
955
988
|
async write(chunk: Buffer, encoding, callback) {
|
|
956
|
-
await stream.write(chunk)
|
|
957
|
-
callback()
|
|
989
|
+
await stream.write(chunk)
|
|
990
|
+
callback()
|
|
958
991
|
},
|
|
959
992
|
final(callback) {
|
|
960
|
-
stream.close()
|
|
961
|
-
callback()
|
|
993
|
+
stream.close()
|
|
994
|
+
callback()
|
|
962
995
|
},
|
|
963
|
-
})
|
|
996
|
+
})
|
|
964
997
|
|
|
965
|
-
Cipher.stream.Decrypt(password, { input, output }).catch(async
|
|
966
|
-
console.error(error)
|
|
967
|
-
await stream.close()
|
|
968
|
-
})
|
|
998
|
+
Cipher.stream.Decrypt(password, { input, output }).catch(async error => {
|
|
999
|
+
console.error(error)
|
|
1000
|
+
await stream.close()
|
|
1001
|
+
})
|
|
969
1002
|
|
|
970
|
-
return new Response(stream.readable, { headers })
|
|
971
|
-
})
|
|
1003
|
+
return new Response(stream.readable, { headers })
|
|
1004
|
+
})
|
|
972
1005
|
```
|
|
973
1006
|
|
|
974
1007
|
---
|
|
@@ -990,54 +1023,54 @@ Hybrid encryption offers an higher level of security since only the RSA Private
|
|
|
990
1023
|
##### Keypair
|
|
991
1024
|
|
|
992
1025
|
```ts
|
|
993
|
-
import { Cipher } from
|
|
1026
|
+
import { Cipher } from '@alessiofrittoli/crypto-cipher'
|
|
994
1027
|
|
|
995
|
-
const keyPair = crypto.generateKeyPairSync(
|
|
1028
|
+
const keyPair = crypto.generateKeyPairSync('rsa', {
|
|
996
1029
|
modulusLength: 512 * 8, // 4096 bits
|
|
997
|
-
publicKeyEncoding: { type:
|
|
998
|
-
privateKeyEncoding: { type:
|
|
999
|
-
})
|
|
1030
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
1031
|
+
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
|
|
1032
|
+
})
|
|
1000
1033
|
|
|
1001
1034
|
// or you can optionally set a custom passphrase
|
|
1002
|
-
const passphrase =
|
|
1035
|
+
const passphrase = 'custompassphrase'
|
|
1003
1036
|
|
|
1004
|
-
const keyPair = crypto.generateKeyPairSync(
|
|
1037
|
+
const keyPair = crypto.generateKeyPairSync('rsa', {
|
|
1005
1038
|
modulusLength: 512 * 8, // 4096 bits
|
|
1006
|
-
publicKeyEncoding: { type:
|
|
1039
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
1007
1040
|
privateKeyEncoding: {
|
|
1008
|
-
type:
|
|
1009
|
-
format:
|
|
1041
|
+
type: 'pkcs1',
|
|
1042
|
+
format: 'pem',
|
|
1010
1043
|
passphrase,
|
|
1011
1044
|
cipher: Cipher.ALGORITHM.CHACHA_20_POLY,
|
|
1012
1045
|
},
|
|
1013
|
-
})
|
|
1046
|
+
})
|
|
1014
1047
|
```
|
|
1015
1048
|
|
|
1016
1049
|
##### Encrypt
|
|
1017
1050
|
|
|
1018
1051
|
```ts
|
|
1019
|
-
const data =
|
|
1052
|
+
const data = 'my top-secret data'
|
|
1020
1053
|
/** Store encrypted chunks for next example. */
|
|
1021
|
-
const encryptedChunks: Buffer[] = []
|
|
1054
|
+
const encryptedChunks: Buffer[] = []
|
|
1022
1055
|
|
|
1023
1056
|
// Create a `Readable` Stream with raw data.
|
|
1024
1057
|
const input = new Readable({
|
|
1025
1058
|
read() {
|
|
1026
|
-
this.push(data)
|
|
1027
|
-
this.push(null)
|
|
1059
|
+
this.push(data) // Push data to encrypt
|
|
1060
|
+
this.push(null) // Signal end of stream
|
|
1028
1061
|
},
|
|
1029
|
-
})
|
|
1062
|
+
})
|
|
1030
1063
|
|
|
1031
1064
|
// Create a `Writable` Stream where encrypted data is written
|
|
1032
1065
|
const output = new Writable({
|
|
1033
1066
|
write(chunk, encoding, callback) {
|
|
1034
1067
|
// push written chunk to `encryptedChunks` for further usage.
|
|
1035
|
-
encryptedChunks.push(chunk)
|
|
1036
|
-
callback()
|
|
1068
|
+
encryptedChunks.push(chunk)
|
|
1069
|
+
callback()
|
|
1037
1070
|
},
|
|
1038
|
-
})
|
|
1071
|
+
})
|
|
1039
1072
|
|
|
1040
|
-
await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output })
|
|
1073
|
+
await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output })
|
|
1041
1074
|
```
|
|
1042
1075
|
|
|
1043
1076
|
---
|
|
@@ -1046,27 +1079,27 @@ await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output });
|
|
|
1046
1079
|
|
|
1047
1080
|
```ts
|
|
1048
1081
|
/** Store decrypted chunks. */
|
|
1049
|
-
const chunks: Buffer[] = []
|
|
1082
|
+
const chunks: Buffer[] = []
|
|
1050
1083
|
// Create a `Readable` Stream with encrypted data.
|
|
1051
|
-
const input = Readable.from(encryptedChunks)
|
|
1084
|
+
const input = Readable.from(encryptedChunks)
|
|
1052
1085
|
|
|
1053
1086
|
// Create a `Writable` Stream where decrypted data is written
|
|
1054
1087
|
const output = new Writable({
|
|
1055
1088
|
write(chunk, encoding, callback) {
|
|
1056
|
-
chunks.push(chunk)
|
|
1057
|
-
callback()
|
|
1089
|
+
chunks.push(chunk)
|
|
1090
|
+
callback()
|
|
1058
1091
|
},
|
|
1059
|
-
})
|
|
1092
|
+
})
|
|
1060
1093
|
|
|
1061
1094
|
await Cipher.stream.HybridDecrypt(
|
|
1062
1095
|
{
|
|
1063
1096
|
key: keyPair.privateKey,
|
|
1064
1097
|
passphrase, // optional passhrase (required if set while generating keypair).
|
|
1065
1098
|
},
|
|
1066
|
-
{ input, output }
|
|
1067
|
-
)
|
|
1099
|
+
{ input, output },
|
|
1100
|
+
)
|
|
1068
1101
|
|
|
1069
|
-
console.log(Buffer.concat(chunks).toString())
|
|
1102
|
+
console.log(Buffer.concat(chunks).toString()) // Outputs: 'my top-secret data'
|
|
1070
1103
|
```
|
|
1071
1104
|
|
|
1072
1105
|
---
|
|
@@ -1078,16 +1111,16 @@ Nothig differs from the [In-memory data stream encryption/decryption](#in-memory
|
|
|
1078
1111
|
##### Encrypt a file
|
|
1079
1112
|
|
|
1080
1113
|
```ts
|
|
1081
|
-
import fs from
|
|
1114
|
+
import fs from 'fs'
|
|
1082
1115
|
|
|
1083
|
-
const password =
|
|
1116
|
+
const password = 'my-very-strong-password'
|
|
1084
1117
|
|
|
1085
1118
|
// input where raw data to encrypt is read
|
|
1086
|
-
const input = fs.createReadStream(
|
|
1119
|
+
const input = fs.createReadStream('my-very-large-top-secret-file.pdf')
|
|
1087
1120
|
// output where encrypted data is written
|
|
1088
|
-
const output = fs.createWriteStream(
|
|
1121
|
+
const output = fs.createWriteStream('my-very-large-top-secret-file.encrypted')
|
|
1089
1122
|
// encrypt
|
|
1090
|
-
await Cipher.stream.Encrypt(password, { input, output })
|
|
1123
|
+
await Cipher.stream.Encrypt(password, { input, output })
|
|
1091
1124
|
```
|
|
1092
1125
|
|
|
1093
1126
|
---
|
|
@@ -1095,18 +1128,16 @@ await Cipher.stream.Encrypt(password, { input, output });
|
|
|
1095
1128
|
##### Decrypt a file
|
|
1096
1129
|
|
|
1097
1130
|
```ts
|
|
1098
|
-
import fs from
|
|
1131
|
+
import fs from 'fs'
|
|
1099
1132
|
|
|
1100
|
-
const password =
|
|
1133
|
+
const password = 'my-very-strong-password'
|
|
1101
1134
|
|
|
1102
1135
|
// input where encrypted data is read
|
|
1103
|
-
const input = fs.createReadStream(
|
|
1136
|
+
const input = fs.createReadStream('my-very-large-top-secret-file.encrypted')
|
|
1104
1137
|
// output where decrypted data is written
|
|
1105
|
-
const output = fs.createWriteStream(
|
|
1106
|
-
"my-very-large-top-secret-file-decrypted.pdf"
|
|
1107
|
-
);
|
|
1138
|
+
const output = fs.createWriteStream('my-very-large-top-secret-file-decrypted.pdf')
|
|
1108
1139
|
// decrypt
|
|
1109
|
-
await Cipher.stream.Decrypt(password, { input, output })
|
|
1140
|
+
await Cipher.stream.Decrypt(password, { input, output })
|
|
1110
1141
|
```
|
|
1111
1142
|
|
|
1112
1143
|
---
|
|
@@ -1128,40 +1159,40 @@ Nothig differs from the [In-memory data stream with hybrid encryption/decryption
|
|
|
1128
1159
|
##### Keypair
|
|
1129
1160
|
|
|
1130
1161
|
```ts
|
|
1131
|
-
import { Cipher } from
|
|
1162
|
+
import { Cipher } from '@alessiofrittoli/crypto-cipher'
|
|
1132
1163
|
|
|
1133
|
-
const keyPair = crypto.generateKeyPairSync(
|
|
1164
|
+
const keyPair = crypto.generateKeyPairSync('rsa', {
|
|
1134
1165
|
modulusLength: 512 * 8, // 4096 bits
|
|
1135
|
-
publicKeyEncoding: { type:
|
|
1136
|
-
privateKeyEncoding: { type:
|
|
1137
|
-
})
|
|
1166
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
1167
|
+
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
|
|
1168
|
+
})
|
|
1138
1169
|
|
|
1139
1170
|
// or you can optionally set a custom passphrase
|
|
1140
|
-
const passphrase =
|
|
1171
|
+
const passphrase = 'custompassphrase'
|
|
1141
1172
|
|
|
1142
|
-
const keyPair = crypto.generateKeyPairSync(
|
|
1173
|
+
const keyPair = crypto.generateKeyPairSync('rsa', {
|
|
1143
1174
|
modulusLength: 512 * 8, // 4096 bits
|
|
1144
|
-
publicKeyEncoding: { type:
|
|
1175
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
1145
1176
|
privateKeyEncoding: {
|
|
1146
|
-
type:
|
|
1147
|
-
format:
|
|
1177
|
+
type: 'pkcs1',
|
|
1178
|
+
format: 'pem',
|
|
1148
1179
|
passphrase,
|
|
1149
1180
|
cipher: Cipher.ALGORITHM.CHACHA_20_POLY,
|
|
1150
1181
|
},
|
|
1151
|
-
})
|
|
1182
|
+
})
|
|
1152
1183
|
```
|
|
1153
1184
|
|
|
1154
1185
|
##### Encrypt a file
|
|
1155
1186
|
|
|
1156
1187
|
```ts
|
|
1157
|
-
import fs from
|
|
1188
|
+
import fs from 'fs'
|
|
1158
1189
|
|
|
1159
1190
|
// input where raw data to encrypt is read
|
|
1160
|
-
const input = fs.createReadStream(
|
|
1191
|
+
const input = fs.createReadStream('my-very-large-top-secret-file.pdf')
|
|
1161
1192
|
// output where encrypted data is written
|
|
1162
|
-
const output = fs.createWriteStream(
|
|
1193
|
+
const output = fs.createWriteStream('my-very-large-top-secret-file.encrypted')
|
|
1163
1194
|
// encrypt
|
|
1164
|
-
await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output })
|
|
1195
|
+
await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output })
|
|
1165
1196
|
```
|
|
1166
1197
|
|
|
1167
1198
|
---
|
|
@@ -1169,61 +1200,63 @@ await Cipher.stream.HybridEncrypt(keyPair.publicKey, { input, output });
|
|
|
1169
1200
|
##### Decrypt a file
|
|
1170
1201
|
|
|
1171
1202
|
```ts
|
|
1172
|
-
import fs from
|
|
1203
|
+
import fs from 'fs'
|
|
1173
1204
|
|
|
1174
1205
|
// input where encrypted data is read
|
|
1175
|
-
const input = fs.createReadStream(
|
|
1206
|
+
const input = fs.createReadStream('my-very-large-top-secret-file.encrypted')
|
|
1176
1207
|
// output where decrypted data is written
|
|
1177
|
-
const output = fs.createWriteStream(
|
|
1178
|
-
"my-very-large-top-secret-file-decrypted.pdf"
|
|
1179
|
-
);
|
|
1208
|
+
const output = fs.createWriteStream('my-very-large-top-secret-file-decrypted.pdf')
|
|
1180
1209
|
// decrypt
|
|
1181
1210
|
const { decrypt } = await Cipher.stream.HybridDecrypt(
|
|
1182
1211
|
{
|
|
1183
1212
|
key: keyPair.privateKey,
|
|
1184
1213
|
passphrase, // optional passhrase (required if set while generating keypair).
|
|
1185
1214
|
},
|
|
1186
|
-
{ input, output }
|
|
1187
|
-
)
|
|
1215
|
+
{ input, output },
|
|
1216
|
+
)
|
|
1188
1217
|
```
|
|
1189
1218
|
|
|
1190
1219
|
---
|
|
1191
1220
|
|
|
1192
1221
|
### Development
|
|
1193
1222
|
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
```bash
|
|
1197
|
-
npm install
|
|
1198
|
-
```
|
|
1223
|
+
Run the following to start development
|
|
1199
1224
|
|
|
1200
|
-
|
|
1225
|
+
```shell
|
|
1226
|
+
nvm use
|
|
1201
1227
|
|
|
1202
|
-
```bash
|
|
1203
1228
|
pnpm i
|
|
1204
1229
|
```
|
|
1205
1230
|
|
|
1206
|
-
####
|
|
1231
|
+
#### Local development
|
|
1207
1232
|
|
|
1208
|
-
Run the following
|
|
1233
|
+
Run the following
|
|
1209
1234
|
|
|
1210
|
-
```
|
|
1211
|
-
pnpm
|
|
1235
|
+
```shell
|
|
1236
|
+
pnpm dev
|
|
1212
1237
|
```
|
|
1213
1238
|
|
|
1214
|
-
|
|
1239
|
+
This will generate unminified output code, sourcemaps and will enable source file watcher.
|
|
1215
1240
|
|
|
1216
|
-
|
|
1241
|
+
---
|
|
1217
1242
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1243
|
+
#### Production build
|
|
1244
|
+
|
|
1245
|
+
Run the following to create a local production build
|
|
1246
|
+
|
|
1247
|
+
```shell
|
|
1248
|
+
pnpm build
|
|
1220
1249
|
```
|
|
1221
1250
|
|
|
1222
|
-
|
|
1251
|
+
This will generate minified output code without sourcemaps.
|
|
1252
|
+
|
|
1253
|
+
---
|
|
1254
|
+
|
|
1255
|
+
#### Unit tests
|
|
1223
1256
|
|
|
1224
1257
|
Run all the defined test suites by running the following:
|
|
1225
1258
|
|
|
1226
|
-
```
|
|
1259
|
+
```shell
|
|
1227
1260
|
# Run tests and watch file changes.
|
|
1228
1261
|
pnpm test:watch
|
|
1229
1262
|
|
|
@@ -1231,21 +1264,21 @@ pnpm test:watch
|
|
|
1231
1264
|
pnpm test:ci
|
|
1232
1265
|
```
|
|
1233
1266
|
|
|
1234
|
-
|
|
1267
|
+
---
|
|
1235
1268
|
|
|
1236
|
-
Run tests with coverage
|
|
1269
|
+
##### Run tests with coverage
|
|
1237
1270
|
|
|
1238
1271
|
An HTTP server is then started to serve coverage files from `./coverage` folder.
|
|
1239
1272
|
|
|
1240
1273
|
⚠️ You may see a blank page the first time you run this command. Simply refresh the browser to see the updates.
|
|
1241
1274
|
|
|
1242
|
-
```
|
|
1243
|
-
test:coverage:serve
|
|
1275
|
+
```shell
|
|
1276
|
+
pnpm test:coverage:serve
|
|
1244
1277
|
```
|
|
1245
1278
|
|
|
1246
1279
|
---
|
|
1247
1280
|
|
|
1248
|
-
|
|
1281
|
+
#### Contributing
|
|
1249
1282
|
|
|
1250
1283
|
Contributions are truly welcome!
|
|
1251
1284
|
|
|
@@ -1257,7 +1290,7 @@ Help keep this project up to date with [GitHub Sponsor][sponsor-url].
|
|
|
1257
1290
|
|
|
1258
1291
|
---
|
|
1259
1292
|
|
|
1260
|
-
|
|
1293
|
+
#### Security
|
|
1261
1294
|
|
|
1262
1295
|
If you believe you have found a security vulnerability, we encourage you to **_responsibly disclose this and NOT open a public issue_**. We will investigate all legitimate reports. Email `security@alessiofrittoli.it` to disclose any security vulnerabilities.
|
|
1263
1296
|
|