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