mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 16:42:21 -05:00
feat(ext/crypto): support JWK import for HMAC (#11716)
This commit is contained in:
parent
ad037b3b1a
commit
1f57cd2c0f
5 changed files with 386 additions and 94 deletions
|
@ -243,22 +243,43 @@ unitTest(async function testSignRSASSAKey() {
|
|||
assert(signature);
|
||||
});
|
||||
|
||||
// deno-fmt-ignore
|
||||
const rawKey = new Uint8Array([
|
||||
1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16
|
||||
]);
|
||||
|
||||
const jwk: JsonWebKey = {
|
||||
kty: "oct",
|
||||
// unpadded base64 for rawKey.
|
||||
k: "AQIDBAUGBwgJCgsMDQ4PEA",
|
||||
alg: "HS256",
|
||||
};
|
||||
|
||||
unitTest(async function subtleCryptoHmacImportExport() {
|
||||
// deno-fmt-ignore
|
||||
const rawKey = new Uint8Array([
|
||||
1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16
|
||||
]);
|
||||
const key = await crypto.subtle.importKey(
|
||||
const key1 = await crypto.subtle.importKey(
|
||||
"raw",
|
||||
rawKey,
|
||||
{ name: "HMAC", hash: "SHA-256" },
|
||||
true,
|
||||
["sign"],
|
||||
);
|
||||
const actual = await crypto.subtle.sign(
|
||||
const key2 = await crypto.subtle.importKey(
|
||||
"jwk",
|
||||
jwk,
|
||||
{ name: "HMAC", hash: "SHA-256" },
|
||||
true,
|
||||
["sign"],
|
||||
);
|
||||
const actual1 = await crypto.subtle.sign(
|
||||
{ name: "HMAC" },
|
||||
key,
|
||||
key1,
|
||||
new Uint8Array([1, 2, 3, 4]),
|
||||
);
|
||||
|
||||
const actual2 = await crypto.subtle.sign(
|
||||
{ name: "HMAC" },
|
||||
key2,
|
||||
new Uint8Array([1, 2, 3, 4]),
|
||||
);
|
||||
// deno-fmt-ignore
|
||||
|
@ -269,10 +290,14 @@ unitTest(async function subtleCryptoHmacImportExport() {
|
|||
23, 122, 222, 1, 146, 46, 182, 87,
|
||||
]);
|
||||
assertEquals(
|
||||
new Uint8Array(actual),
|
||||
new Uint8Array(actual1),
|
||||
expected,
|
||||
);
|
||||
|
||||
const exportedKey = await crypto.subtle.exportKey("raw", key);
|
||||
assertEquals(
|
||||
new Uint8Array(actual2),
|
||||
expected,
|
||||
);
|
||||
// TODO(@littledivy): Add a test for exporting JWK key when supported.
|
||||
const exportedKey = await crypto.subtle.exportKey("raw", key1);
|
||||
assertEquals(new Uint8Array(exportedKey), rawKey);
|
||||
});
|
||||
|
|
|
@ -12,13 +12,18 @@
|
|||
const core = window.Deno.core;
|
||||
const webidl = window.__bootstrap.webidl;
|
||||
const { DOMException } = window.__bootstrap.domException;
|
||||
const { atob } = window.__bootstrap.base64;
|
||||
|
||||
const {
|
||||
ArrayPrototypeFind,
|
||||
ArrayBufferIsView,
|
||||
ArrayPrototypeEvery,
|
||||
ArrayPrototypeIncludes,
|
||||
ArrayBuffer,
|
||||
ArrayBufferIsView,
|
||||
BigInt64Array,
|
||||
StringPrototypeToUpperCase,
|
||||
StringPrototypeReplace,
|
||||
StringPrototypeCharCodeAt,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
|
@ -100,6 +105,23 @@
|
|||
},
|
||||
};
|
||||
|
||||
// Decodes the unpadded base64 to the octet sequence containing key value `k` defined in RFC7518 Section 6.4
|
||||
function decodeSymmetricKey(key) {
|
||||
// Decode from base64url without `=` padding.
|
||||
const base64 = StringPrototypeReplace(
|
||||
StringPrototypeReplace(key, /\-/g, "+"),
|
||||
/\_/g,
|
||||
"/",
|
||||
);
|
||||
const decodedKey = atob(base64);
|
||||
const keyLength = decodedKey.length;
|
||||
const keyBytes = new Uint8Array(keyLength);
|
||||
for (let i = 0; i < keyLength; i++) {
|
||||
keyBytes[i] = StringPrototypeCharCodeAt(decodedKey, i);
|
||||
}
|
||||
return keyBytes;
|
||||
}
|
||||
|
||||
// See https://www.w3.org/TR/WebCryptoAPI/#dfn-normalize-an-algorithm
|
||||
// 18.4.4
|
||||
function normalizeAlgorithm(algorithm, op) {
|
||||
|
@ -631,7 +653,7 @@
|
|||
prefix,
|
||||
context: "Argument 1",
|
||||
});
|
||||
keyData = webidl.converters.BufferSource(keyData, {
|
||||
keyData = webidl.converters["BufferSource or JsonWebKey"](keyData, {
|
||||
prefix,
|
||||
context: "Argument 2",
|
||||
});
|
||||
|
@ -649,22 +671,32 @@
|
|||
});
|
||||
|
||||
// 2.
|
||||
if (ArrayBufferIsView(keyData)) {
|
||||
keyData = new Uint8Array(
|
||||
keyData.buffer,
|
||||
keyData.byteOffset,
|
||||
keyData.byteLength,
|
||||
);
|
||||
if (format !== "jwk") {
|
||||
if (ArrayBufferIsView(keyData) || keyData instanceof ArrayBuffer) {
|
||||
if (ArrayBufferIsView(keyData)) {
|
||||
keyData = new Uint8Array(
|
||||
keyData.buffer,
|
||||
keyData.byteOffset,
|
||||
keyData.byteLength,
|
||||
);
|
||||
} else {
|
||||
keyData = new Uint8Array(keyData);
|
||||
}
|
||||
keyData = TypedArrayPrototypeSlice(keyData);
|
||||
} else {
|
||||
throw new TypeError("keyData is a JsonWebKey");
|
||||
}
|
||||
} else {
|
||||
keyData = new Uint8Array(keyData);
|
||||
if (ArrayBufferIsView(keyData) || keyData instanceof ArrayBuffer) {
|
||||
throw new TypeError("keyData is not a JsonWebKey");
|
||||
}
|
||||
}
|
||||
keyData = TypedArrayPrototypeSlice(keyData);
|
||||
|
||||
const normalizedAlgorithm = normalizeAlgorithm(algorithm, "importKey");
|
||||
|
||||
switch (normalizedAlgorithm.name) {
|
||||
// https://w3c.github.io/webcrypto/#hmac-operations
|
||||
case "HMAC": {
|
||||
// 2.
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
|
@ -674,59 +706,177 @@
|
|||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
// 3.
|
||||
let hash;
|
||||
let data;
|
||||
|
||||
// 4. https://w3c.github.io/webcrypto/#hmac-operations
|
||||
switch (format) {
|
||||
case "raw": {
|
||||
const hash = normalizedAlgorithm.hash;
|
||||
// 5.
|
||||
let length = keyData.byteLength * 8;
|
||||
// 6.
|
||||
if (length === 0) {
|
||||
throw new DOMException("Key length is zero", "DataError");
|
||||
data = keyData;
|
||||
hash = normalizedAlgorithm.hash;
|
||||
break;
|
||||
}
|
||||
case "jwk": {
|
||||
// TODO(@littledivy): Why does the spec validate JWK twice?
|
||||
const jwk = keyData;
|
||||
// 2.
|
||||
if (jwk.kty !== "oct") {
|
||||
throw new DOMException(
|
||||
"`kty` member of JsonWebKey must be `oct`",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
if (normalizeAlgorithm.length) {
|
||||
// 7.
|
||||
|
||||
// Section 6.4.1 of RFC7518
|
||||
if (!jwk.k) {
|
||||
throw new DOMException(
|
||||
"`k` member of JsonWebKey must be present",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
|
||||
// 4.
|
||||
data = decodeSymmetricKey(jwk.k);
|
||||
// 5.
|
||||
hash = normalizedAlgorithm.hash;
|
||||
// 6.
|
||||
switch (hash.name) {
|
||||
case "SHA-1": {
|
||||
if (jwk.alg !== undefined && jwk.alg !== "HS1") {
|
||||
throw new DOMException(
|
||||
"`alg` member of JsonWebKey must be `HS1`",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SHA-256": {
|
||||
if (jwk.alg !== undefined && jwk.alg !== "HS256") {
|
||||
throw new DOMException(
|
||||
"`alg` member of JsonWebKey must be `HS256`",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SHA-384": {
|
||||
if (jwk.alg !== undefined && jwk.alg !== "HS384") {
|
||||
throw new DOMException(
|
||||
"`alg` member of JsonWebKey must be `HS384`",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SHA-512": {
|
||||
if (jwk.alg !== undefined && jwk.alg !== "HS512") {
|
||||
throw new DOMException(
|
||||
"`alg` member of JsonWebKey must be `HS512`",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new TypeError("unreachable");
|
||||
}
|
||||
|
||||
// 7.
|
||||
if (keyUsages.length > 0 && jwk.use && jwk.use !== "sign") {
|
||||
throw new DOMException(
|
||||
"`use` member of JsonWebKey must be `sign`",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
|
||||
// 8.
|
||||
// Section 4.3 of RFC7517
|
||||
if (jwk.key_ops) {
|
||||
if (
|
||||
normalizedAlgorithm.length > length ||
|
||||
normalizedAlgorithm.length <= (length - 8)
|
||||
ArrayPrototypeFind(
|
||||
jwk.key_ops,
|
||||
(u) => !ArrayPrototypeIncludes(recognisedUsages, u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException(
|
||||
"Key length is invalid",
|
||||
"`key_ops` member of JsonWebKey is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!ArrayPrototypeEvery(
|
||||
jwk.key_ops,
|
||||
(u) => ArrayPrototypeIncludes(keyUsages, u),
|
||||
)
|
||||
) {
|
||||
throw new DOMException(
|
||||
"`key_ops` member of JsonWebKey is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
length = normalizeAlgorithm.length;
|
||||
}
|
||||
|
||||
if (keyUsages.length == 0) {
|
||||
throw new DOMException("Key usage is empty", "SyntaxError");
|
||||
// 9.
|
||||
if (jwk.ext === false && extractable == true) {
|
||||
throw new DOMException(
|
||||
"`ext` member of JsonWebKey is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, {
|
||||
type: "raw",
|
||||
data: keyData,
|
||||
});
|
||||
|
||||
const algorithm = {
|
||||
name: "HMAC",
|
||||
length,
|
||||
hash,
|
||||
};
|
||||
|
||||
const key = constructKey(
|
||||
"secret",
|
||||
extractable,
|
||||
usageIntersection(keyUsages, recognisedUsages),
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
|
||||
return key;
|
||||
break;
|
||||
}
|
||||
// TODO(@littledivy): jwk
|
||||
default:
|
||||
throw new DOMException("Not implemented", "NotSupportedError");
|
||||
}
|
||||
|
||||
// 5.
|
||||
let length = data.byteLength * 8;
|
||||
// 6.
|
||||
if (length === 0) {
|
||||
throw new DOMException("Key length is zero", "DataError");
|
||||
}
|
||||
// 7.
|
||||
if (normalizedAlgorithm.length !== undefined) {
|
||||
if (
|
||||
normalizedAlgorithm.length > length ||
|
||||
normalizedAlgorithm.length <= (length - 8)
|
||||
) {
|
||||
throw new DOMException(
|
||||
"Key length is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
length = normalizedAlgorithm.length;
|
||||
}
|
||||
|
||||
if (keyUsages.length == 0) {
|
||||
throw new DOMException("Key usage is empty", "SyntaxError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, {
|
||||
type: "raw",
|
||||
data,
|
||||
});
|
||||
|
||||
const algorithm = {
|
||||
name: "HMAC",
|
||||
length,
|
||||
hash,
|
||||
};
|
||||
|
||||
const key = constructKey(
|
||||
"secret",
|
||||
extractable,
|
||||
usageIntersection(keyUsages, recognisedUsages),
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
|
||||
return key;
|
||||
}
|
||||
// TODO(@littledivy): RSASSA-PKCS1-v1_5
|
||||
// TODO(@littledivy): RSA-PSS
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
((window) => {
|
||||
const webidl = window.__bootstrap.webidl;
|
||||
const { CryptoKey } = window.__bootstrap.crypto;
|
||||
const { ArrayBufferIsView, ArrayBuffer } = window.__bootstrap.primordials;
|
||||
|
||||
webidl.converters.AlgorithmIdentifier = (V, opts) => {
|
||||
// Union for (object or DOMString)
|
||||
|
@ -18,6 +19,14 @@
|
|||
return webidl.converters.DOMString(V, opts);
|
||||
};
|
||||
|
||||
webidl.converters["BufferSource or JsonWebKey"] = (V, opts) => {
|
||||
// Union for (BufferSource or JsonWebKey)
|
||||
if (ArrayBufferIsView(V) || V instanceof ArrayBuffer) {
|
||||
return webidl.converters.BufferSource(V, opts);
|
||||
}
|
||||
return webidl.converters.JsonWebKey(V, opts);
|
||||
};
|
||||
|
||||
webidl.converters.KeyType = webidl.createEnumConverter("KeyType", [
|
||||
"public",
|
||||
"private",
|
||||
|
@ -178,6 +187,115 @@
|
|||
webidl.converters.HmacImportParams = webidl
|
||||
.createDictionaryConverter("HmacImportParams", dictHmacImportParams);
|
||||
|
||||
const dictRsaOtherPrimesInfo = [
|
||||
{
|
||||
key: "r",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "d",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "t",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
];
|
||||
|
||||
webidl.converters.RsaOtherPrimesInfo = webidl.createDictionaryConverter(
|
||||
"RsaOtherPrimesInfo",
|
||||
dictRsaOtherPrimesInfo,
|
||||
);
|
||||
webidl.converters["sequence<RsaOtherPrimesInfo>"] = webidl
|
||||
.createSequenceConverter(
|
||||
webidl.converters.RsaOtherPrimesInfo,
|
||||
);
|
||||
|
||||
const dictJsonWebKey = [
|
||||
// Sections 4.2 and 4.3 of RFC7517.
|
||||
// https://datatracker.ietf.org/doc/html/rfc7517#section-4
|
||||
{
|
||||
key: "kty",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "use",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "key_ops",
|
||||
converter: webidl.converters["sequence<DOMString>"],
|
||||
},
|
||||
{
|
||||
key: "alg",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
// JSON Web Key Parameters Registration
|
||||
{
|
||||
key: "ext",
|
||||
converter: webidl.converters["boolean"],
|
||||
},
|
||||
// Section 6 of RFC7518 JSON Web Algorithms
|
||||
// https://datatracker.ietf.org/doc/html/rfc7518#section-6
|
||||
{
|
||||
key: "crv",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "x",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "y",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "d",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "n",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "e",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "p",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "q",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "dp",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "dq",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "qi",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
{
|
||||
key: "oth",
|
||||
converter: webidl.converters["sequence<RsaOtherPrimesInfo>"],
|
||||
},
|
||||
{
|
||||
key: "k",
|
||||
converter: webidl.converters["DOMString"],
|
||||
},
|
||||
];
|
||||
|
||||
webidl.converters.JsonWebKey = webidl.createDictionaryConverter(
|
||||
"JsonWebKey",
|
||||
dictJsonWebKey,
|
||||
);
|
||||
|
||||
const dictPbkdf2Params = [
|
||||
...dictAlgorithm,
|
||||
{
|
||||
|
|
35
ext/crypto/lib.deno_crypto.d.ts
vendored
35
ext/crypto/lib.deno_crypto.d.ts
vendored
|
@ -28,6 +28,34 @@ type KeyUsage =
|
|||
|
||||
type NamedCurve = string;
|
||||
|
||||
interface RsaOtherPrimesInfo {
|
||||
d?: string;
|
||||
r?: string;
|
||||
t?: string;
|
||||
}
|
||||
|
||||
interface JsonWebKey {
|
||||
alg?: string;
|
||||
crv?: string;
|
||||
d?: string;
|
||||
dp?: string;
|
||||
dq?: string;
|
||||
e?: string;
|
||||
ext?: boolean;
|
||||
k?: string;
|
||||
// deno-lint-ignore camelcase
|
||||
key_ops?: string[];
|
||||
kty?: string;
|
||||
n?: string;
|
||||
oth?: RsaOtherPrimesInfo[];
|
||||
p?: string;
|
||||
q?: string;
|
||||
qi?: string;
|
||||
use?: string;
|
||||
x?: string;
|
||||
y?: string;
|
||||
}
|
||||
|
||||
interface HmacKeyGenParams extends Algorithm {
|
||||
hash: HashAlgorithmIdentifier;
|
||||
length?: number;
|
||||
|
@ -122,6 +150,13 @@ interface SubtleCrypto {
|
|||
extractable: boolean,
|
||||
keyUsages: KeyUsage[],
|
||||
): Promise<CryptoKeyPair | CryptoKey>;
|
||||
importKey(
|
||||
format: "jwk",
|
||||
keyData: JsonWebKey,
|
||||
algorithm: AlgorithmIdentifier | HmacImportParams,
|
||||
extractable: boolean,
|
||||
keyUsages: KeyUsage[],
|
||||
): Promise<CryptoKey>;
|
||||
importKey(
|
||||
format: "raw",
|
||||
keyData: BufferSource,
|
||||
|
|
|
@ -14041,42 +14041,6 @@
|
|||
"Good parameters: 256 bits (jwk, {alg: A256KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-KW}, true, [unwrapKey])",
|
||||
"Good parameters: 256 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 2: 3, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 3: 4, 30: 31, 31: 32, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: AES-KW}, false, [unwrapKey])",
|
||||
"Good parameters: 256 bits (jwk, {alg: A256KW, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {name: AES-KW}, false, [unwrapKey])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-1, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-1, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-1, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS1, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-1, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-256, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-256, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-256, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS256, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-256, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-384, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-384, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-384, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS384, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-384, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 128 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-512, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-512, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 192 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcY, kty: oct}, {hash: SHA-512, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [verify, sign])",
|
||||
"Good parameters: 256 bits (jwk, {alg: HS512, k: AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA, kty: oct}, {hash: SHA-512, name: HMAC}, false, [verify])",
|
||||
"Good parameters: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [deriveBits])",
|
||||
"Good parameters: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [deriveKey, deriveBits])",
|
||||
"Good parameters: 128 bits (raw, {0: 1, 1: 2, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}, {name: HKDF}, false, [deriveKey])",
|
||||
|
|
Loading…
Reference in a new issue