• 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      message: 'The "key" argument must be of type string or an instance of ' +
105               'Buffer, TypedArray, DataView, or KeyObject. Received null'
106    });
107
108  assert.throws(
109    () => crypto.createCipheriv('des-ede3-cbc', key, 10),
110    {
111      code: 'ERR_INVALID_ARG_TYPE',
112      name: 'TypeError',
113      message: 'The "iv" argument must be of type string or an instance of ' +
114               'Buffer, TypedArray, or DataView. Received type number (10)'
115    });
116}
117
118{
119  const Decipheriv = crypto.Decipheriv;
120  const key = '123456789012345678901234';
121  const iv = '12345678';
122
123  const instance = Decipheriv('des-ede3-cbc', key, iv);
124  assert(instance instanceof Decipheriv, 'Decipheriv expected to return a new' +
125                                         ' instance when called without `new`');
126
127  assert.throws(
128    () => crypto.createDecipheriv(null),
129    {
130      code: 'ERR_INVALID_ARG_TYPE',
131      name: 'TypeError',
132      message: 'The "cipher" argument must be of type string. ' +
133               'Received null'
134    });
135
136  assert.throws(
137    () => crypto.createDecipheriv('des-ede3-cbc', null),
138    {
139      code: 'ERR_INVALID_ARG_TYPE',
140      name: 'TypeError',
141      message: 'The "key" argument must be of type string or an instance of ' +
142               'Buffer, TypedArray, DataView, or KeyObject. Received null'
143    });
144
145  assert.throws(
146    () => crypto.createDecipheriv('des-ede3-cbc', key, 10),
147    {
148      code: 'ERR_INVALID_ARG_TYPE',
149      name: 'TypeError',
150      message: 'The "iv" argument must be of type string or an instance of ' +
151               'Buffer, TypedArray, or DataView. Received type number (10)'
152    });
153}
154
155testCipher1('0123456789abcd0123456789', '12345678');
156testCipher1('0123456789abcd0123456789', Buffer.from('12345678'));
157testCipher1(Buffer.from('0123456789abcd0123456789'), '12345678');
158testCipher1(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
159testCipher2(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
160
161if (!common.hasFipsCrypto) {
162  testCipher3(Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex'),
163              Buffer.from('A6A6A6A6A6A6A6A6', 'hex'));
164}
165
166// Zero-sized IV or null should be accepted in ECB mode.
167crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), Buffer.alloc(0));
168crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), null);
169
170const errMessage = /Invalid IV length/;
171
172// But non-empty IVs should be rejected.
173for (let n = 1; n < 256; n += 1) {
174  assert.throws(
175    () => crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16),
176                                Buffer.alloc(n)),
177    errMessage);
178}
179
180// Correctly sized IV should be accepted in CBC mode.
181crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), Buffer.alloc(16));
182
183// But all other IV lengths should be rejected.
184for (let n = 0; n < 256; n += 1) {
185  if (n === 16) continue;
186  assert.throws(
187    () => crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16),
188                                Buffer.alloc(n)),
189    errMessage);
190}
191
192// And so should null be.
193assert.throws(() => {
194  crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), null);
195}, /Missing IV for cipher aes-128-cbc/);
196
197// Zero-sized IV should be rejected in GCM mode.
198assert.throws(
199  () => crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16),
200                              Buffer.alloc(0)),
201  errMessage);
202
203// But all other IV lengths should be accepted.
204for (let n = 1; n < 256; n += 1) {
205  if (common.hasFipsCrypto && n < 12) continue;
206  crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), Buffer.alloc(n));
207}
208
209{
210  // Passing an invalid cipher name should throw.
211  assert.throws(
212    () => crypto.createCipheriv('aes-127', Buffer.alloc(16), null),
213    {
214      name: 'Error',
215      code: 'ERR_CRYPTO_UNKNOWN_CIPHER',
216      message: 'Unknown cipher'
217    });
218
219  // Passing a key with an invalid length should throw.
220  assert.throws(
221    () => crypto.createCipheriv('aes-128-ecb', Buffer.alloc(17), null),
222    /Invalid key length/);
223}
224