• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const common = require('../common');
4
5if (!common.hasCrypto)
6  common.skip('missing crypto');
7
8const assert = require('assert');
9const { webcrypto } = require('crypto');
10const { subtle } = webcrypto;
11
12{
13  async function test() {
14    const keyData = webcrypto.getRandomValues(new Uint8Array(32));
15    await Promise.all([1, null, undefined, {}, []].map((format) =>
16      assert.rejects(
17        subtle.importKey(format, keyData, {}, false, ['wrapKey']), {
18          code: 'ERR_INVALID_ARG_VALUE'
19        })
20    ));
21    await assert.rejects(
22      subtle.importKey('not valid', keyData, {}, false, ['wrapKey']), {
23        code: 'ERR_INVALID_ARG_VALUE'
24      });
25    await assert.rejects(
26      subtle.importKey('raw', 1, {}, false, ['deriveBits']), {
27        code: 'ERR_INVALID_ARG_TYPE'
28      });
29    await assert.rejects(
30      subtle.importKey('raw', keyData, {
31        name: 'HMAC'
32      }, false, ['sign', 'verify']), {
33        code: 'ERR_MISSING_OPTION'
34      });
35    await assert.rejects(
36      subtle.importKey('raw', keyData, {
37        name: 'HMAC',
38        hash: 'SHA-256'
39      }, false, ['deriveBits']), {
40        name: 'SyntaxError',
41        message: 'Unsupported key usage for an HMAC key'
42      });
43    await assert.rejects(
44      subtle.importKey('raw', keyData, {
45        name: 'HMAC',
46        hash: 'SHA-256',
47        length: 0
48      }, false, ['sign', 'verify']), {
49        name: 'DataError',
50        message: 'Zero-length key is not supported'
51      });
52    await assert.rejects(
53      subtle.importKey('raw', keyData, {
54        name: 'HMAC',
55        hash: 'SHA-256',
56        length: 1
57      }, false, ['sign', 'verify']), {
58        name: 'DataError',
59        message: 'Invalid key length'
60      });
61    await assert.rejects(
62      subtle.importKey('jwk', null, {
63        name: 'HMAC',
64        hash: 'SHA-256',
65      }, false, ['sign', 'verify']), {
66        name: 'DataError',
67        message: 'Invalid keyData'
68      });
69  }
70
71  test().then(common.mustCall());
72}
73
74// Import/Export HMAC Secret Key
75{
76  async function test() {
77    const keyData = webcrypto.getRandomValues(new Uint8Array(32));
78    const key = await subtle.importKey(
79      'raw',
80      keyData, {
81        name: 'HMAC',
82        hash: 'SHA-256'
83      }, true, ['sign', 'verify']);
84
85    const raw = await subtle.exportKey('raw', key);
86
87    assert.deepStrictEqual(
88      Buffer.from(keyData).toString('hex'),
89      Buffer.from(raw).toString('hex'));
90
91    const jwk = await subtle.exportKey('jwk', key);
92    assert.deepStrictEqual(jwk.key_ops, ['sign', 'verify']);
93    assert(jwk.ext);
94    assert.strictEqual(jwk.kty, 'oct');
95
96    assert.deepStrictEqual(
97      Buffer.from(jwk.k, 'base64').toString('hex'),
98      Buffer.from(raw).toString('hex'));
99
100    await assert.rejects(
101      subtle.importKey(
102        'raw',
103        keyData,
104        {
105          name: 'HMAC',
106          hash: 'SHA-256'
107        },
108        true,
109        [/* empty usages */]),
110      { name: 'SyntaxError', message: 'Usages cannot be empty when importing a secret key.' });
111  }
112
113  test().then(common.mustCall());
114}
115
116// Import/Export AES Secret Key
117{
118  async function test() {
119    const keyData = webcrypto.getRandomValues(new Uint8Array(32));
120    const key = await subtle.importKey(
121      'raw',
122      keyData, {
123        name: 'AES-CTR',
124        length: 256,
125      }, true, ['encrypt', 'decrypt']);
126
127    const raw = await subtle.exportKey('raw', key);
128
129    assert.deepStrictEqual(
130      Buffer.from(keyData).toString('hex'),
131      Buffer.from(raw).toString('hex'));
132
133    const jwk = await subtle.exportKey('jwk', key);
134    assert.deepStrictEqual(jwk.key_ops, ['encrypt', 'decrypt']);
135    assert(jwk.ext);
136    assert.strictEqual(jwk.kty, 'oct');
137
138    assert.deepStrictEqual(
139      Buffer.from(jwk.k, 'base64').toString('hex'),
140      Buffer.from(raw).toString('hex'));
141
142    await assert.rejects(
143      subtle.importKey(
144        'raw',
145        keyData,
146        {
147          name: 'AES-CTR',
148          length: 256,
149        },
150        true,
151        [/* empty usages */]),
152      { name: 'SyntaxError', message: 'Usages cannot be empty when importing a secret key.' });
153  }
154
155  test().then(common.mustCall());
156}
157
158// Import/Export RSA Key Pairs
159{
160  async function test() {
161    const { publicKey, privateKey } = await subtle.generateKey({
162      name: 'RSA-PSS',
163      modulusLength: 1024,
164      publicExponent: new Uint8Array([1, 0, 1]),
165      hash: 'SHA-384'
166    }, true, ['sign', 'verify']);
167
168    const [
169      spki,
170      pkcs8,
171      publicJwk,
172      privateJwk,
173    ] = await Promise.all([
174      subtle.exportKey('spki', publicKey),
175      subtle.exportKey('pkcs8', privateKey),
176      subtle.exportKey('jwk', publicKey),
177      subtle.exportKey('jwk', privateKey),
178    ]);
179
180    assert(spki);
181    assert(pkcs8);
182    assert(publicJwk);
183    assert(privateJwk);
184
185    const [
186      importedSpkiPublicKey,
187      importedPkcs8PrivateKey,
188      importedJwkPublicKey,
189      importedJwkPrivateKey,
190    ] = await Promise.all([
191      subtle.importKey('spki', spki, {
192        name: 'RSA-PSS',
193        hash: 'SHA-384',
194      }, true, ['verify']),
195      subtle.importKey('pkcs8', pkcs8, {
196        name: 'RSA-PSS',
197        hash: 'SHA-384',
198      }, true, ['sign']),
199      subtle.importKey('jwk', publicJwk, {
200        name: 'RSA-PSS',
201        hash: 'SHA-384',
202      }, true, ['verify']),
203      subtle.importKey('jwk', privateJwk, {
204        name: 'RSA-PSS',
205        hash: 'SHA-384',
206      }, true, ['sign']),
207    ]);
208
209    assert(importedSpkiPublicKey);
210    assert(importedPkcs8PrivateKey);
211    assert(importedJwkPublicKey);
212    assert(importedJwkPrivateKey);
213  }
214
215  test().then(common.mustCall());
216}
217
218// Import/Export EC Key Pairs
219{
220  async function test() {
221    const { publicKey, privateKey } = await subtle.generateKey({
222      name: 'ECDSA',
223      namedCurve: 'P-384'
224    }, true, ['sign', 'verify']);
225
226    const [
227      spki,
228      pkcs8,
229      publicJwk,
230      privateJwk,
231    ] = await Promise.all([
232      subtle.exportKey('spki', publicKey),
233      subtle.exportKey('pkcs8', privateKey),
234      subtle.exportKey('jwk', publicKey),
235      subtle.exportKey('jwk', privateKey),
236    ]);
237
238    assert(spki);
239    assert(pkcs8);
240    assert(publicJwk);
241    assert(privateJwk);
242
243    const [
244      importedSpkiPublicKey,
245      importedPkcs8PrivateKey,
246      importedJwkPublicKey,
247      importedJwkPrivateKey,
248    ] = await Promise.all([
249      subtle.importKey('spki', spki, {
250        name: 'ECDSA',
251        namedCurve: 'P-384'
252      }, true, ['verify']),
253      subtle.importKey('pkcs8', pkcs8, {
254        name: 'ECDSA',
255        namedCurve: 'P-384'
256      }, true, ['sign']),
257      subtle.importKey('jwk', publicJwk, {
258        name: 'ECDSA',
259        namedCurve: 'P-384'
260      }, true, ['verify']),
261      subtle.importKey('jwk', privateJwk, {
262        name: 'ECDSA',
263        namedCurve: 'P-384'
264      }, true, ['sign']),
265    ]);
266
267    assert(importedSpkiPublicKey);
268    assert(importedPkcs8PrivateKey);
269    assert(importedJwkPublicKey);
270    assert(importedJwkPrivateKey);
271  }
272
273  test().then(common.mustCall());
274}
275