feat: 초기 프로젝트 설정 및 룰.md 파일 추가
This commit is contained in:
221
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/mdsTypes.d.ts
generated
vendored
Normal file
221
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/mdsTypes.d.ts
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
import type { Base64URLString } from '../types/index.js';
|
||||
/**
|
||||
* Metadata Service structures
|
||||
* https://fidoalliance.org/specs/mds/fido-metadata-service-v3.0-ps-20210518.html
|
||||
*/
|
||||
/** */
|
||||
export type MDSJWTHeader = {
|
||||
alg: string;
|
||||
typ: string;
|
||||
x5c: Base64URLString[];
|
||||
};
|
||||
export type MDSJWTPayload = {
|
||||
legalHeader: string;
|
||||
no: number;
|
||||
nextUpdate: string;
|
||||
entries: MetadataBLOBPayloadEntry[];
|
||||
};
|
||||
export type MetadataBLOBPayloadEntry = {
|
||||
aaid?: string;
|
||||
aaguid?: string;
|
||||
attestationCertificateKeyIdentifiers?: string[];
|
||||
metadataStatement?: MetadataStatement;
|
||||
biometricStatusReports?: BiometricStatusReport[];
|
||||
statusReports: StatusReport[];
|
||||
timeOfLastStatusChange: string;
|
||||
rogueListURL?: string;
|
||||
rogueListHash?: string;
|
||||
};
|
||||
export type BiometricStatusReport = {
|
||||
certLevel: number;
|
||||
modality: UserVerify;
|
||||
effectiveDate?: string;
|
||||
certificationDescriptor?: string;
|
||||
certificateNumber?: string;
|
||||
certificationPolicyVersion?: string;
|
||||
certificationRequirementsVersion?: string;
|
||||
};
|
||||
export type StatusReport = {
|
||||
status: AuthenticatorStatus;
|
||||
effectiveDate?: string;
|
||||
authenticatorVersion?: number;
|
||||
certificate?: string;
|
||||
url?: string;
|
||||
certificationDescriptor?: string;
|
||||
certificateNumber?: string;
|
||||
certificationPolicyVersion?: string;
|
||||
certificationRequirementsVersion?: string;
|
||||
};
|
||||
export type AuthenticatorStatus = 'NOT_FIDO_CERTIFIED' | 'FIDO_CERTIFIED' | 'USER_VERIFICATION_BYPASS' | 'ATTESTATION_KEY_COMPROMISE' | 'USER_KEY_REMOTE_COMPROMISE' | 'USER_KEY_PHYSICAL_COMPROMISE' | 'UPDATE_AVAILABLE' | 'REVOKED' | 'SELF_ASSERTION_SUBMITTED' | 'FIDO_CERTIFIED_L1' | 'FIDO_CERTIFIED_L1plus' | 'FIDO_CERTIFIED_L2' | 'FIDO_CERTIFIED_L2plus' | 'FIDO_CERTIFIED_L3' | 'FIDO_CERTIFIED_L3plus';
|
||||
/**
|
||||
* Types defined in the FIDO Metadata Statement spec
|
||||
*
|
||||
* See https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html
|
||||
*/
|
||||
export type CodeAccuracyDescriptor = {
|
||||
base: number;
|
||||
minLength: number;
|
||||
maxRetries?: number;
|
||||
blockSlowdown?: number;
|
||||
};
|
||||
export type BiometricAccuracyDescriptor = {
|
||||
selfAttestedFRR?: number;
|
||||
selfAttestedFAR?: number;
|
||||
maxTemplates?: number;
|
||||
maxRetries?: number;
|
||||
blockSlowdown?: number;
|
||||
};
|
||||
export type PatternAccuracyDescriptor = {
|
||||
minComplexity: number;
|
||||
maxRetries?: number;
|
||||
blockSlowdown?: number;
|
||||
};
|
||||
export type VerificationMethodDescriptor = {
|
||||
userVerificationMethod: UserVerify;
|
||||
caDesc?: CodeAccuracyDescriptor;
|
||||
baDesc?: BiometricAccuracyDescriptor;
|
||||
paDesc?: PatternAccuracyDescriptor;
|
||||
};
|
||||
export type VerificationMethodANDCombinations = VerificationMethodDescriptor[];
|
||||
export type rgbPaletteEntry = {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
};
|
||||
export type DisplayPNGCharacteristicsDescriptor = {
|
||||
width: number;
|
||||
height: number;
|
||||
bitDepth: number;
|
||||
colorType: number;
|
||||
compression: number;
|
||||
filter: number;
|
||||
interlace: number;
|
||||
plte?: rgbPaletteEntry[];
|
||||
};
|
||||
export type EcdaaTrustAnchor = {
|
||||
X: string;
|
||||
Y: string;
|
||||
c: string;
|
||||
sx: string;
|
||||
sy: string;
|
||||
G1Curve: string;
|
||||
};
|
||||
export type ExtensionDescriptor = {
|
||||
id: string;
|
||||
tag?: number;
|
||||
data?: string;
|
||||
fail_if_unknown: boolean;
|
||||
};
|
||||
/**
|
||||
* langCode -> "en-US", "ja-JP", etc...
|
||||
*/
|
||||
export type AlternativeDescriptions = {
|
||||
[langCode: string]: string;
|
||||
};
|
||||
export type MetadataStatement = {
|
||||
legalHeader?: string;
|
||||
aaid?: string;
|
||||
aaguid?: string;
|
||||
attestationCertificateKeyIdentifiers?: string[];
|
||||
description: string;
|
||||
alternativeDescriptions?: AlternativeDescriptions;
|
||||
authenticatorVersion: number;
|
||||
protocolFamily: string;
|
||||
schema: number;
|
||||
upv: Version[];
|
||||
authenticationAlgorithms: AlgSign[];
|
||||
publicKeyAlgAndEncodings: AlgKey[];
|
||||
attestationTypes: Attestation[];
|
||||
userVerificationDetails: VerificationMethodANDCombinations[];
|
||||
keyProtection: KeyProtection[];
|
||||
isKeyRestricted?: boolean;
|
||||
isFreshUserVerificationRequired?: boolean;
|
||||
matcherProtection: MatcherProtection[];
|
||||
cryptoStrength?: number;
|
||||
attachmentHint?: AttachmentHint[];
|
||||
tcDisplay: TransactionConfirmationDisplay[];
|
||||
tcDisplayContentType?: string;
|
||||
tcDisplayPNGCharacteristics?: DisplayPNGCharacteristicsDescriptor[];
|
||||
attestationRootCertificates: string[];
|
||||
ecdaaTrustAnchors?: EcdaaTrustAnchor[];
|
||||
icon?: string;
|
||||
supportedExtensions?: ExtensionDescriptor[];
|
||||
authenticatorGetInfo?: AuthenticatorGetInfo;
|
||||
};
|
||||
/**
|
||||
* Types declared in other specs
|
||||
*/
|
||||
/**
|
||||
* USER_VERIFY
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#user-verification-methods
|
||||
*/
|
||||
export type UserVerify = 'presence_internal' | 'fingerprint_internal' | 'passcode_internal' | 'voiceprint_internal' | 'faceprint_internal' | 'location_internal' | 'eyeprint_internal' | 'pattern_internal' | 'handprint_internal' | 'passcode_external' | 'pattern_external' | 'none' | 'all';
|
||||
/**
|
||||
* ALG_SIGN
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#authentication-algorithms
|
||||
*
|
||||
* Using this helpful TS pattern here so that we can strongly enforce the existence of COSE info
|
||||
* mappings in `algSignToCOSEInfoMap` in verifyAttestationWithMetadata.ts
|
||||
*/
|
||||
export type AlgSign = typeof AlgSign[number];
|
||||
declare const AlgSign: readonly ["secp256r1_ecdsa_sha256_raw", "secp256r1_ecdsa_sha256_der", "rsassa_pss_sha256_raw", "rsassa_pss_sha256_der", "secp256k1_ecdsa_sha256_raw", "secp256k1_ecdsa_sha256_der", "rsassa_pss_sha384_raw", "rsassa_pkcsv15_sha256_raw", "rsassa_pkcsv15_sha384_raw", "rsassa_pkcsv15_sha512_raw", "rsassa_pkcsv15_sha1_raw", "secp384r1_ecdsa_sha384_raw", "secp512r1_ecdsa_sha256_raw", "ed25519_eddsa_sha512_raw"];
|
||||
/**
|
||||
* ALG_KEY
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#public-key-representation-formats
|
||||
*/
|
||||
export type AlgKey = 'ecc_x962_raw' | 'ecc_x962_der' | 'rsa_2048_raw' | 'rsa_2048_der' | 'cose';
|
||||
/**
|
||||
* ATTESTATION
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#authenticator-attestation-types
|
||||
*/
|
||||
export type Attestation = 'basic_full' | 'basic_surrogate' | 'ecdaa' | 'attca' | 'anonca' | 'none';
|
||||
/**
|
||||
* KEY_PROTECTION
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#key-protection-types
|
||||
*/
|
||||
export type KeyProtection = 'software' | 'hardware' | 'tee' | 'secure_element' | 'remote_handle';
|
||||
/**
|
||||
* MATCHER_PROTECTION
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#matcher-protection-types
|
||||
*/
|
||||
export type MatcherProtection = 'software' | 'tee' | 'on_chip';
|
||||
/**
|
||||
* ATTACHMENT_HINT
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#authenticator-attachment-hints
|
||||
*/
|
||||
export type AttachmentHint = 'internal' | 'external' | 'wired' | 'wireless' | 'nfc' | 'bluetooth' | 'network' | 'ready' | 'wifi_direct';
|
||||
/**
|
||||
* TRANSACTION_CONFIRMATION_DISPLAY
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#transaction-confirmation-display-types
|
||||
*/
|
||||
export type TransactionConfirmationDisplay = 'any' | 'privileged_software' | 'tee' | 'hardware' | 'remote';
|
||||
/**
|
||||
* https://fidoalliance.org/specs/fido-uaf-v1.2-ps-20201020/fido-uaf-protocol-v1.2-ps-20201020.html#version-interface
|
||||
*/
|
||||
export type Version = {
|
||||
major: number;
|
||||
minor: number;
|
||||
};
|
||||
/**
|
||||
* https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorGetInfoz
|
||||
*/
|
||||
export type AuthenticatorGetInfo = {
|
||||
versions: ('FIDO_2_0' | 'U2F_V2')[];
|
||||
extensions?: string[];
|
||||
aaguid: string;
|
||||
options?: {
|
||||
plat?: boolean;
|
||||
rk?: boolean;
|
||||
clientPin?: boolean;
|
||||
up?: boolean;
|
||||
uv?: boolean;
|
||||
};
|
||||
maxMsgSize?: number;
|
||||
pinProtocols?: number[];
|
||||
algorithms?: {
|
||||
type: 'public-key';
|
||||
alg: number;
|
||||
}[];
|
||||
};
|
||||
export {};
|
||||
//# sourceMappingURL=mdsTypes.d.ts.map
|
||||
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/mdsTypes.d.ts.map
generated
vendored
Normal file
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/mdsTypes.d.ts.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
18
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/mdsTypes.js
generated
vendored
Normal file
18
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/mdsTypes.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const AlgSign = [
|
||||
'secp256r1_ecdsa_sha256_raw',
|
||||
'secp256r1_ecdsa_sha256_der',
|
||||
'rsassa_pss_sha256_raw',
|
||||
'rsassa_pss_sha256_der',
|
||||
'secp256k1_ecdsa_sha256_raw',
|
||||
'secp256k1_ecdsa_sha256_der',
|
||||
'rsassa_pss_sha384_raw',
|
||||
'rsassa_pkcsv15_sha256_raw',
|
||||
'rsassa_pkcsv15_sha384_raw',
|
||||
'rsassa_pkcsv15_sha512_raw',
|
||||
'rsassa_pkcsv15_sha1_raw',
|
||||
'secp384r1_ecdsa_sha384_raw',
|
||||
'secp512r1_ecdsa_sha256_raw',
|
||||
'ed25519_eddsa_sha512_raw',
|
||||
];
|
||||
5
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/parseJWT.d.ts
generated
vendored
Normal file
5
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/parseJWT.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Process a JWT into Javascript-friendly data structures
|
||||
*/
|
||||
export declare function parseJWT<T1, T2>(jwt: string): [T1, T2, string];
|
||||
//# sourceMappingURL=parseJWT.d.ts.map
|
||||
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/parseJWT.d.ts.map
generated
vendored
Normal file
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/parseJWT.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"parseJWT.d.ts","sourceRoot":"","sources":["../../src/metadata/parseJWT.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,CAO9D"}
|
||||
15
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/parseJWT.js
generated
vendored
Normal file
15
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/parseJWT.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseJWT = parseJWT;
|
||||
const index_js_1 = require("../helpers/iso/index.js");
|
||||
/**
|
||||
* Process a JWT into Javascript-friendly data structures
|
||||
*/
|
||||
function parseJWT(jwt) {
|
||||
const parts = jwt.split('.');
|
||||
return [
|
||||
JSON.parse(index_js_1.isoBase64URL.toUTF8String(parts[0])),
|
||||
JSON.parse(index_js_1.isoBase64URL.toUTF8String(parts[1])),
|
||||
parts[2],
|
||||
];
|
||||
}
|
||||
30
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyAttestationWithMetadata.d.ts
generated
vendored
Normal file
30
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyAttestationWithMetadata.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { Base64URLString } from '../types/index.js';
|
||||
import type { AlgSign, MetadataStatement } from './mdsTypes.js';
|
||||
import { type COSEALG, type COSECRV, COSEKTY } from '../helpers/cose.js';
|
||||
/**
|
||||
* Match properties of the authenticator's attestation statement against expected values as
|
||||
* registered with the FIDO Alliance Metadata Service
|
||||
*/
|
||||
export declare function verifyAttestationWithMetadata({ statement, credentialPublicKey, x5c, attestationStatementAlg, }: {
|
||||
statement: MetadataStatement;
|
||||
credentialPublicKey: Uint8Array;
|
||||
x5c: Uint8Array[] | Base64URLString[];
|
||||
attestationStatementAlg?: number;
|
||||
}): Promise<boolean>;
|
||||
type COSEInfo = {
|
||||
kty: COSEKTY;
|
||||
alg: COSEALG;
|
||||
crv?: COSECRV;
|
||||
};
|
||||
/**
|
||||
* Convert ALG_SIGN values to COSE info
|
||||
*
|
||||
* Values pulled from `ALG_KEY_COSE` definitions in the FIDO Registry of Predefined Values
|
||||
*
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#authentication-algorithms
|
||||
*/
|
||||
export declare const algSignToCOSEInfoMap: {
|
||||
[key in AlgSign]: COSEInfo;
|
||||
};
|
||||
export {};
|
||||
//# sourceMappingURL=verifyAttestationWithMetadata.d.ts.map
|
||||
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyAttestationWithMetadata.d.ts.map
generated
vendored
Normal file
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyAttestationWithMetadata.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"verifyAttestationWithMetadata.d.ts","sourceRoot":"","sources":["../../src/metadata/verifyAttestationWithMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAIhE,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,OAAO,EAEZ,OAAO,EAER,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,SAAS,EACT,mBAAmB,EACnB,GAAG,EACH,uBAAuB,GACxB,EAAE;IACD,SAAS,EAAE,iBAAiB,CAAC;IAC7B,mBAAmB,EAAE,UAAU,CAAC;IAChC,GAAG,EAAE,UAAU,EAAE,GAAG,eAAe,EAAE,CAAC;IACtC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,GAAG,OAAO,CAAC,OAAO,CAAC,CAoJnB;AAED,KAAK,QAAQ,GAAG;IACd,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE;KAAG,GAAG,IAAI,OAAO,GAAG,QAAQ;CAe9D,CAAC"}
|
||||
163
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyAttestationWithMetadata.js
generated
vendored
Normal file
163
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyAttestationWithMetadata.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.algSignToCOSEInfoMap = void 0;
|
||||
exports.verifyAttestationWithMetadata = verifyAttestationWithMetadata;
|
||||
const convertCertBufferToPEM_js_1 = require("../helpers/convertCertBufferToPEM.js");
|
||||
const validateCertificatePath_js_1 = require("../helpers/validateCertificatePath.js");
|
||||
const decodeCredentialPublicKey_js_1 = require("../helpers/decodeCredentialPublicKey.js");
|
||||
const cose_js_1 = require("../helpers/cose.js");
|
||||
/**
|
||||
* Match properties of the authenticator's attestation statement against expected values as
|
||||
* registered with the FIDO Alliance Metadata Service
|
||||
*/
|
||||
async function verifyAttestationWithMetadata({ statement, credentialPublicKey, x5c, attestationStatementAlg, }) {
|
||||
const { authenticationAlgorithms, authenticatorGetInfo, attestationRootCertificates, } = statement;
|
||||
// Make sure the alg in the attestation statement matches one of the ones specified in metadata
|
||||
const keypairCOSEAlgs = new Set();
|
||||
authenticationAlgorithms.forEach((algSign) => {
|
||||
// Map algSign string to { kty, alg, crv }
|
||||
const algSignCOSEINFO = exports.algSignToCOSEInfoMap[algSign];
|
||||
// Keeping this statement here just in case MDS returns something unexpected
|
||||
if (algSignCOSEINFO) {
|
||||
keypairCOSEAlgs.add(algSignCOSEINFO);
|
||||
}
|
||||
});
|
||||
// Extract the public key's COSE info for comparison
|
||||
const decodedPublicKey = (0, decodeCredentialPublicKey_js_1.decodeCredentialPublicKey)(credentialPublicKey);
|
||||
const kty = decodedPublicKey.get(cose_js_1.COSEKEYS.kty);
|
||||
const alg = decodedPublicKey.get(cose_js_1.COSEKEYS.alg);
|
||||
if (!kty) {
|
||||
throw new Error('Credential public key was missing kty');
|
||||
}
|
||||
if (!alg) {
|
||||
throw new Error('Credential public key was missing alg');
|
||||
}
|
||||
if (!kty) {
|
||||
throw new Error('Credential public key was missing kty');
|
||||
}
|
||||
// Assume everything is a number because these values should be
|
||||
const publicKeyCOSEInfo = { kty, alg };
|
||||
if ((0, cose_js_1.isCOSEPublicKeyEC2)(decodedPublicKey)) {
|
||||
const crv = decodedPublicKey.get(cose_js_1.COSEKEYS.crv);
|
||||
publicKeyCOSEInfo.crv = crv;
|
||||
}
|
||||
/**
|
||||
* Attempt to match the credential public key's algorithm to one specified in the device's
|
||||
* metadata
|
||||
*/
|
||||
let foundMatch = false;
|
||||
for (const keypairAlg of keypairCOSEAlgs) {
|
||||
// Make sure algorithm and key type match
|
||||
if (keypairAlg.alg === publicKeyCOSEInfo.alg &&
|
||||
keypairAlg.kty === publicKeyCOSEInfo.kty) {
|
||||
// If not an RSA keypair then make sure curve numbers match too
|
||||
if ((keypairAlg.kty === cose_js_1.COSEKTY.EC2 || keypairAlg.kty === cose_js_1.COSEKTY.OKP) &&
|
||||
keypairAlg.crv === publicKeyCOSEInfo.crv) {
|
||||
foundMatch = true;
|
||||
}
|
||||
else {
|
||||
// We've matched an RSA public key's properties
|
||||
foundMatch = true;
|
||||
}
|
||||
}
|
||||
if (foundMatch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Make sure the public key is one of the allowed algorithms
|
||||
if (!foundMatch) {
|
||||
/**
|
||||
* Craft some useful error output from the MDS algorithms
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* [
|
||||
* 'rsassa_pss_sha256_raw' (COSE info: { kty: 3, alg: -37 }),
|
||||
* 'secp256k1_ecdsa_sha256_raw' (COSE info: { kty: 2, alg: -47, crv: 8 })
|
||||
* ]
|
||||
* ```
|
||||
*/
|
||||
const debugMDSAlgs = authenticationAlgorithms.map((algSign) => `'${algSign}' (COSE info: ${stringifyCOSEInfo(exports.algSignToCOSEInfoMap[algSign])})`);
|
||||
const strMDSAlgs = JSON.stringify(debugMDSAlgs, null, 2).replace(/"/g, '');
|
||||
/**
|
||||
* Construct useful error output about the public key
|
||||
*/
|
||||
const strPubKeyAlg = stringifyCOSEInfo(publicKeyCOSEInfo);
|
||||
throw new Error(`Public key parameters ${strPubKeyAlg} did not match any of the following metadata algorithms:\n${strMDSAlgs}`);
|
||||
}
|
||||
/**
|
||||
* Confirm the attestation statement's algorithm is one supported according to metadata
|
||||
*/
|
||||
if (attestationStatementAlg !== undefined &&
|
||||
authenticatorGetInfo?.algorithms !== undefined) {
|
||||
const getInfoAlgs = authenticatorGetInfo.algorithms.map((_alg) => _alg.alg);
|
||||
if (getInfoAlgs.indexOf(attestationStatementAlg) < 0) {
|
||||
throw new Error(`Attestation statement alg ${attestationStatementAlg} did not match one of ${getInfoAlgs}`);
|
||||
}
|
||||
}
|
||||
// Prepare to check the certificate chain
|
||||
const authenticatorCerts = x5c.map(convertCertBufferToPEM_js_1.convertCertBufferToPEM);
|
||||
const statementRootCerts = attestationRootCertificates.map(convertCertBufferToPEM_js_1.convertCertBufferToPEM);
|
||||
/**
|
||||
* If an authenticator returns exactly one certificate in its x5c, and that cert is found in the
|
||||
* metadata statement then the authenticator is "self-referencing". In this case we forego
|
||||
* certificate chain validation.
|
||||
*/
|
||||
let authenticatorIsSelfReferencing = false;
|
||||
if (authenticatorCerts.length === 1 &&
|
||||
statementRootCerts.indexOf(authenticatorCerts[0]) >= 0) {
|
||||
authenticatorIsSelfReferencing = true;
|
||||
}
|
||||
if (!authenticatorIsSelfReferencing) {
|
||||
try {
|
||||
await (0, validateCertificatePath_js_1.validateCertificatePath)(authenticatorCerts, statementRootCerts);
|
||||
}
|
||||
catch (err) {
|
||||
const _err = err;
|
||||
throw new Error(`Could not validate certificate path with any metadata root certificates: ${_err.message}`);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Convert ALG_SIGN values to COSE info
|
||||
*
|
||||
* Values pulled from `ALG_KEY_COSE` definitions in the FIDO Registry of Predefined Values
|
||||
*
|
||||
* https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-ps-20220523.html#authentication-algorithms
|
||||
*/
|
||||
exports.algSignToCOSEInfoMap = {
|
||||
secp256r1_ecdsa_sha256_raw: { kty: 2, alg: -7, crv: 1 },
|
||||
secp256r1_ecdsa_sha256_der: { kty: 2, alg: -7, crv: 1 },
|
||||
rsassa_pss_sha256_raw: { kty: 3, alg: -37 },
|
||||
rsassa_pss_sha256_der: { kty: 3, alg: -37 },
|
||||
secp256k1_ecdsa_sha256_raw: { kty: 2, alg: -47, crv: 8 },
|
||||
secp256k1_ecdsa_sha256_der: { kty: 2, alg: -47, crv: 8 },
|
||||
rsassa_pss_sha384_raw: { kty: 3, alg: -38 },
|
||||
rsassa_pkcsv15_sha256_raw: { kty: 3, alg: -257 },
|
||||
rsassa_pkcsv15_sha384_raw: { kty: 3, alg: -258 },
|
||||
rsassa_pkcsv15_sha512_raw: { kty: 3, alg: -259 },
|
||||
rsassa_pkcsv15_sha1_raw: { kty: 3, alg: -65535 },
|
||||
secp384r1_ecdsa_sha384_raw: { kty: 2, alg: -35, crv: 2 },
|
||||
secp512r1_ecdsa_sha256_raw: { kty: 2, alg: -36, crv: 3 },
|
||||
ed25519_eddsa_sha512_raw: { kty: 1, alg: -8, crv: 6 },
|
||||
};
|
||||
/**
|
||||
* A helper to format COSEInfo a little nicer than we can achieve with JSON.stringify()
|
||||
*
|
||||
* Input: `{ "kty": 3, "alg": -257 }`
|
||||
*
|
||||
* Output: `"{ kty: 3, alg: -257 }"`
|
||||
*/
|
||||
function stringifyCOSEInfo(info) {
|
||||
const { kty, alg, crv } = info;
|
||||
let toReturn = '';
|
||||
if (kty !== cose_js_1.COSEKTY.RSA) {
|
||||
toReturn = `{ kty: ${kty}, alg: ${alg}, crv: ${crv} }`;
|
||||
}
|
||||
else {
|
||||
toReturn = `{ kty: ${kty}, alg: ${alg} }`;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
11
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyJWT.d.ts
generated
vendored
Normal file
11
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyJWT.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Lightweight verification for FIDO MDS JWTs. Supports use of EC2 and RSA.
|
||||
*
|
||||
* If this ever needs to support more JWS algorithms, here's the list of them:
|
||||
*
|
||||
* https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1
|
||||
*
|
||||
* (Pulled from https://www.rfc-editor.org/rfc/rfc7515#section-4.1.1)
|
||||
*/
|
||||
export declare function verifyJWT(jwt: string, leafCert: Uint8Array): Promise<boolean>;
|
||||
//# sourceMappingURL=verifyJWT.d.ts.map
|
||||
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyJWT.d.ts.map
generated
vendored
Normal file
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyJWT.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"verifyJWT.d.ts","sourceRoot":"","sources":["../../src/metadata/verifyJWT.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CA0B7E"}
|
||||
40
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyJWT.js
generated
vendored
Normal file
40
api.hyungi.net/node_modules/@simplewebauthn/server/script/metadata/verifyJWT.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.verifyJWT = verifyJWT;
|
||||
const convertX509PublicKeyToCOSE_js_1 = require("../helpers/convertX509PublicKeyToCOSE.js");
|
||||
const index_js_1 = require("../helpers/iso/index.js");
|
||||
const cose_js_1 = require("../helpers/cose.js");
|
||||
const verifyEC2_js_1 = require("../helpers/iso/isoCrypto/verifyEC2.js");
|
||||
const verifyRSA_js_1 = require("../helpers/iso/isoCrypto/verifyRSA.js");
|
||||
/**
|
||||
* Lightweight verification for FIDO MDS JWTs. Supports use of EC2 and RSA.
|
||||
*
|
||||
* If this ever needs to support more JWS algorithms, here's the list of them:
|
||||
*
|
||||
* https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1
|
||||
*
|
||||
* (Pulled from https://www.rfc-editor.org/rfc/rfc7515#section-4.1.1)
|
||||
*/
|
||||
function verifyJWT(jwt, leafCert) {
|
||||
const [header, payload, signature] = jwt.split('.');
|
||||
const certCOSE = (0, convertX509PublicKeyToCOSE_js_1.convertX509PublicKeyToCOSE)(leafCert);
|
||||
const data = index_js_1.isoUint8Array.fromUTF8String(`${header}.${payload}`);
|
||||
const signatureBytes = index_js_1.isoBase64URL.toBuffer(signature);
|
||||
if ((0, cose_js_1.isCOSEPublicKeyEC2)(certCOSE)) {
|
||||
return (0, verifyEC2_js_1.verifyEC2)({
|
||||
data,
|
||||
signature: signatureBytes,
|
||||
cosePublicKey: certCOSE,
|
||||
shaHashOverride: cose_js_1.COSEALG.ES256,
|
||||
});
|
||||
}
|
||||
else if ((0, cose_js_1.isCOSEPublicKeyRSA)(certCOSE)) {
|
||||
return (0, verifyRSA_js_1.verifyRSA)({
|
||||
data,
|
||||
signature: signatureBytes,
|
||||
cosePublicKey: certCOSE,
|
||||
});
|
||||
}
|
||||
const kty = certCOSE.get(cose_js_1.COSEKEYS.kty);
|
||||
throw new Error(`JWT verification with public key of kty ${kty} is not supported by this method`);
|
||||
}
|
||||
Reference in New Issue
Block a user