| // META: title=WebCrypto API: supports method tests | |
| // META: script=util/helpers.js | |
| // META: script=util/supports.js | |
| 'use strict'; | |
| const standardAlgorithms = { | |
| // Asymmetric algorithms | |
| 'RSASSA-PKCS1-v1_5': { | |
| operations: ['generateKey', 'importKey', 'sign', 'verify', 'getPublicKey'], | |
| keyGenParams: { | |
| name: 'RSASSA-PKCS1-v1_5', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array([1, 0, 1]), | |
| hash: 'SHA-256', | |
| }, | |
| importParams: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, | |
| signParams: { name: 'RSASSA-PKCS1-v1_5' }, | |
| }, | |
| 'RSA-PSS': { | |
| operations: ['generateKey', 'importKey', 'sign', 'verify', 'getPublicKey'], | |
| keyGenParams: { | |
| name: 'RSA-PSS', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array([1, 0, 1]), | |
| hash: 'SHA-256', | |
| }, | |
| importParams: { name: 'RSA-PSS', hash: 'SHA-256' }, | |
| signParams: { name: 'RSA-PSS', saltLength: 32 }, | |
| }, | |
| 'RSA-OAEP': { | |
| operations: ['generateKey', 'importKey', 'encrypt', 'decrypt', 'getPublicKey'], | |
| keyGenParams: { | |
| name: 'RSA-OAEP', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array([1, 0, 1]), | |
| hash: 'SHA-256', | |
| }, | |
| importParams: { name: 'RSA-OAEP', hash: 'SHA-256' }, | |
| encryptParams: { name: 'RSA-OAEP' }, | |
| }, | |
| ECDSA: { | |
| operations: ['generateKey', 'importKey', 'sign', 'verify', 'getPublicKey'], | |
| keyGenParams: { name: 'ECDSA', namedCurve: 'P-256' }, | |
| importParams: { name: 'ECDSA', namedCurve: 'P-256' }, | |
| signParams: { name: 'ECDSA', hash: 'SHA-256' }, | |
| }, | |
| ECDH: { | |
| operations: ['generateKey', 'importKey', 'deriveBits', 'getPublicKey'], | |
| keyGenParams: { name: 'ECDH', namedCurve: 'P-256' }, | |
| importParams: { name: 'ECDH', namedCurve: 'P-256' }, | |
| deriveBitsParamsFactory: async () => { | |
| const {publicKey} = await crypto.subtle.generateKey( | |
| {name: 'ECDH', namedCurve: 'P-256'}, false, ['deriveBits']); | |
| return {name: 'ECDH', public: publicKey}; | |
| }, | |
| }, | |
| Ed25519: { | |
| operations: ['generateKey', 'importKey', 'sign', 'verify', 'getPublicKey'], | |
| keyGenParams: null, | |
| signParams: { name: 'Ed25519' }, | |
| }, | |
| X25519: { | |
| operations: ['generateKey', 'importKey', 'deriveBits', 'getPublicKey'], | |
| keyGenParams: null, | |
| deriveBitsParamsFactory: async () => { | |
| const {publicKey} = await crypto.subtle.generateKey( | |
| 'X25519', false, ['deriveBits']); | |
| return {name: 'X25519', public: publicKey}; | |
| }, | |
| }, | |
| // Symmetric algorithms | |
| 'AES-CBC': { | |
| operations: ['generateKey', 'importKey', 'encrypt', 'decrypt'], | |
| keyGenParams: { name: 'AES-CBC', length: 256 }, | |
| encryptParams: { name: 'AES-CBC', iv: new Uint8Array(16) }, | |
| }, | |
| 'AES-CTR': { | |
| operations: ['generateKey', 'importKey', 'encrypt', 'decrypt'], | |
| keyGenParams: { name: 'AES-CTR', length: 256 }, | |
| encryptParams: { | |
| name: 'AES-CTR', | |
| counter: new Uint8Array(16), | |
| length: 128, | |
| }, | |
| }, | |
| 'AES-GCM': { | |
| operations: ['generateKey', 'importKey', 'encrypt', 'decrypt'], | |
| keyGenParams: { name: 'AES-GCM', length: 256 }, | |
| encryptParams: { name: 'AES-GCM', iv: new Uint8Array(12) }, | |
| }, | |
| 'AES-KW': { | |
| operations: ['generateKey', 'importKey'], // wrapKey/unwrapKey not in requested operations | |
| keyGenParams: { name: 'AES-KW', length: 256 }, | |
| }, | |
| HMAC: { | |
| operations: ['generateKey', 'importKey', 'sign', 'verify'], | |
| keyGenParams: { name: 'HMAC', hash: 'SHA-256' }, | |
| importParams: { name: 'HMAC', hash: 'SHA-256' }, | |
| signParams: { name: 'HMAC' }, | |
| }, | |
| // Hash algorithms | |
| 'SHA-1': { | |
| operations: ['digest'], | |
| keyGenParams: null, | |
| }, | |
| 'SHA-256': { | |
| operations: ['digest'], | |
| keyGenParams: null, | |
| }, | |
| 'SHA-384': { | |
| operations: ['digest'], | |
| keyGenParams: null, | |
| }, | |
| 'SHA-512': { | |
| operations: ['digest'], | |
| keyGenParams: null, | |
| }, | |
| // Key derivation algorithms | |
| HKDF: { | |
| operations: ['importKey', 'deriveBits'], | |
| keyGenParams: null, | |
| deriveBitsParams: { | |
| name: 'HKDF', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(16), | |
| info: new Uint8Array(0), | |
| }, | |
| }, | |
| PBKDF2: { | |
| operations: ['importKey', 'deriveBits'], | |
| keyGenParams: null, | |
| deriveBitsParams: { | |
| name: 'PBKDF2', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(16), | |
| iterations: 100000, | |
| }, | |
| }, | |
| }; | |
| const operations = [ | |
| 'generateKey', | |
| 'importKey', | |
| 'sign', | |
| 'verify', | |
| 'encrypt', | |
| 'decrypt', | |
| 'deriveBits', | |
| 'digest', | |
| 'getPublicKey', | |
| ]; | |
| // Test that supports method exists and is a static method | |
| testSupportsMethod(); | |
| // Test invalid operation names | |
| test(() => { | |
| assert_false( | |
| SubtleCrypto.supports('invalidOperation', 'AES-GCM'), | |
| 'Invalid operation should return false' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('', 'AES-GCM'), | |
| 'Empty operation should return false' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('GENERATEKEY', 'AES-GCM'), | |
| 'Case-sensitive operation check' | |
| ); | |
| }, 'supports returns false for invalid operations'); | |
| // Test invalid algorithm identifiers | |
| test(() => { | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', 'InvalidAlgorithm'), | |
| 'Invalid algorithm should return false' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', ''), | |
| 'Empty algorithm should return false' | |
| ); | |
| }, 'supports returns false for invalid algorithms'); | |
| // Test standard WebCrypto algorithms for requested operations | |
| runSupportsTests(standardAlgorithms, operations); | |
| // Test algorithm objects (not just strings) | |
| test(() => { | |
| assert_true( | |
| SubtleCrypto.supports('generateKey', { name: 'AES-GCM', length: 256 }), | |
| 'Algorithm object should be supported' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports('generateKey', { name: 'HMAC', hash: 'SHA-256' }), | |
| 'Algorithm object with parameters should be supported' | |
| ); | |
| }, 'supports works with algorithm objects'); | |
| // Test with algorithm objects that have invalid parameters | |
| test(() => { | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { name: 'AES-GCM', length: 100 }), | |
| 'Invalid key length should return false' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'HMAC', | |
| hash: 'INVALID-HASH', | |
| }), | |
| 'Invalid hash parameter should return false' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'encrypt', {name: 'AES-CBC', iv: new Uint8Array(10)}), | |
| 'Invalid IV for AES-CBC should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('encrypt', { | |
| name: 'AES-CTR', | |
| counter: new Uint8Array(10), | |
| length: 128, | |
| }), | |
| 'Invalid IV for AES-CTR should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('encrypt', { | |
| name: 'AES-CTR', | |
| counter: new Uint8Array(16), | |
| length: 0, | |
| }), | |
| 'Invalid length=0 for AES-CTR should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('encrypt', { | |
| name: 'AES-CTR', | |
| counter: new Uint8Array(16), | |
| length: 129, | |
| }), | |
| 'Invalid length=129 for AES-CTR should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('encrypt', { | |
| name: 'AES-GCM', | |
| iv: new Uint8Array(16), | |
| tagLength: 100, | |
| }), | |
| 'Invalid tag length for AES-GCM should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('decrypt', { | |
| name: 'AES-GCM', | |
| iv: new Uint8Array(16), | |
| tagLength: 100, | |
| }), | |
| 'Invalid tag length for AES-GCM should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', {name: 'ECDH', namedCurve: 'P-51'}), | |
| 'Invalid curve for ECDH should return false'); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', { | |
| name: 'HKDF', | |
| hash: 'SHA-25', | |
| salt: new Uint8Array(16), | |
| info: new Uint8Array(0), | |
| }, | |
| 8), | |
| 'Invalid hash for HKDF should return false'); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', { | |
| name: 'HKDF', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(16), | |
| info: new Uint8Array(0), | |
| }, | |
| 11), | |
| 'Invalid length for HKDF should return false'); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', { | |
| name: 'HKDF', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(16), | |
| info: new Uint8Array(0), | |
| }), | |
| 'null length for HKDF should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'HMAC', | |
| hash: 'SHA-25', | |
| }), | |
| 'Invalid hash for HMAC should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'HMAC', | |
| hash: 'SHA-256', | |
| length: 0, | |
| }), | |
| 'Invalid length for HMAC should return false'); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', { | |
| name: 'PBKDF2', | |
| hash: 'SHA-25', | |
| salt: new Uint8Array(16), | |
| iterations: 100000, | |
| }, | |
| 8), | |
| 'Invalid hash for PBKDF2 should return false'); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', { | |
| name: 'PBKDF2', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(16), | |
| iterations: 100000, | |
| }, | |
| 11), | |
| 'Invalid length for PBKDF2 should return false'); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', { | |
| name: 'PBKDF2', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(16), | |
| iterations: 100000, | |
| }), | |
| 'null length for PBKDF2 should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'RSASSA-PKCS1-v1_5', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array([1, 0, 1]), | |
| hash: 'SHA-56', | |
| }), | |
| 'Invalid hash for RSA PKCS1 should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'RSA-PSS', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array([1, 0, 1]), | |
| hash: 'SHA-56', | |
| }), | |
| 'Invalid hash for RSA PSS should return false'); | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'RSA-OAEP', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array([1, 0, 1]), | |
| hash: 'SHA-26', | |
| }), | |
| 'Invalid hash for RSA OAEP should return false'); | |
| }, 'supports returns false for algorithm objects with invalid parameters'); | |
| [ | |
| ['SHA-1', 160], | |
| ['SHA-256', 256], | |
| ['SHA-384', 384], | |
| ['SHA-512', 512], | |
| ].forEach(([hash, hashLength]) => { | |
| test(() => { | |
| const algorithm = { | |
| name: 'HKDF', | |
| hash, | |
| salt: new Uint8Array(), | |
| info: new Uint8Array(), | |
| }; | |
| const maximumLength = 255 * hashLength; | |
| assert_true( | |
| SubtleCrypto.supports('deriveBits', algorithm, maximumLength), | |
| `HKDF with ${hash} supports its maximum output length` | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('deriveBits', algorithm, maximumLength + 8), | |
| `HKDF with ${hash} rejects output longer than its maximum` | |
| ); | |
| }, `supports validates HKDF ${hash} output length`); | |
| }); | |
| test(() => { | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveKey', | |
| { | |
| name: 'HKDF', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(), | |
| info: new Uint8Array(), | |
| }, | |
| {name: 'HMAC', hash: 'SHA-256', length: 65288} | |
| ), | |
| 'HKDF rejects a derived key longer than 255 hash blocks' | |
| ); | |
| }, 'supports validates HKDF output length for deriveKey'); | |
| test(() => { | |
| assert_false( | |
| SubtleCrypto.supports('importKey', { | |
| name: 'HMAC', | |
| hash: 'SHA-256', | |
| length: 0, | |
| }), | |
| 'HMAC rejects an explicitly zero-length imported key' | |
| ); | |
| }, 'supports validates HMAC import length'); | |
| const invalidRsaKeyGenParameters = [ | |
| { | |
| description: 'a modulus shorter than 4 bits', | |
| modulusLength: 3, | |
| publicExponent: Uint8Array.of(3), | |
| }, | |
| { | |
| description: 'a public exponent less than 3', | |
| modulusLength: 2048, | |
| publicExponent: Uint8Array.of(1), | |
| }, | |
| { | |
| description: 'an even public exponent', | |
| modulusLength: 2048, | |
| publicExponent: Uint8Array.of(4), | |
| }, | |
| { | |
| description: 'a public exponent equal to 2^modulusLength - 1', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array(256).fill(0xff), | |
| }, | |
| ]; | |
| [ | |
| 'RSASSA-PKCS1-v1_5', | |
| 'RSA-PSS', | |
| 'RSA-OAEP', | |
| ].forEach(name => { | |
| invalidRsaKeyGenParameters.forEach(({description, ...parameters}) => { | |
| test(() => { | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', { | |
| name, | |
| ...parameters, | |
| hash: 'SHA-256', | |
| }), | |
| `${name} rejects ${description}` | |
| ); | |
| }, `supports rejects ${name} generateKey with ${description}`); | |
| }); | |
| }); | |
| ['ECDSA', 'ECDH'].forEach(name => { | |
| test(() => { | |
| assert_false( | |
| SubtleCrypto.supports('importKey', { | |
| name, | |
| namedCurve: 'not-a-curve', | |
| }), | |
| `${name} rejects an unknown named curve` | |
| ); | |
| }, `supports validates ${name} import namedCurve`); | |
| }); | |
| [ | |
| ['P-256', 256], | |
| ['P-384', 384], | |
| ['P-521', 528], | |
| ].forEach(([namedCurve, maximumLength]) => { | |
| promise_test(async () => { | |
| const {publicKey} = await crypto.subtle.generateKey( | |
| {name: 'ECDH', namedCurve}, false, ['deriveBits']); | |
| const algorithm = {name: 'ECDH', public: publicKey}; | |
| assert_true( | |
| SubtleCrypto.supports('deriveBits', algorithm, maximumLength), | |
| `ECDH ${namedCurve} supports its maximum output length` | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('deriveBits', algorithm, maximumLength + 1), | |
| `ECDH ${namedCurve} rejects output longer than its maximum` | |
| ); | |
| }, `supports validates ECDH ${namedCurve} deriveBits length`); | |
| }); | |
| promise_test(async () => { | |
| const {publicKey} = await crypto.subtle.generateKey( | |
| 'X25519', false, ['deriveBits']); | |
| const algorithm = {name: 'X25519', public: publicKey}; | |
| assert_true( | |
| SubtleCrypto.supports('deriveBits', algorithm, 256), | |
| 'X25519 supports its maximum output length' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('deriveBits', algorithm, 257), | |
| 'X25519 rejects output longer than its maximum' | |
| ); | |
| }, 'supports validates X25519 deriveBits length'); | |
| promise_test(async () => { | |
| const [ecdhKeyPair, x25519KeyPair] = await Promise.all([ | |
| crypto.subtle.generateKey( | |
| {name: 'ECDH', namedCurve: 'P-256'}, false, ['deriveBits']), | |
| crypto.subtle.generateKey('X25519', false, ['deriveBits']), | |
| ]); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', {name: 'ECDH', public: ecdhKeyPair.privateKey}, 256), | |
| 'ECDH rejects a private public property' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', {name: 'ECDH', public: x25519KeyPair.publicKey}, 256), | |
| 'ECDH rejects a public property for another algorithm' | |
| ); | |
| }, 'supports validates the ECDH public key'); | |
| promise_test(async () => { | |
| const [x25519KeyPair, ecdhKeyPair] = await Promise.all([ | |
| crypto.subtle.generateKey('X25519', false, ['deriveBits']), | |
| crypto.subtle.generateKey( | |
| {name: 'ECDH', namedCurve: 'P-256'}, false, ['deriveBits']), | |
| ]); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', {name: 'X25519', public: x25519KeyPair.privateKey}, 256), | |
| 'X25519 rejects a private public property' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveBits', {name: 'X25519', public: ecdhKeyPair.publicKey}, 256), | |
| 'X25519 rejects a public property for another algorithm' | |
| ); | |
| }, 'supports validates the X25519 public key'); | |
| promise_test(async () => { | |
| const [p256KeyPair, p521KeyPair] = await Promise.all([ | |
| crypto.subtle.generateKey( | |
| {name: 'ECDH', namedCurve: 'P-256'}, false, ['deriveBits']), | |
| crypto.subtle.generateKey( | |
| {name: 'ECDH', namedCurve: 'P-521'}, false, ['deriveBits']), | |
| ]); | |
| const derivedKeyAlgorithm = {name: 'HMAC', hash: 'SHA-256'}; | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveKey', | |
| {name: 'ECDH', public: p256KeyPair.publicKey}, | |
| derivedKeyAlgorithm | |
| ), | |
| 'ECDH P-256 cannot derive a 512-bit HMAC key' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports( | |
| 'deriveKey', | |
| {name: 'ECDH', public: p521KeyPair.publicKey}, | |
| derivedKeyAlgorithm | |
| ), | |
| 'ECDH P-521 can derive a 512-bit HMAC key' | |
| ); | |
| }, 'supports derives the ECDH output limit from the public curve'); | |
| // Test some specific combinations that should work | |
| test(() => { | |
| // RSA algorithms | |
| assert_true( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'RSASSA-PKCS1-v1_5', | |
| modulusLength: 2048, | |
| publicExponent: new Uint8Array([1, 0, 1]), | |
| hash: 'SHA-256', | |
| }), | |
| 'RSASSA-PKCS1-v1_5 generateKey' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports('sign', { name: 'RSASSA-PKCS1-v1_5' }), | |
| 'RSASSA-PKCS1-v1_5 sign' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports('verify', { name: 'RSASSA-PKCS1-v1_5' }), | |
| 'RSASSA-PKCS1-v1_5 verify' | |
| ); | |
| // ECDSA | |
| assert_true( | |
| SubtleCrypto.supports('generateKey', { | |
| name: 'ECDSA', | |
| namedCurve: 'P-256', | |
| }), | |
| 'ECDSA generateKey' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports('sign', { name: 'ECDSA', hash: 'SHA-256' }), | |
| 'ECDSA sign' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports('verify', { name: 'ECDSA', hash: 'SHA-256' }), | |
| 'ECDSA verify' | |
| ); | |
| // AES-GCM | |
| assert_true( | |
| SubtleCrypto.supports('generateKey', { name: 'AES-GCM', length: 256 }), | |
| 'AES-GCM generateKey' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports('encrypt', { | |
| name: 'AES-GCM', | |
| iv: new Uint8Array(12), | |
| }), | |
| 'AES-GCM encrypt' | |
| ); | |
| assert_true( | |
| SubtleCrypto.supports('decrypt', { | |
| name: 'AES-GCM', | |
| iv: new Uint8Array(12), | |
| }), | |
| 'AES-GCM decrypt' | |
| ); | |
| // HMAC | |
| assert_true( | |
| SubtleCrypto.supports('generateKey', { name: 'HMAC', hash: 'SHA-256' }), | |
| 'HMAC generateKey' | |
| ); | |
| assert_true(SubtleCrypto.supports('sign', { name: 'HMAC' }), 'HMAC sign'); | |
| assert_true(SubtleCrypto.supports('verify', { name: 'HMAC' }), 'HMAC verify'); | |
| }, 'Common algorithm and operation combinations work'); | |
| // Test some specific combinations that should not work | |
| test(() => { | |
| // Hash algorithms don't support key operations | |
| assert_false( | |
| SubtleCrypto.supports('generateKey', 'SHA-256'), | |
| 'SHA-256 generateKey should fail' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('sign', 'SHA-256'), | |
| 'SHA-256 sign should fail' | |
| ); | |
| // AES can't sign/verify (these require algorithm parameters due to normalization) | |
| assert_false( | |
| SubtleCrypto.supports('sign', 'AES-GCM'), | |
| 'AES-GCM sign should fail' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('verify', 'AES-GCM'), | |
| 'AES-GCM verify should fail' | |
| ); | |
| // ECDSA can't encrypt/decrypt | |
| assert_false( | |
| SubtleCrypto.supports('encrypt', 'ECDSA'), | |
| 'ECDSA encrypt should fail' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('decrypt', 'ECDSA'), | |
| 'ECDSA decrypt should fail' | |
| ); | |
| // HMAC can't encrypt/decrypt | |
| assert_false( | |
| SubtleCrypto.supports('encrypt', 'HMAC'), | |
| 'HMAC encrypt should fail' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('decrypt', 'HMAC'), | |
| 'HMAC decrypt should fail' | |
| ); | |
| // Non-hash algorithms can't digest | |
| assert_false( | |
| SubtleCrypto.supports('digest', 'AES-GCM'), | |
| 'AES-GCM digest should fail' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('digest', 'ECDSA'), | |
| 'ECDSA digest should fail' | |
| ); | |
| assert_false( | |
| SubtleCrypto.supports('digest', 'HMAC'), | |
| 'HMAC digest should fail' | |
| ); | |
| }, 'Invalid algorithm and operation combinations fail'); | |
| // Test supports for deriveKey op | |
| test(() => { | |
| assert_true( | |
| SubtleCrypto.supports( | |
| 'deriveKey', { | |
| name: 'HKDF', | |
| hash: 'SHA-256', | |
| salt: new Uint8Array(16), | |
| info: new Uint8Array(0), | |
| }, | |
| {name: 'HMAC', hash: 'SHA-256'}), | |
| 'deriveKey HKDF-HMAC should pass'); | |
| }, 'deriveKey tests'); | |
| promise_test(async (t) => { | |
| let keypair = await crypto.subtle.generateKey( | |
| { | |
| name: 'X25519', | |
| }, | |
| false, ['deriveKey', 'deriveBits']); | |
| assert_true( | |
| SubtleCrypto.supports( | |
| 'deriveKey', { | |
| name: 'X25519', | |
| public: keypair.publicKey, | |
| }, | |
| {name: 'AES-GCM', length: 256}), | |
| 'deriveKey X25519-AES-GCM-256 should pass'); | |
| assert_false( | |
| SubtleCrypto.supports( | |
| 'deriveKey', { | |
| name: 'X25519', | |
| public: keypair.publicKey, | |
| }, | |
| {name: 'HMAC', hash: 'SHA-256'}), | |
| 'deriveKey X25519-HMAC-SHA-256 should fail'); | |
| }, 'deriveKey promise tests'); | |
| // Test supports for exportKey op | |
| test(() => { | |
| assert_true(SubtleCrypto.supports('exportKey', 'AES-GCM'), | |
| 'exportKey AES-GCM should pass'); | |
| assert_false(SubtleCrypto.supports('exportKey', 'HKDF'), | |
| 'exportKey HKDF should fail'); | |
| assert_false(SubtleCrypto.supports('exportKey', 'PBKDF2'), | |
| 'exportKey PBKDF2 should fail'); | |
| }, 'exportKey tests'); | |
| // Test supports for wrapKey op | |
| test(() => { | |
| assert_true(SubtleCrypto.supports('wrapKey', 'AES-KW', 'AES-GCM'), | |
| 'wrapKey AES-KW-AES-GCM should pass'); | |
| assert_false(SubtleCrypto.supports('wrapKey', 'AES-KW', 'HKDF'), | |
| 'wrapKey AES-KW-HKDF should fail'); | |
| assert_false(SubtleCrypto.supports('wrapKey', 'AES-KW', 'PBKDF2'), | |
| 'wrapKey AES-KW-PBKDF2 should fail'); | |
| }, 'wrapKey tests'); | |
| done(); |