• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3if (!common.hasCrypto)
4  common.skip('missing crypto');
5
6const assert = require('assert');
7const crypto = require('crypto');
8
9function testCipher1(key, iv) {
10  // Test encryption and decryption with explicit key and iv
11  const plaintext =
12          '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
13          'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
14          'jAfaFg**';
15  const cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
16  let ciph = cipher.update(plaintext, 'utf8', 'hex');
17  ciph += cipher.final('hex');
18
19  const decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
20  let txt = decipher.update(ciph, 'hex', 'utf8');
21  txt += decipher.final('utf8');
22
23  assert.strictEqual(txt, plaintext,
24                     `encryption/decryption with key ${key} and iv ${iv}`);
25
26  // Streaming cipher interface
27  // NB: In real life, it's not guaranteed that you can get all of it
28  // in a single read() like this.  But in this case, we know it's
29  // quite small, so there's no harm.
30  const cStream = crypto.createCipheriv('des-ede3-cbc', key, iv);
31  cStream.end(plaintext);
32  ciph = cStream.read();
33
34  const dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv);
35  dStream.end(ciph);
36  txt = dStream.read().toString('utf8');
37
38  assert.strictEqual(txt, plaintext,
39                     `streaming cipher with key ${key} and iv ${iv}`);
40}
41
42
43function testCipher2(key, iv) {
44  // Test encryption and decryption with explicit key and iv
45  const plaintext =
46          '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
47          'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
48          'jAfaFg**';
49  const cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
50  let ciph = cipher.update(plaintext, 'utf8', 'buffer');
51  ciph = Buffer.concat([ciph, cipher.final('buffer')]);
52
53  const decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
54  let txt = decipher.update(ciph, 'buffer', 'utf8');
55  txt += decipher.final('utf8');
56
57  assert.strictEqual(txt, plaintext,
58                     `encryption/decryption with key ${key} and iv ${iv}`);
59}
60
61
62function testCipher3(key, iv) {
63  // Test encryption and decryption with explicit key and iv.
64  // AES Key Wrap test vector comes from RFC3394
65  const plaintext = Buffer.from('00112233445566778899AABBCCDDEEFF', 'hex');
66
67  const cipher = crypto.createCipheriv('id-aes128-wrap', key, iv);
68  let ciph = cipher.update(plaintext, 'utf8', 'buffer');
69  ciph = Buffer.concat([ciph, cipher.final('buffer')]);
70  const ciph2 = Buffer.from('1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5',
71                            'hex');
72  assert(ciph.equals(ciph2));
73  const decipher = crypto.createDecipheriv('id-aes128-wrap', key, iv);
74  let deciph = decipher.update(ciph, 'buffer');
75  deciph = Buffer.concat([deciph, decipher.final()]);
76
77  assert(deciph.equals(plaintext),
78         `encryption/decryption with key ${key} and iv ${iv}`);
79}
80
81{
82  const Cipheriv = crypto.Cipheriv;
83  const key = '123456789012345678901234';
84  const iv = '12345678';
85
86  const instance = Cipheriv('des-ede3-cbc', key, iv);
87  assert(instance instanceof Cipheriv, 'Cipheriv is expected to return a new ' +
88                                       'instance when called without `new`');
89
90  assert.throws(
91    () => crypto.createCipheriv(null),
92    {
93      code: 'ERR_INVALID_ARG_TYPE',
94      name: 'TypeError',
95      message: 'The "cipher" argument must be of type string. ' +
96               'Received null'
97    });
98
99  assert.throws(
100    () => crypto.createCipheriv('des-ede3-cbc', null),
101    {
102      code: 'ERR_INVALID_ARG_TYPE',
103      name: 'TypeError',
104    });
105
106  assert.throws(
107    () => crypto.createCipheriv('des-ede3-cbc', key, 10),
108    {
109      code: 'ERR_INVALID_ARG_TYPE',
110      name: 'TypeError',
111    });
112}
113
114{
115  const Decipheriv = crypto.Decipheriv;
116  const key = '123456789012345678901234';
117  const iv = '12345678';
118
119  const instance = Decipheriv('des-ede3-cbc', key, iv);
120  assert(instance instanceof Decipheriv, 'Decipheriv expected to return a new' +
121                                         ' instance when called without `new`');
122
123  assert.throws(
124    () => crypto.createDecipheriv(null),
125    {
126      code: 'ERR_INVALID_ARG_TYPE',
127      name: 'TypeError',
128      message: 'The "cipher" argument must be of type string. ' +
129               'Received null'
130    });
131
132  assert.throws(
133    () => crypto.createDecipheriv('des-ede3-cbc', null),
134    {
135      code: 'ERR_INVALID_ARG_TYPE',
136      name: 'TypeError',
137    });
138
139  assert.throws(
140    () => crypto.createDecipheriv('des-ede3-cbc', key, 10),
141    {
142      code: 'ERR_INVALID_ARG_TYPE',
143      name: 'TypeError',
144    });
145}
146
147testCipher1('0123456789abcd0123456789', '12345678');
148testCipher1('0123456789abcd0123456789', Buffer.from('12345678'));
149testCipher1(Buffer.from('0123456789abcd0123456789'), '12345678');
150testCipher1(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
151testCipher2(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
152
153if (!common.hasFipsCrypto) {
154  testCipher3(Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex'),
155              Buffer.from('A6A6A6A6A6A6A6A6', 'hex'));
156}
157
158// Zero-sized IV or null should be accepted in ECB mode.
159crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), Buffer.alloc(0));
160crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), null);
161
162const errMessage = /Invalid initialization vector/;
163
164// But non-empty IVs should be rejected.
165for (let n = 1; n < 256; n += 1) {
166  assert.throws(
167    () => crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16),
168                                Buffer.alloc(n)),
169    errMessage);
170}
171
172// Correctly sized IV should be accepted in CBC mode.
173crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), Buffer.alloc(16));
174
175// But all other IV lengths should be rejected.
176for (let n = 0; n < 256; n += 1) {
177  if (n === 16) continue;
178  assert.throws(
179    () => crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16),
180                                Buffer.alloc(n)),
181    errMessage);
182}
183
184// And so should null be.
185assert.throws(() => {
186  crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), null);
187}, /Invalid initialization vector/);
188
189// Zero-sized IV should be rejected in GCM mode.
190assert.throws(
191  () => crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16),
192                              Buffer.alloc(0)),
193  errMessage);
194
195// But all other IV lengths should be accepted.
196const minIvLength = common.hasOpenSSL3 ? 8 : 1;
197const maxIvLength = common.hasOpenSSL3 ? 64 : 256;
198for (let n = minIvLength; n < maxIvLength; n += 1) {
199  if (common.hasFipsCrypto && n < 12) continue;
200  crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), Buffer.alloc(n));
201}
202
203{
204  // Passing an invalid cipher name should throw.
205  assert.throws(
206    () => crypto.createCipheriv('aes-127', Buffer.alloc(16), null),
207    {
208      name: 'Error',
209      code: 'ERR_CRYPTO_UNKNOWN_CIPHER',
210      message: 'Unknown cipher'
211    });
212
213  // Passing a key with an invalid length should throw.
214  assert.throws(
215    () => crypto.createCipheriv('aes-128-ecb', Buffer.alloc(17), null),
216    /Invalid key length/);
217}
218
219{
220  // https://github.com/nodejs/node/issues/45757
221  // eslint-disable-next-line no-restricted-syntax
222  assert.throws(() =>
223    crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), Buffer.alloc(12))
224    .update(Buffer.allocUnsafeSlow(2 ** 31 - 1)));
225}
226