-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcrypt.js
77 lines (69 loc) · 2.05 KB
/
crypt.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
const stream = require('stream')
const crypto = require('crypto')
const CIPHER = 'aes-256-cbc'
const IVSIZE = 16
class IVReader extends stream.Transform {
constructor(options) {
super(options)
this.iv = Buffer.alloc(0)
}
_transform(chunk, encoding, callback) {
if (this.iv.length == IVSIZE) {
this.push(chunk)
} else {
let nbytes = IVSIZE - this.iv.length
let ivpart = chunk.slice(0, nbytes)
this.iv = Buffer.concat([this.iv, ivpart])
if (this.iv.length == IVSIZE) {
this.emit('iv', this.iv);
}
this.push(chunk.slice(nbytes))
}
callback()
}
}
const decryptStream = (key, input, output, encoding = null) => {
let options = {}
if (encoding) {
// input outputs strings so we can decode them as
// defaultEncoding
input.setEncoding('utf8')
options = {defaultEncoding: encoding, decodeStrings: true}
}
let ivr = new IVReader(options)
input.pipe(ivr)
ivr.on('iv', (iv) => {
let deci = crypto.createDecipheriv(CIPHER, key, iv)
ivr.pipe(deci).pipe(output)
})
}
const encryptStream = (key, input, output, encoding = null) => {
let iv = crypto.randomBytes(IVSIZE)
// use passthrough to recode stream joining iv + ciph
let p = new stream.PassThrough(encoding ? {encoding: encoding} : {})
// write the iv before we do anything
p.write(iv, () => {
let ciph = crypto.createCipheriv(CIPHER, key, iv)
input.pipe(ciph).pipe(p).pipe(output)
})
}
const cryptString = (pher, key, input, encoding = null) => {
let output = new stream.PassThrough()
pher(key, stream.Readable.from(input), output, encoding)
let result = ""
output.on('data', (d) => result += d)
return new Promise((resolve) => output.on('end', () => {
resolve(result)}))
}
const decryptString = (key, input, encoding = null) => {
return cryptString(decryptStream, key, input, encoding)
}
const encryptString = (key, input, encoding = null) => {
return cryptString(encryptStream, key, input, encoding)
}
module.exports = {
encryptStream,
decryptStream,
decryptString,
encryptString,
}