1 | var assert = require('assert'); |
||
2 | var sjcl = require('sjcl'); |
||
3 | var KeyDerivation = require('./keyderivation'); |
||
4 | var randomBytes = require('randombytes'); |
||
5 | |||
6 | var Encryption = { |
||
7 | defaultSaltLen: 10, /* can permit changes, no more than 512 bit (128 bytes) */ |
||
8 | tagLenBits: 128, /* can permit changes */ |
||
9 | ivLenBits: 128, /* fixed */ |
||
10 | ivLenWords: 128 / 32 |
||
11 | }; |
||
12 | |||
13 | Encryption.generateSalt = function() { |
||
14 | return randomBytes(this.defaultSaltLen); |
||
15 | }; |
||
16 | |||
17 | Encryption.generateIV = function() { |
||
18 | return randomBytes(this.ivLenBits / 8); |
||
19 | }; |
||
20 | |||
21 | Encryption.encrypt = function(pt, pw, iterations) { |
||
22 | var salt = this.generateSalt(); |
||
23 | var iv = this.generateIV(); |
||
24 | |||
25 | iterations = typeof iterations === 'undefined' ? KeyDerivation.defaultIterations : iterations; |
||
26 | return this.encryptWithSaltAndIV(pt, pw, salt, iv, iterations); |
||
27 | }; |
||
28 | |||
29 | Encryption.encryptWithSaltAndIV = function(pt, pw, saltBuf, iv, iterations) { |
||
30 | assert(pt instanceof Buffer, 'pt must be provided as a buffer'); |
||
0 ignored issues
–
show
|
|||
31 | assert(pw instanceof Buffer, 'pw must be provided as a buffer'); |
||
32 | assert(iv instanceof Buffer, 'IV must be provided as a buffer'); |
||
33 | assert(saltBuf instanceof Buffer, 'saltBuff must be provided as a buffer'); |
||
34 | assert(iv.length === 16, 'IV must be exactly 16 bytes'); |
||
35 | |||
36 | var SL = (new Buffer(1)); |
||
37 | var S = saltBuf; |
||
38 | var I = new Buffer(4); |
||
39 | SL.writeUInt8(saltBuf.length); |
||
40 | I.writeUInt32LE(iterations); |
||
41 | var header = SL.toString('hex') + S.toString('hex') + I.toString('hex'); |
||
42 | |||
43 | var key = sjcl.codec.hex.toBits(KeyDerivation.compute(pw, saltBuf, iterations).toString('hex')); |
||
44 | var ct_t = sjcl.mode.gcm.encrypt( |
||
45 | new sjcl.cipher.aes(key), |
||
46 | sjcl.codec.hex.toBits(pt.toString('hex')), |
||
47 | sjcl.codec.hex.toBits(iv.toString('hex')), |
||
48 | sjcl.codec.hex.toBits(header), |
||
49 | this.tagLenBits |
||
50 | ); |
||
51 | |||
52 | // iter || saltLen8 || salt || iv || tag || ct |
||
53 | return new Buffer([header, iv.toString('hex'), sjcl.codec.hex.fromBits(ct_t)].join(''), 'hex'); |
||
54 | }; |
||
55 | |||
56 | Encryption.decrypt = function(ct, pw) { |
||
57 | assert(ct instanceof Buffer, 'cipherText must be provided as a Buffer'); |
||
0 ignored issues
–
show
The variable
Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed. To learn more about declaring variables in Javascript, see the MDN. ![]() |
|||
58 | assert(pw instanceof Buffer, 'password must be provided as a Buffer'); |
||
59 | var copy = new Buffer(ct, 'hex'); |
||
60 | var c = 0; |
||
61 | |||
62 | var saltLen = copy.readUInt8(c) ; c += 1; |
||
63 | var salt = copy.slice(1, c + saltLen); c += saltLen; |
||
64 | var iterations = copy.readUInt32LE(c); c += 4; |
||
65 | var header = copy.slice(0, c); |
||
66 | |||
67 | var iv = copy.slice(c, 16 + c); c += 16; |
||
68 | var ct_t = copy.slice(c); |
||
69 | |||
70 | // SaltBuf is required for KeyDerivation. Convert to sjcl where required. |
||
71 | var key = KeyDerivation.compute(pw, salt, iterations); |
||
72 | var plainText = sjcl.mode.gcm.decrypt( |
||
73 | new sjcl.cipher.aes(sjcl.codec.hex.toBits(key.toString('hex'))), |
||
74 | sjcl.codec.hex.toBits(ct_t.toString('hex')), |
||
75 | sjcl.codec.hex.toBits(iv.toString('hex')), |
||
76 | sjcl.codec.hex.toBits(header.toString('hex')), |
||
77 | this.tagLenBits |
||
78 | ); |
||
79 | return new Buffer(sjcl.codec.hex.fromBits(plainText), 'hex'); |
||
80 | }; |
||
81 | |||
82 | module.exports = Encryption; |
||
83 |
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.