@transmute/cose
Advanced tools
Comparing version 0.2.11 to 0.2.12
@@ -14,19 +14,17 @@ "use strict"; | ||
const jose_1 = require("jose"); | ||
const algorithms_1 = require("../algorithms"); | ||
const elliptic_curves_1 = require("../elliptic-curves"); | ||
const algorithms = Object.values(algorithms_1.IANACOSEAlgorithms); | ||
const curves = Object.values(elliptic_curves_1.IANACOSEEllipticCurves); | ||
const formatJwk_1 = require("./formatJwk"); | ||
const iana_1 = require("../../iana"); | ||
const Params_1 = require("../Params"); | ||
const convertCoseKeyToJsonWebKey = (coseKey) => __awaiter(void 0, void 0, void 0, function* () { | ||
const kty = coseKey.get(1); | ||
const kid = coseKey.get(2); | ||
const alg = coseKey.get(3); | ||
const crv = coseKey.get(-1); | ||
// kty EC, kty: EK | ||
if (![2, 5].includes(kty)) { | ||
const kty = coseKey.get(Params_1.Key.Kty); | ||
// kty EC2 | ||
if (![Params_1.KeyTypes.EC2].includes(kty)) { | ||
throw new Error('This library requires does not support the given key type'); | ||
} | ||
const foundAlgorithm = algorithms.find((param) => { | ||
return param.Value === `${alg}`; | ||
}); | ||
const kid = coseKey.get(Params_1.Key.Kid); | ||
const alg = coseKey.get(Params_1.Key.Alg); | ||
const crv = coseKey.get(Params_1.EC2.Crv); | ||
const foundAlgorithm = iana_1.iana["COSE Algorithms"].getByValue(alg); | ||
if (!foundAlgorithm) { | ||
@@ -46,5 +44,5 @@ throw new Error('This library requires keys to use fully specified algorithms'); | ||
}; | ||
const x = coseKey.get(-2); | ||
const y = coseKey.get(-3); | ||
const d = coseKey.get(-4); | ||
const x = coseKey.get(Params_1.EC2.X); | ||
const y = coseKey.get(Params_1.EC2.Y); | ||
const d = coseKey.get(Params_1.EC2.D); | ||
if (x) { | ||
@@ -51,0 +49,0 @@ jwk.x = jose_1.base64url.encode(x); |
@@ -1,2 +0,2 @@ | ||
import { PublicKeyJwk, SecretKeyJwk } from '../sign1'; | ||
export declare const convertJsonWebKeyToCoseKey: <T>(jwk: PublicKeyJwk | SecretKeyJwk) => Promise<T>; | ||
import { PublicKeyJwk, PrivateKeyJwk } from '../sign1'; | ||
export declare const convertJsonWebKeyToCoseKey: <T>(jwk: PublicKeyJwk | PrivateKeyJwk) => Promise<T>; |
@@ -16,7 +16,6 @@ "use strict"; | ||
const key_common_parameters_1 = require("../key-common-parameters"); | ||
const algorithms_1 = require("../algorithms"); | ||
const key_type_parameters_1 = require("../key-type-parameters"); | ||
const key_type_1 = require("../key-type"); | ||
const elliptic_curves_1 = require("../elliptic-curves"); | ||
const algorithms = Object.values(algorithms_1.IANACOSEAlgorithms); | ||
const iana_1 = require("../../iana"); | ||
const commonParams = Object.values(key_common_parameters_1.IANACOSEKeyCommonParameters); | ||
@@ -90,5 +89,3 @@ const keyTypeParams = Object.values(key_type_parameters_1.IANACOSEKeyTypeParameters); | ||
if (foundCommonParam) { | ||
const foundAlgorithm = algorithms.find((param) => { | ||
return param.Name === value; | ||
}); | ||
const foundAlgorithm = iana_1.iana['COSE Algorithms'].getByName(value); | ||
if (foundAlgorithm) { | ||
@@ -95,0 +92,0 @@ coseKey.set(label, parseInt(foundAlgorithm.Value, 10)); |
export type CoseKeyAgreementAlgorithms = 'ECDH-ES+A128KW'; | ||
export type CoseSignatureAlgorithms = 'ES256' | 'ES384' | 'ES512'; | ||
export type CoseSignatureAlgorithms = 'ES256' | 'ES384' | 'ES512' | 'ESP256' | 'ESP384'; | ||
export type ContentTypeOfJsonWebKey = 'application/jwk+json'; | ||
@@ -4,0 +4,0 @@ export type ContentTypeOfCoseKey = 'application/cose-key'; |
@@ -18,10 +18,15 @@ "use strict"; | ||
const formatJwk_1 = require("./formatJwk"); | ||
const iana_1 = require("../../iana"); | ||
const Params_1 = require("../Params"); | ||
const generate = (alg, contentType = 'application/jwk+json') => __awaiter(void 0, void 0, void 0, function* () { | ||
const knownAlgorithm = Object.values(algorithms_1.IANACOSEAlgorithms).find((entry) => { | ||
let knownAlgorithm = Object.values(algorithms_1.IANACOSEAlgorithms).find((entry) => { | ||
return entry.Name === alg; | ||
}); | ||
if (!knownAlgorithm) { | ||
knownAlgorithm = iana_1.iana["COSE Algorithms"].getByName(alg); | ||
} | ||
if (!knownAlgorithm) { | ||
throw new Error('Algorithm is not supported.'); | ||
} | ||
const cryptoKeyPair = yield (0, jose_1.generateKeyPair)(knownAlgorithm.Name, { extractable: true }); | ||
const cryptoKeyPair = yield (0, jose_1.generateKeyPair)(iana_1.iana["COSE Algorithms"]["less-specified"](knownAlgorithm.Name), { extractable: true }); | ||
const privateKeyJwk = yield (0, jose_1.exportJWK)(cryptoKeyPair.privateKey); | ||
@@ -38,3 +43,3 @@ const jwkThumbprint = yield (0, jose_1.calculateJwkThumbprint)(privateKeyJwk); | ||
const coseKeyThumbprint = yield thumbprint_1.thumbprint.calculateCoseKeyThumbprint(secretKeyCoseKey); | ||
secretKeyCoseKey.set(2, coseKeyThumbprint); | ||
secretKeyCoseKey.set(Params_1.Key.Kid, coseKeyThumbprint); | ||
return secretKeyCoseKey; | ||
@@ -41,0 +46,0 @@ } |
@@ -1,3 +0,3 @@ | ||
import { PublicKeyJwk, SecretKeyJwk } from '../sign1'; | ||
export type JsonWebKey = SecretKeyJwk | PublicKeyJwk; | ||
import { PublicKeyJwk, PrivateKeyJwk } from '../sign1'; | ||
export type JsonWebKey = PrivateKeyJwk | PublicKeyJwk; | ||
export type CoseMapKey = string | number; | ||
@@ -4,0 +4,0 @@ export type CoseMapValue = Uint8Array | ArrayBuffer | string | number | Map<CoseMapKey, unknown>; |
import { CoseKey } from "."; | ||
import { SecretKeyJwk } from "../sign1"; | ||
export declare const extracePublicKeyJwk: (privateKeyJwk: SecretKeyJwk) => { | ||
import { PrivateKeyJwk } from "../sign1"; | ||
export declare const extractPublicKeyJwk: (privateKeyJwk: PrivateKeyJwk) => { | ||
alg?: string | undefined; | ||
@@ -18,2 +18,2 @@ crv?: string | undefined; | ||
export declare const extractPublicCoseKey: (secretKey: CoseKey) => Map<import(".").CoseMapKey, import(".").CoseMapValue>; | ||
export declare const publicFromPrivate: <T>(secretKey: SecretKeyJwk | CoseKey) => T; | ||
export declare const publicFromPrivate: <T>(secretKey: PrivateKeyJwk | CoseKey) => T; |
@@ -14,4 +14,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.publicFromPrivate = exports.extractPublicCoseKey = exports.extracePublicKeyJwk = void 0; | ||
const extracePublicKeyJwk = (privateKeyJwk) => { | ||
exports.publicFromPrivate = exports.extractPublicCoseKey = exports.extractPublicKeyJwk = void 0; | ||
const Params_1 = require("../Params"); | ||
const extractPublicKeyJwk = (privateKeyJwk) => { | ||
if (privateKeyJwk.kty !== 'EC') { | ||
@@ -24,12 +25,12 @@ throw new Error('Only EC keys are supported'); | ||
}; | ||
exports.extracePublicKeyJwk = extracePublicKeyJwk; | ||
exports.extractPublicKeyJwk = extractPublicKeyJwk; | ||
const extractPublicCoseKey = (secretKey) => { | ||
const publicCoseKeyMap = new Map(secretKey); | ||
if (publicCoseKeyMap.get(1) !== 2) { | ||
if (publicCoseKeyMap.get(Params_1.Key.Kty) !== Params_1.KeyTypes.EC2) { | ||
throw new Error('Only EC2 keys are supported'); | ||
} | ||
if (!publicCoseKeyMap.get(-4)) { | ||
if (!publicCoseKeyMap.get(Params_1.EC2.D)) { | ||
throw new Error('privateKey is not a secret / private key (has no d / -4)'); | ||
} | ||
publicCoseKeyMap.delete(-4); | ||
publicCoseKeyMap.delete(Params_1.EC2.D); | ||
return publicCoseKeyMap; | ||
@@ -40,3 +41,3 @@ }; | ||
if (secretKey.kty) { | ||
return (0, exports.extracePublicKeyJwk)(secretKey); | ||
return (0, exports.extractPublicKeyJwk)(secretKey); | ||
} | ||
@@ -43,0 +44,0 @@ return (0, exports.extractPublicCoseKey)(secretKey); |
import { calculateJwkThumbprint, calculateJwkThumbprintUri } from "jose"; | ||
import { CoseKey } from "."; | ||
export declare const thumbprint: { | ||
calculateJwkThumbprint: typeof calculateJwkThumbprint; | ||
calculateJwkThumbprintUri: typeof calculateJwkThumbprintUri; | ||
calculateCoseKeyThumbprint: (coseKey: Map<any, any>) => Promise<ArrayBuffer>; | ||
calculateCoseKeyThumbprintUri: (coseKey: Map<any, any>) => Promise<string>; | ||
uri: (coseKey: Map<any, any>) => Promise<string>; | ||
calculateCoseKeyThumbprint: (coseKey: CoseKey) => Promise<ArrayBuffer>; | ||
calculateCoseKeyThumbprintUri: (coseKey: CoseKey) => Promise<string>; | ||
uri: (coseKey: CoseKey) => Promise<string>; | ||
}; |
@@ -19,8 +19,12 @@ "use strict"; | ||
const subtleCryptoProvider_1 = __importDefault(require("../../crypto/subtleCryptoProvider")); | ||
const Params_1 = require("../Params"); | ||
// https://www.ietf.org/archive/id/draft-ietf-cose-key-thumbprint-01.html#section-6 | ||
const calculateCoseKeyThumbprint = (coseKey) => __awaiter(void 0, void 0, void 0, function* () { | ||
if (coseKey.get(Params_1.Key.Kty) !== Params_1.KeyTypes.EC2) { | ||
throw new Error('Unsupported key type (Only EC2 are supported'); | ||
} | ||
const onlyRequiredMap = new Map(); | ||
const requriedKeys = [1, -1, -2, -3]; | ||
const requiredKeys = [Params_1.EC2.Kty, Params_1.EC2.Crv, Params_1.EC2.X, Params_1.EC2.Y]; | ||
for (const [key, value] of coseKey.entries()) { | ||
if (requriedKeys.includes(key)) { | ||
if (requiredKeys.includes(key)) { | ||
onlyRequiredMap.set(key, value); | ||
@@ -27,0 +31,0 @@ } |
@@ -71,2 +71,3 @@ export type HeaderMapEntry = [number, any]; | ||
ES256: number; | ||
ES384: number; | ||
}; | ||
@@ -85,18 +86,26 @@ export declare const KeyAgreement: { | ||
}; | ||
export declare const EC2 = 2; | ||
export declare const KeyTypes: { | ||
EC2: number; | ||
}; | ||
export declare const KeyType = 1; | ||
export declare const KeyAlg = 3; | ||
export declare const KeyCurve = -1; | ||
export declare const KeyId = 2; | ||
export declare const Key: { | ||
Kty: number; | ||
Alg: number; | ||
Kid: number; | ||
}; | ||
export declare const Epk: { | ||
Kty: number; | ||
Crv: number; | ||
Alg: number; | ||
Kid: number; | ||
}; | ||
export declare const Key: { | ||
export declare const KeyTypes: { | ||
EC2: number; | ||
}; | ||
export declare const EC2: { | ||
Crv: number; | ||
X: number; | ||
Y: number; | ||
D: number; | ||
Kty: number; | ||
Crv: number; | ||
Alg: number; | ||
Kid: number; | ||
}; | ||
@@ -103,0 +112,0 @@ export declare const Curves: { |
"use strict"; | ||
// This module is just just a limited set of the IANA registries, | ||
// exposed to make Map initialization more readable | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.COSE_Encrypt = exports.COSE_Sign1 = exports.COSE_Encrypt0 = exports.Curves = exports.Key = exports.Epk = exports.KeyCurve = exports.KeyAlg = exports.KeyType = exports.KeyTypes = exports.EC2 = exports.Direct = exports.KeyWrap = exports.KeyAgreementWithKeyWrap = exports.KeyAgreement = exports.Signature = exports.Hash = exports.Aead = exports.A128GCM = exports.Unprotected = exports.Protected = exports.VerifiableDataProofTypes = exports.VerifiableDataStructures = exports.VerifiableDataProofs = exports.VerifiableDataStructure = exports.Receipts = exports.Type = exports.CWTClaims = exports.PayloadHashAlgorithm = exports.PayloadPreImageContentType = exports.PayloadLocation = exports.ContentType = exports.PartyVOther = exports.PartyVNonce = exports.PartyVIdentity = exports.PartyUOther = exports.PartyUNonce = exports.PartyUIdentity = exports.HeaderParameters = exports.UnprotectedHeader = exports.ProtectedHeader = void 0; | ||
exports.COSE_Encrypt = exports.COSE_Sign1 = exports.COSE_Encrypt0 = exports.Curves = exports.EC2 = exports.KeyTypes = exports.Epk = exports.Key = exports.KeyId = exports.KeyAlg = exports.KeyType = exports.Direct = exports.KeyWrap = exports.KeyAgreementWithKeyWrap = exports.KeyAgreement = exports.Signature = exports.Hash = exports.Aead = exports.A128GCM = exports.Unprotected = exports.Protected = exports.VerifiableDataProofTypes = exports.VerifiableDataStructures = exports.VerifiableDataProofs = exports.VerifiableDataStructure = exports.Receipts = exports.Type = exports.CWTClaims = exports.PayloadHashAlgorithm = exports.PayloadPreImageContentType = exports.PayloadLocation = exports.ContentType = exports.PartyVOther = exports.PartyVNonce = exports.PartyVIdentity = exports.PartyUOther = exports.PartyUNonce = exports.PartyUIdentity = exports.HeaderParameters = exports.UnprotectedHeader = exports.ProtectedHeader = void 0; | ||
const ProtectedHeader = (entries) => { | ||
@@ -72,3 +71,4 @@ return new Map(entries); | ||
exports.Signature = { | ||
'ES256': -7 | ||
'ES256': -7, | ||
'ES384': -35 | ||
}; | ||
@@ -87,19 +87,15 @@ exports.KeyAgreement = { | ||
}; | ||
exports.EC2 = 2; | ||
exports.KeyTypes = { | ||
EC2: exports.EC2 | ||
}; | ||
exports.KeyType = 1; | ||
exports.KeyAlg = 3; | ||
exports.KeyCurve = -1; | ||
exports.Epk = { | ||
Kty: exports.KeyType, | ||
Crv: exports.KeyCurve, | ||
Alg: exports.KeyAlg | ||
}; | ||
exports.KeyId = 2; | ||
exports.Key = { | ||
Kty: exports.KeyType, | ||
Crv: exports.KeyCurve, | ||
Alg: exports.KeyAlg | ||
Alg: exports.KeyAlg, | ||
Kid: exports.KeyId | ||
}; | ||
exports.Epk = Object.assign({}, exports.Key); | ||
exports.KeyTypes = { | ||
EC2: 2 | ||
}; | ||
exports.EC2 = Object.assign(Object.assign({}, exports.Key), { Crv: -1, X: -2, Y: -3, D: -4 }); | ||
exports.Curves = { | ||
@@ -106,0 +102,0 @@ P256: 1, |
@@ -14,2 +14,3 @@ "use strict"; | ||
const cbor_1 = require("../../cbor"); | ||
const Params_1 = require("../Params"); | ||
const add = (signature, receipt) => __awaiter(void 0, void 0, void 0, function* () { | ||
@@ -24,7 +25,7 @@ const { tag, value } = (0, cbor_1.decodeFirstSync)(signature); | ||
// unprotected header | ||
const receipts = value[1].get(394) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
const receipts = value[1].get(Params_1.Receipts) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
receipts.push(receipt); | ||
value[1].set(394, receipts); | ||
value[1].set(Params_1.Receipts, receipts); | ||
return (0, cbor_1.toArrayBuffer)(yield (0, cbor_1.encodeAsync)(new cbor_1.Tagged(cbor_1.Sign1Tag, value), { canonical: true })); | ||
}); | ||
exports.add = add; |
@@ -19,3 +19,3 @@ "use strict"; | ||
const consistencyVds = protectedHeader.get(__1.Protected.VerifiableDataStructure); | ||
if (consistencyVds !== 1) { | ||
if (consistencyVds !== __1.VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs'); | ||
@@ -30,3 +30,3 @@ } | ||
const inclusionVds = receiptProtectedHeader.get(__1.Protected.VerifiableDataStructure); | ||
if (inclusionVds !== 1) { | ||
if (inclusionVds !== __1.VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs'); | ||
@@ -33,0 +33,0 @@ } |
@@ -24,3 +24,3 @@ "use strict"; | ||
const vds = protectedHeader.get(__1.Protected.VerifiableDataStructure); | ||
if (vds !== 1) { | ||
if (vds !== __1.VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs'); | ||
@@ -27,0 +27,0 @@ } |
@@ -14,2 +14,3 @@ "use strict"; | ||
const cbor_1 = require("../../cbor"); | ||
const Params_1 = require("../Params"); | ||
const get = (signature) => __awaiter(void 0, void 0, void 0, function* () { | ||
@@ -24,5 +25,5 @@ const { tag, value } = (0, cbor_1.decodeFirstSync)(signature); | ||
// unprotected header | ||
const receipts = value[1].get(394) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
const receipts = value[1].get(Params_1.Receipts) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
return receipts; | ||
}); | ||
exports.get = get; |
@@ -18,3 +18,3 @@ "use strict"; | ||
const vds = protectedHeader.get(__1.Protected.VerifiableDataStructure); | ||
if (vds !== 1) { | ||
if (vds !== __1.VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs'); | ||
@@ -21,0 +21,0 @@ } |
@@ -24,3 +24,3 @@ "use strict"; | ||
const vds = protectedHeader.get(__1.Protected.VerifiableDataStructure); | ||
if (vds !== 1) { | ||
if (vds !== __1.VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs'); | ||
@@ -27,0 +27,0 @@ } |
@@ -7,2 +7,5 @@ "use strict"; | ||
joseToCose.set('ES512', `SHA-512`); | ||
// fully specified | ||
joseToCose.set('ESP256', `SHA-256`); | ||
joseToCose.set('ESP384', `SHA-384`); | ||
const getDigestFromVerificationKey = (alg) => { | ||
@@ -9,0 +12,0 @@ const digestAlg = joseToCose.get(alg); |
@@ -26,3 +26,3 @@ "use strict"; | ||
const hashEnvelopeAlgorithm = protectedHeader.get(Params_1.Protected.PayloadHashAlgorithm); | ||
if (hashEnvelopeAlgorithm !== -16) { | ||
if (hashEnvelopeAlgorithm !== Params_1.Hash.SHA256) { | ||
throw new Error('Unsupported hash envelope algorithm (-16 is only one supported)'); | ||
@@ -29,0 +29,0 @@ } |
@@ -9,7 +9,7 @@ /// <reference types="node" /> | ||
}; | ||
export type SecretKeyJwk = JsonWebKey & { | ||
export type PrivateKeyJwk = JsonWebKey & { | ||
d: string; | ||
kid?: string; | ||
}; | ||
export type PublicKeyJwk = Omit<SecretKeyJwk, 'd'>; | ||
export type PublicKeyJwk = Omit<PrivateKeyJwk, 'd'>; | ||
export type RequestCoseSign1Signer = { | ||
@@ -16,0 +16,0 @@ remote: { |
@@ -16,9 +16,11 @@ "use strict"; | ||
const cbor_1 = require("../../cbor"); | ||
const getAlgFromVerificationKey_1 = __importDefault(require("./getAlgFromVerificationKey")); | ||
const verifier_1 = __importDefault(require("../../crypto/verifier")); | ||
const iana_1 = require("../../iana"); | ||
const Params_1 = require("../Params"); | ||
const verifier = ({ resolver }) => { | ||
return { | ||
verify: ({ coseSign1, externalAAD }) => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a; | ||
const publicKeyJwk = yield resolver.resolve(coseSign1); | ||
const algInPublicKey = (0, getAlgFromVerificationKey_1.default)(`${publicKeyJwk.alg}`); | ||
const algInPublicKey = parseInt(`${(_a = iana_1.iana['COSE Algorithms'].getByName(`${publicKeyJwk.alg}`)) === null || _a === void 0 ? void 0 : _a.Value}`, 10); | ||
const ecdsa = (0, verifier_1.default)({ publicKeyJwk }); | ||
@@ -33,5 +35,6 @@ const obj = yield (0, cbor_1.decodeFirst)(coseSign1); | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const [protectedHeaderBytes, _, payload, signature] = signatureStructure; | ||
const protectedHeaderMap = (!protectedHeaderBytes.length) ? new Map() : (0, cbor_1.decodeFirstSync)(protectedHeaderBytes); | ||
const algInHeader = protectedHeaderMap.get(1); | ||
const algInHeader = protectedHeaderMap.get(Params_1.Protected.Alg); | ||
if (algInHeader !== algInPublicKey) { | ||
@@ -38,0 +41,0 @@ throw new Error('Verification key does not support algorithm: ' + algInHeader); |
@@ -1,4 +0,4 @@ | ||
import { SecretKeyJwk } from '../cose/sign1'; | ||
import { PrivateKeyJwk } from '../cose/sign1'; | ||
declare const signer: ({ privateKeyJwk }: { | ||
privateKeyJwk: SecretKeyJwk; | ||
privateKeyJwk: PrivateKeyJwk; | ||
}) => { | ||
@@ -5,0 +5,0 @@ sign: (toBeSigned: ArrayBuffer) => Promise<ArrayBuffer>; |
"use strict"; | ||
/* eslint-disable @typescript-eslint/no-unused-vars */ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -11,2 +12,13 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -21,8 +33,9 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
const digest = (0, getDigestFromVerificationKey_1.default)(`${privateKeyJwk.alg}`); | ||
const { alg } = privateKeyJwk, withoutAlg = __rest(privateKeyJwk, ["alg"]); | ||
return { | ||
sign: (toBeSigned) => __awaiter(void 0, void 0, void 0, function* () { | ||
const subtle = yield (0, subtleCryptoProvider_1.default)(); | ||
const signingKey = yield subtle.importKey("jwk", privateKeyJwk, { | ||
const signingKey = yield subtle.importKey("jwk", withoutAlg, { | ||
name: "ECDSA", | ||
namedCurve: privateKeyJwk.crv, | ||
namedCurve: withoutAlg.crv, | ||
}, true, ["sign"]); | ||
@@ -29,0 +42,0 @@ const signature = yield subtle.sign({ |
@@ -11,2 +11,13 @@ "use strict"; | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -20,8 +31,10 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
const digest = (0, getDigestFromVerificationKey_1.default)(`${publicKeyJwk.alg}`); | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const { alg } = publicKeyJwk, withoutAlg = __rest(publicKeyJwk, ["alg"]); | ||
return { | ||
verify: (toBeSigned, signature) => __awaiter(void 0, void 0, void 0, function* () { | ||
const subtle = yield (0, subtleCryptoProvider_1.default)(); | ||
const verificationKey = yield subtle.importKey("jwk", publicKeyJwk, { | ||
const verificationKey = yield subtle.importKey("jwk", withoutAlg, { | ||
name: "ECDSA", | ||
namedCurve: publicKeyJwk.crv, | ||
namedCurve: withoutAlg.crv, | ||
}, true, ["verify"]); | ||
@@ -28,0 +41,0 @@ const verified = yield subtle.verify({ |
@@ -11,2 +11,3 @@ /// <reference types="node" /> | ||
exp: string; | ||
serial: string; | ||
}; | ||
@@ -13,0 +14,0 @@ export type RootCertificateResponse = { |
@@ -52,2 +52,12 @@ "use strict"; | ||
const algTowebCryptoParams = { | ||
'ESP256': { | ||
name: "ECDSA", | ||
hash: "SHA-256", | ||
namedCurve: "P-256", | ||
}, | ||
'ESP384': { | ||
name: "ECDSA", | ||
hash: "SHA-384", | ||
namedCurve: "P-384", | ||
}, | ||
'ES256': { | ||
@@ -72,3 +82,3 @@ name: "ECDSA", | ||
const current = new x509.X509Certificate(cert); | ||
return [-16, yield current.getThumbprint('SHA-256')]; | ||
return [__1.Hash.SHA256, yield current.getThumbprint('SHA-256')]; | ||
}); | ||
@@ -86,3 +96,3 @@ const root = (req) => __awaiter(void 0, void 0, void 0, function* () { | ||
const caCert = yield x509.X509CertificateGenerator.create({ | ||
serialNumber: "01", | ||
serialNumber: req.serial || "01", | ||
subject: req.sub, | ||
@@ -89,0 +99,0 @@ issuer: req.iss, |
{ | ||
"name": "@transmute/cose", | ||
"version": "0.2.11", | ||
"version": "0.2.12", | ||
"description": "COSE and related work.", | ||
@@ -5,0 +5,0 @@ "main": "./dist/index.js", |
import { base64url, calculateJwkThumbprint } from "jose"; | ||
import { CoseKey } from "."; | ||
import { IANACOSEAlgorithms } from '../algorithms'; | ||
import { IANACOSEEllipticCurves } from '../elliptic-curves'; | ||
const algorithms = Object.values(IANACOSEAlgorithms) | ||
const curves = Object.values(IANACOSEEllipticCurves) | ||
import { formatJwk } from "./formatJwk"; | ||
import { iana } from "../../iana"; | ||
import { EC2, Key, KeyTypes } from "../Params"; | ||
export const convertCoseKeyToJsonWebKey = async <T>(coseKey: CoseKey): Promise<T> => { | ||
const kty = coseKey.get(1) as number | ||
const kid = coseKey.get(2) | ||
const alg = coseKey.get(3) | ||
const crv = coseKey.get(-1) | ||
// kty EC, kty: EK | ||
if (![2, 5].includes(kty)) { | ||
const kty = coseKey.get(Key.Kty) as number | ||
// kty EC2 | ||
if (![KeyTypes.EC2].includes(kty)) { | ||
throw new Error('This library requires does not support the given key type') | ||
} | ||
const foundAlgorithm = algorithms.find((param) => { | ||
return param.Value === `${alg}` | ||
}) | ||
const kid = coseKey.get(Key.Kid) | ||
const alg = coseKey.get(Key.Alg) | ||
const crv = coseKey.get(EC2.Crv) | ||
const foundAlgorithm = iana["COSE Algorithms"].getByValue(alg as number) | ||
if (!foundAlgorithm) { | ||
@@ -39,5 +36,5 @@ throw new Error('This library requires keys to use fully specified algorithms') | ||
} as any | ||
const x = coseKey.get(-2) as any | ||
const y = coseKey.get(-3) as any | ||
const d = coseKey.get(-4) as any | ||
const x = coseKey.get(EC2.X) as any | ||
const y = coseKey.get(EC2.Y) as any | ||
const d = coseKey.get(EC2.D) as any | ||
if (x) { | ||
@@ -44,0 +41,0 @@ jwk.x = base64url.encode(x) |
@@ -6,10 +6,8 @@ | ||
import { IANACOSEKeyCommonParameters } from '../key-common-parameters'; | ||
import { IANACOSEAlgorithms } from '../algorithms'; | ||
import { IANACOSEKeyTypeParameters, IANACOSEKeyTypeParameter } from '../key-type-parameters'; | ||
import { IANACOSEKeyTypes } from '../key-type'; | ||
import { IANACOSEEllipticCurves } from '../elliptic-curves'; | ||
import { PublicKeyJwk, SecretKeyJwk } from '../sign1'; | ||
import { PublicKeyJwk, PrivateKeyJwk } from '../sign1'; | ||
import { iana } from '../../iana'; | ||
const algorithms = Object.values(IANACOSEAlgorithms) | ||
const commonParams = Object.values(IANACOSEKeyCommonParameters) | ||
@@ -44,3 +42,3 @@ const keyTypeParams = Object.values(IANACOSEKeyTypeParameters) | ||
export const convertJsonWebKeyToCoseKey = async <T>(jwk: PublicKeyJwk | SecretKeyJwk): Promise<T> => { | ||
export const convertJsonWebKeyToCoseKey = async <T>(jwk: PublicKeyJwk | PrivateKeyJwk): Promise<T> => { | ||
@@ -87,5 +85,3 @@ const { kty } = jwk | ||
if (foundCommonParam) { | ||
const foundAlgorithm = algorithms.find((param) => { | ||
return param.Name === value | ||
}) | ||
const foundAlgorithm = iana['COSE Algorithms'].getByName(value) | ||
if (foundAlgorithm) { | ||
@@ -92,0 +88,0 @@ coseKey.set(label, parseInt(foundAlgorithm.Value, 10)) |
@@ -9,4 +9,5 @@ | ||
import { CoseKey } from '.' | ||
export type CoseKeyAgreementAlgorithms = 'ECDH-ES+A128KW' | ||
export type CoseSignatureAlgorithms = 'ES256' | 'ES384' | 'ES512' | ||
export type CoseSignatureAlgorithms = 'ES256' | 'ES384' | 'ES512' | 'ESP256' | 'ESP384' | ||
export type ContentTypeOfJsonWebKey = 'application/jwk+json' | ||
@@ -22,5 +23,7 @@ export type ContentTypeOfCoseKey = 'application/cose-key' | ||
import { iana } from '../../iana' | ||
import { Key } from "../Params" | ||
export const generate = async <T>(alg: CoseSignatureAlgorithms, contentType: PrivateKeyContentType = 'application/jwk+json'): Promise<T> => { | ||
const knownAlgorithm = Object.values(IANACOSEAlgorithms).find(( | ||
let knownAlgorithm = Object.values(IANACOSEAlgorithms).find(( | ||
entry | ||
@@ -31,5 +34,11 @@ ) => { | ||
if (!knownAlgorithm) { | ||
knownAlgorithm = iana["COSE Algorithms"].getByName(alg) | ||
} | ||
if (!knownAlgorithm) { | ||
throw new Error('Algorithm is not supported.') | ||
} | ||
const cryptoKeyPair = await generateKeyPair(knownAlgorithm.Name, { extractable: true }); | ||
const cryptoKeyPair = await generateKeyPair( | ||
iana["COSE Algorithms"]["less-specified"](knownAlgorithm.Name), | ||
{ extractable: true } | ||
); | ||
const privateKeyJwk = await exportJWK(cryptoKeyPair.privateKey) | ||
@@ -46,3 +55,3 @@ const jwkThumbprint = await calculateJwkThumbprint(privateKeyJwk) | ||
const coseKeyThumbprint = await thumbprint.calculateCoseKeyThumbprint(secretKeyCoseKey) | ||
secretKeyCoseKey.set(2, coseKeyThumbprint) | ||
secretKeyCoseKey.set(Key.Kid, coseKeyThumbprint) | ||
return secretKeyCoseKey as T | ||
@@ -49,0 +58,0 @@ } |
import { PublicKeyJwk, SecretKeyJwk } from '../sign1' | ||
import { PublicKeyJwk, PrivateKeyJwk } from '../sign1' | ||
export type JsonWebKey = SecretKeyJwk | PublicKeyJwk | ||
export type JsonWebKey = PrivateKeyJwk | PublicKeyJwk | ||
@@ -8,0 +8,0 @@ export type CoseMapKey = string | number |
import { CoseKey } from "."; | ||
import { SecretKeyJwk } from "../sign1"; | ||
import { EC2, Key, KeyTypes } from "../Params"; | ||
import { PrivateKeyJwk } from "../sign1"; | ||
export const extracePublicKeyJwk = (privateKeyJwk: SecretKeyJwk) => { | ||
export const extractPublicKeyJwk = (privateKeyJwk: PrivateKeyJwk) => { | ||
if (privateKeyJwk.kty !== 'EC') { | ||
@@ -16,17 +17,17 @@ throw new Error('Only EC keys are supported') | ||
const publicCoseKeyMap = new Map(secretKey) | ||
if (publicCoseKeyMap.get(1) !== 2) { | ||
if (publicCoseKeyMap.get(Key.Kty) !== KeyTypes.EC2) { | ||
throw new Error('Only EC2 keys are supported') | ||
} | ||
if (!publicCoseKeyMap.get(-4)) { | ||
if (!publicCoseKeyMap.get(EC2.D)) { | ||
throw new Error('privateKey is not a secret / private key (has no d / -4)') | ||
} | ||
publicCoseKeyMap.delete(-4); | ||
publicCoseKeyMap.delete(EC2.D); | ||
return publicCoseKeyMap | ||
} | ||
export const publicFromPrivate = <T>(secretKey: SecretKeyJwk | CoseKey) => { | ||
if ((secretKey as any).kty) { | ||
return extracePublicKeyJwk(secretKey as SecretKeyJwk) as T | ||
export const publicFromPrivate = <T>(secretKey: PrivateKeyJwk | CoseKey) => { | ||
if ((secretKey as PrivateKeyJwk).kty) { | ||
return extractPublicKeyJwk(secretKey as PrivateKeyJwk) as T | ||
} | ||
return extractPublicCoseKey(secretKey as CoseKey) as T | ||
} |
@@ -8,3 +8,3 @@ | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
if ((key as any).kty) { | ||
if ((key as JWK).kty) { | ||
return JSON.stringify(key, null, 2) | ||
@@ -11,0 +11,0 @@ } |
@@ -6,9 +6,14 @@ import { calculateJwkThumbprint, calculateJwkThumbprintUri, base64url } from "jose"; | ||
import subtleCryptoProvider from "../../crypto/subtleCryptoProvider"; | ||
import { EC2, Key, KeyTypes } from "../Params"; | ||
import { CoseKey } from "."; | ||
// https://www.ietf.org/archive/id/draft-ietf-cose-key-thumbprint-01.html#section-6 | ||
const calculateCoseKeyThumbprint = async (coseKey: Map<any, any>): Promise<ArrayBuffer> => { | ||
const calculateCoseKeyThumbprint = async (coseKey: CoseKey): Promise<ArrayBuffer> => { | ||
if (coseKey.get(Key.Kty) !== KeyTypes.EC2) { | ||
throw new Error('Unsupported key type (Only EC2 are supported') | ||
} | ||
const onlyRequiredMap = new Map() | ||
const requriedKeys = [1, -1, -2, -3] | ||
const requiredKeys = [EC2.Kty, EC2.Crv, EC2.X, EC2.Y] | ||
for (const [key, value] of coseKey.entries()) { | ||
if (requriedKeys.includes(key as number)) { | ||
if (requiredKeys.includes(key as number)) { | ||
onlyRequiredMap.set(key, value) | ||
@@ -23,3 +28,3 @@ } | ||
const calculateCoseKeyThumbprintUri = async (coseKey: Map<any, any>): Promise<string> => { | ||
const calculateCoseKeyThumbprintUri = async (coseKey: CoseKey): Promise<string> => { | ||
const prefix = `urn:ietf:params:oauth:ckt:sha-256` | ||
@@ -26,0 +31,0 @@ const digest = await calculateCoseKeyThumbprint(coseKey) |
@@ -0,1 +1,3 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
// This module is just just a limited set of the IANA registries, | ||
@@ -99,3 +101,4 @@ // exposed to make Map initialization more readable | ||
export const Signature = { | ||
'ES256': -7 | ||
'ES256': -7, | ||
'ES384': -35 | ||
} | ||
@@ -119,24 +122,30 @@ | ||
export const EC2 = 2 | ||
export const KeyTypes = { | ||
EC2 | ||
} | ||
export const KeyType = 1 | ||
export const KeyAlg = 3 | ||
export const KeyCurve = -1 | ||
export const KeyId = 2 | ||
export const Epk = { | ||
export const Key = { | ||
Kty: KeyType, | ||
Crv: KeyCurve, | ||
Alg: KeyAlg | ||
Alg: KeyAlg, | ||
Kid: KeyId | ||
} | ||
export const Key = { | ||
Kty: KeyType, | ||
Crv: KeyCurve, | ||
Alg: KeyAlg | ||
export const Epk = { | ||
...Key | ||
} | ||
export const KeyTypes = { | ||
EC2: 2 | ||
} | ||
export const EC2 = { | ||
...Key, | ||
Crv: -1, | ||
X: -2, | ||
Y: -3, | ||
D: -4 | ||
} | ||
export const Curves = { | ||
@@ -143,0 +152,0 @@ P256: 1, |
import { decodeFirstSync, toArrayBuffer, encodeAsync, Tagged, Sign1Tag } from '../../cbor' | ||
import { Receipts } from '../Params'; | ||
import { CoseSign1Bytes } from "../sign1"; | ||
@@ -13,6 +14,6 @@ | ||
// unprotected header | ||
const receipts = value[1].get(394) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
const receipts = value[1].get(Receipts) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
receipts.push(receipt) | ||
value[1].set(394, receipts) | ||
value[1].set(Receipts, receipts) | ||
return toArrayBuffer(await encodeAsync(new Tagged(Sign1Tag, value), { canonical: true })); | ||
} |
import { CoMETRE } from '@transmute/rfc9162' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes } from '../../..' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes, VerifiableDataStructures } from '../../..' | ||
@@ -19,3 +19,3 @@ import { CoseSign1Bytes, CoseSign1Signer, ProtectedHeaderMap } from "../../sign1" | ||
const consistencyVds = protectedHeader.get(Protected.VerifiableDataStructure) | ||
if (consistencyVds !== 1) { | ||
if (consistencyVds !== VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs') | ||
@@ -32,3 +32,3 @@ } | ||
const inclusionVds = receiptProtectedHeader.get(Protected.VerifiableDataStructure); | ||
if (inclusionVds !== 1) { | ||
if (inclusionVds !== VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs') | ||
@@ -35,0 +35,0 @@ } |
import { CoMETRE } from '@transmute/rfc9162' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes } from '../../..' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes, VerifiableDataStructures } from '../../..' | ||
@@ -24,3 +24,3 @@ import { CoseSign1Bytes, CoseSign1DetachedVerifier } from "../../sign1" | ||
const vds = protectedHeader.get(Protected.VerifiableDataStructure); | ||
if (vds !== 1) { | ||
if (vds !== VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs') | ||
@@ -27,0 +27,0 @@ } |
import { decodeFirstSync, Sign1Tag } from '../../cbor' | ||
import { Receipts } from '../Params'; | ||
import { CoseSign1Bytes } from "../sign1"; | ||
@@ -13,4 +14,4 @@ | ||
// unprotected header | ||
const receipts = value[1].get(394) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
const receipts = value[1].get(Receipts) || []; // see https://datatracker.ietf.org/doc/draft-ietf-scitt-architecture/ | ||
return receipts | ||
} |
import { CoMETRE } from '@transmute/rfc9162' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes } from '../../..' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes, VerifiableDataStructures } from '../../..' | ||
@@ -18,3 +18,3 @@ import { CoseSign1Signer, ProtectedHeaderMap } from "../../sign1" | ||
const vds = protectedHeader.get(Protected.VerifiableDataStructure) | ||
if (vds !== 1) { | ||
if (vds !== VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs') | ||
@@ -21,0 +21,0 @@ } |
import { CoMETRE } from '@transmute/rfc9162' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes } from '../../..' | ||
import { cbor, Protected, Unprotected, VerifiableDataProofTypes, VerifiableDataStructures } from '../../..' | ||
@@ -23,3 +23,3 @@ import { CoseSign1Bytes, CoseSign1DetachedVerifier } from "../../sign1" | ||
const vds = protectedHeader.get(Protected.VerifiableDataStructure); | ||
if (vds !== 1) { | ||
if (vds !== VerifiableDataStructures['RFC9162-Binary-Merkle-Tree']) { | ||
throw new Error('Unsupported verifiable data structure. See https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs') | ||
@@ -26,0 +26,0 @@ } |
const joseToCose = new Map<string, string>() | ||
joseToCose.set('ES256', `SHA-256`) | ||
@@ -8,2 +9,6 @@ joseToCose.set('ES384', `SHA-384`) | ||
// fully specified | ||
joseToCose.set('ESP256', `SHA-256`) | ||
joseToCose.set('ESP384', `SHA-384`) | ||
const getDigestFromVerificationKey = (alg: string): string => { | ||
@@ -10,0 +15,0 @@ const digestAlg = joseToCose.get(alg) |
@@ -9,6 +9,4 @@ import signer from "./signer"; | ||
import { Hash, Protected } from "../Params"; | ||
import { Protected } from "../Params"; | ||
export const hash = { | ||
@@ -20,3 +18,3 @@ signer: ({ remote }: RequestCoseSign1Signer) => { | ||
const hashEnvelopeAlgorithm = protectedHeader.get(Protected.PayloadHashAlgorithm) | ||
if (hashEnvelopeAlgorithm !== -16) { | ||
if (hashEnvelopeAlgorithm !== Hash.SHA256) { | ||
throw new Error('Unsupported hash envelope algorithm (-16 is only one supported)') | ||
@@ -23,0 +21,0 @@ } |
import { decodeFirst, decodeFirstSync, encode, EMPTY_BUFFER } from '../../cbor' | ||
import { DecodedToBeSigned, ProtectedHeaderMap } from './types' | ||
import { decodeFirst, encode } from '../../cbor' | ||
export const attach = async (coseSign1Bytes: ArrayBuffer, payload: ArrayBuffer) => { | ||
@@ -7,0 +7,0 @@ const obj = await decodeFirst(coseSign1Bytes); |
@@ -11,4 +11,4 @@ | ||
export type SecretKeyJwk = JsonWebKey & { d: string, kid?: string } | ||
export type PublicKeyJwk = Omit<SecretKeyJwk, 'd'> | ||
export type PrivateKeyJwk = JsonWebKey & { d: string, kid?: string } | ||
export type PublicKeyJwk = Omit<PrivateKeyJwk, 'd'> | ||
@@ -15,0 +15,0 @@ export type RequestCoseSign1Signer = { |
import { decodeFirst, decodeFirstSync, encode, EMPTY_BUFFER } from '../../cbor' | ||
import { RequestCoseSign1Verifier, RequestCoseSign1Verify } from './types' | ||
import getAlgFromVerificationKey from './getAlgFromVerificationKey' | ||
import { DecodedToBeSigned, ProtectedHeaderMap } from './types' | ||
import rawVerifier from '../../crypto/verifier' | ||
import { iana } from '../../iana' | ||
import { Protected } from '../Params' | ||
const verifier = ({ resolver }: RequestCoseSign1Verifier) => { | ||
@@ -12,3 +15,3 @@ return { | ||
const publicKeyJwk = await resolver.resolve(coseSign1) | ||
const algInPublicKey = getAlgFromVerificationKey(`${publicKeyJwk.alg}`) | ||
const algInPublicKey = parseInt(`${iana['COSE Algorithms'].getByName(`${publicKeyJwk.alg}`)?.Value}`, 10) | ||
const ecdsa = rawVerifier({ publicKeyJwk }) | ||
@@ -23,5 +26,6 @@ const obj = await decodeFirst(coseSign1); | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const [protectedHeaderBytes, _, payload, signature] = signatureStructure; | ||
const protectedHeaderMap: ProtectedHeaderMap = (!protectedHeaderBytes.length) ? new Map() : decodeFirstSync(protectedHeaderBytes); | ||
const algInHeader = protectedHeaderMap.get(1) | ||
const algInHeader = protectedHeaderMap.get(Protected.Alg) | ||
if (algInHeader !== algInPublicKey) { | ||
@@ -28,0 +32,0 @@ throw new Error('Verification key does not support algorithm: ' + algInHeader); |
@@ -0,4 +1,5 @@ | ||
/* eslint-disable @typescript-eslint/no-unused-vars */ | ||
import { toArrayBuffer } from '../cbor' | ||
import { SecretKeyJwk } from '../cose/sign1' | ||
import { PrivateKeyJwk } from '../cose/sign1' | ||
@@ -9,4 +10,5 @@ import subtleCryptoProvider from './subtleCryptoProvider' | ||
const signer = ({ privateKeyJwk }: { privateKeyJwk: SecretKeyJwk }) => { | ||
const signer = ({ privateKeyJwk }: { privateKeyJwk: PrivateKeyJwk }) => { | ||
const digest = getDigestFromVerificationKey(`${privateKeyJwk.alg}`) | ||
const { alg, ...withoutAlg } = privateKeyJwk | ||
return { | ||
@@ -17,6 +19,6 @@ sign: async (toBeSigned: ArrayBuffer): Promise<ArrayBuffer> => { | ||
"jwk", | ||
privateKeyJwk, | ||
withoutAlg, | ||
{ | ||
name: "ECDSA", | ||
namedCurve: privateKeyJwk.crv, | ||
namedCurve: withoutAlg.crv, | ||
}, | ||
@@ -23,0 +25,0 @@ true, |
@@ -12,2 +12,4 @@ | ||
const digest = getDigestFromVerificationKey(`${publicKeyJwk.alg}`) | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const { alg, ...withoutAlg } = publicKeyJwk | ||
return { | ||
@@ -18,6 +20,6 @@ verify: async (toBeSigned: ArrayBuffer, signature: ArrayBuffer): Promise<ArrayBuffer> => { | ||
"jwk", | ||
publicKeyJwk, | ||
withoutAlg, | ||
{ | ||
name: "ECDSA", | ||
namedCurve: publicKeyJwk.crv, | ||
namedCurve: withoutAlg.crv, | ||
}, | ||
@@ -24,0 +26,0 @@ true, |
import { exportJWK, exportPKCS8, importPKCS8 } from 'jose'; | ||
import { ProtectedHeaderMap, PublicKeyJwk } from "../cose/sign1" | ||
import { PublicKeyJwk } from "../cose/sign1" | ||
import * as x509 from "@peculiar/x509"; | ||
import { CoseSignatureAlgorithms } from '../cose/key'; | ||
import { IANACOSEAlgorithms, SecretKeyJwk, detached, RequestCoseSign1VerifyDetached } from '..'; | ||
import { decodeFirstSync } from '../cbor' | ||
import { IANACOSEAlgorithms, PrivateKeyJwk, detached, RequestCoseSign1VerifyDetached, Hash } from '..'; | ||
import { crypto } from '..'; | ||
@@ -32,2 +25,12 @@ | ||
= { | ||
'ESP256': { | ||
name: "ECDSA", | ||
hash: "SHA-256", | ||
namedCurve: "P-256", | ||
}, | ||
'ESP384': { | ||
name: "ECDSA", | ||
hash: "SHA-384", | ||
namedCurve: "P-384", | ||
}, | ||
'ES256': { | ||
@@ -56,2 +59,3 @@ name: "ECDSA", | ||
exp: string | ||
serial: string | ||
} | ||
@@ -62,3 +66,3 @@ | ||
const current = new x509.X509Certificate(cert) | ||
return [-16, await current.getThumbprint('SHA-256')] | ||
return [Hash.SHA256, await current.getThumbprint('SHA-256')] | ||
} | ||
@@ -79,3 +83,3 @@ | ||
const caCert = await x509.X509CertificateGenerator.create({ | ||
serialNumber: "01", | ||
serialNumber: req.serial || "01", | ||
subject: req.sub, | ||
@@ -106,3 +110,3 @@ issuer: req.iss, | ||
} | ||
const privateKeyJwk = await exportJWK(await importPKCS8(privateKeyPKCS8, `${foundAlgorithm.Name}`)) as SecretKeyJwk | ||
const privateKeyJwk = await exportJWK(await importPKCS8(privateKeyPKCS8, `${foundAlgorithm.Name}`)) as PrivateKeyJwk | ||
privateKeyJwk.alg = foundAlgorithm.Name; | ||
@@ -109,0 +113,0 @@ return detached.signer({ |
245896
6216