summaryrefslogtreecommitdiffhomepage
path: root/packages/server/src
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2022-11-19 22:22:33 -0800
committerMatthew Miller <matthew@millerti.me>2022-11-19 22:22:33 -0800
commit52e1abca516295c2f0cf34353ed5c5c01d77d3c7 (patch)
tree89a40a80cbdc3e9810b184a9b7d3333df50c856e /packages/server/src
parenta7f2514c381e5f57f27dfaf887a633045747eb4f (diff)
Streamline calls to verifySignature()
Diffstat (limited to 'packages/server/src')
-rw-r--r--packages/server/src/helpers/verifySignature.ts162
-rw-r--r--packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts3
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts3
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationPacked.ts4
4 files changed, 12 insertions, 160 deletions
diff --git a/packages/server/src/helpers/verifySignature.ts b/packages/server/src/helpers/verifySignature.ts
index 19cbac1..ff4e73b 100644
--- a/packages/server/src/helpers/verifySignature.ts
+++ b/packages/server/src/helpers/verifySignature.ts
@@ -1,13 +1,7 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-import { verify as ed25519Verify } from '@noble/ed25519';
-import { AsnParser } from '@peculiar/asn1-schema';
-import { Certificate } from '@peculiar/asn1-x509';
-import { ECParameters, id_ecPublicKey, id_secp256r1 } from '@peculiar/asn1-ecc';
-import { RSAPublicKey } from '@peculiar/asn1-rsa';
-
-import { COSEALG, COSECRV, COSEKEYS, COSEKTY, COSEPublicKey, COSEPublicKeyEC2, COSEPublicKeyRSA, isCOSEAlg, isCOSEPublicKeyOKP } from './convertCOSEtoPKCS';
+import { COSEALG, COSEPublicKey } from './cose';
import { isoCrypto } from './iso';
import { decodeCredentialPublicKey } from './decodeCredentialPublicKey';
+import { convertX509PublicKeyToCOSE } from './convertX509PublicKeyToCOSE';
/**
* Verify an authenticator's signature
@@ -17,9 +11,9 @@ export async function verifySignature(opts: {
data: Uint8Array;
credentialPublicKey?: Uint8Array;
leafCertificate?: Uint8Array;
- rsaHashAlgorithm?: string;
+ attestationHashAlgorithm?: COSEALG;
}): Promise<boolean> {
- const { signature, data, credentialPublicKey, leafCertificate, rsaHashAlgorithm } = opts;
+ const { signature, data, credentialPublicKey, leafCertificate, attestationHashAlgorithm } = opts;
if (!leafCertificate && !credentialPublicKey) {
throw new Error('Must declare either "leafCert" or "credentialPublicKey"');
@@ -29,156 +23,18 @@ export async function verifySignature(opts: {
throw new Error('Must not declare both "leafCert" and "credentialPublicKey"');
}
- let subtlePublicKey: CryptoKey;
- let kty: COSEKTY;
- let alg: COSEALG;
+ let cosePublicKey: COSEPublicKey = new Map();
if (credentialPublicKey) {
- const cosePublicKey = decodeCredentialPublicKey(credentialPublicKey);
-
- const _kty = cosePublicKey.get(COSEKEYS.kty);
- const _alg = cosePublicKey.get(COSEKEYS.alg);
-
- if (!_kty) {
- throw new Error('Public key was missing kty');
- }
-
- if (!_alg) {
- throw new Error('Public key was missing alg');
- }
-
- if (!isCOSEAlg(_alg)) {
- throw new Error(`Public key contained invalid alg ${_alg}`);
- }
-
- // Verify Ed25519 slightly differently
- if (isCOSEPublicKeyOKP(cosePublicKey)) {
- const x = cosePublicKey.get(COSEKEYS.x);
-
- if (!x) {
- throw new Error('Public key was missing x (OKP)');
- }
-
- return ed25519Verify(signature, data, x);
- }
-
- // Assume we're handling COSEKTY.EC2 or COSEKTY.RSA key from here on
- subtlePublicKey = await isoCrypto.importKey(cosePublicKey as COSEPublicKeyEC2 | COSEPublicKeyRSA);
- kty = _kty as COSEKTY;
- alg = _alg;
+ cosePublicKey = decodeCredentialPublicKey(credentialPublicKey);
} else if (leafCertificate) {
- /**
- * Time to extract the public key from an X.509 leaf certificate
- */
- const x509 = AsnParser.parse(leafCertificate, Certificate);
-
- const { tbsCertificate } = x509;
- const {
- subjectPublicKeyInfo,
- signature: _tbsSignature,
- } = tbsCertificate;
-
- // console.log(tbsCertificate);
-
- const signatureAlgorithm = _tbsSignature.algorithm;
- const publicKeyAlgorithmID = subjectPublicKeyInfo.algorithm.algorithm;
-
- if (publicKeyAlgorithmID === id_ecPublicKey) {
- /**
- * EC2 Public Key
- */
- kty = COSEKTY.EC2;
-
- if (!subjectPublicKeyInfo.algorithm.parameters) {
- throw new Error('Leaf cert public key missing parameters (EC2)');
- }
-
- const ecParameters = AsnParser.parse(new Uint8Array(subjectPublicKeyInfo.algorithm.parameters), ECParameters);
-
- let crv = -999;
- if (ecParameters.namedCurve === id_secp256r1) {
- crv = COSECRV.P256;
- } else {
- throw new Error(
- `Leaf cert public key contained unexpected namedCurve ${ecParameters.namedCurve} (EC2)`,
- );
- }
-
- const subjectPublicKey = new Uint8Array(subjectPublicKeyInfo.subjectPublicKey)
-
- let x: Uint8Array;
- let y: Uint8Array;
- if (subjectPublicKey[0] === 0x04) {
- // Public key is in "uncompressed form", so we can split the remaining bytes in half
- let pointer = 1;
- const halfLength = (subjectPublicKey.length - 1) / 2;
- x = subjectPublicKey.slice(pointer, pointer += halfLength);
- y = subjectPublicKey.slice(pointer);
- } else {
- throw new Error('TODO: Figure out how to handle public keys in "compressed form"');
- }
-
- const coseEC2PubKey: COSEPublicKeyEC2 = new Map();
- coseEC2PubKey.set(COSEKEYS.kty, COSEKTY.EC2);
- coseEC2PubKey.set(COSEKEYS.crv, crv);
- coseEC2PubKey.set(COSEKEYS.x, x);
- coseEC2PubKey.set(COSEKEYS.y, y);
-
- subtlePublicKey = await isoCrypto.importKey(coseEC2PubKey);
- alg = -7;
- } else if (publicKeyAlgorithmID === '1.2.840.113549.1.1.1') {
- /**
- * RSA public key
- */
- kty = COSEKTY.RSA;
- const rsaPublicKey = AsnParser.parse(subjectPublicKeyInfo.subjectPublicKey, RSAPublicKey);
-
- let _alg: COSEALG;
- if (signatureAlgorithm === '1.2.840.113549.1.1.11') {
- _alg = -257; // RS256
- } else if (signatureAlgorithm === '1.2.840.113549.1.1.12') {
- _alg = -258; // RS384
- } else if (signatureAlgorithm === '1.2.840.113549.1.1.13') {
- _alg = -259; // RS512
- } else {
- throw new Error(
- `Leaf cert contained unexpected signature algorithm ${signatureAlgorithm} (RSA)`,
- );
- }
-
- const coseRSAPubKey: COSEPublicKeyRSA = new Map();
- coseRSAPubKey.set(COSEKEYS.kty, COSEKTY.RSA);
- coseRSAPubKey.set(COSEKEYS.alg, _alg);
- coseRSAPubKey.set(COSEKEYS.n, new Uint8Array(rsaPublicKey.modulus));
- coseRSAPubKey.set(COSEKEYS.e, new Uint8Array(rsaPublicKey.publicExponent));
-
- subtlePublicKey = await isoCrypto.importKey(coseRSAPubKey, rsaHashAlgorithm);
- alg = _alg;
- } else {
- throw new Error(`Unexpected leaf cert public key algorithm ${publicKeyAlgorithmID}`);
- }
- } else {
- throw new Error(
- 'How did we get here? We were supposed to make sure we were only dealing with one of two possible sets of method arguments!!',
- );
- }
-
- if (
- // @ts-ignore 2454
- typeof subtlePublicKey === 'undefined'
- // @ts-ignore 2454
- || typeof kty === 'undefined'
- // @ts-ignore 2454
- || typeof alg === 'undefined'
- ) {
- throw new Error('You must import a public key, and determine kty and alg before proceeding');
+ cosePublicKey = convertX509PublicKeyToCOSE(leafCertificate);
}
return isoCrypto.verify({
- publicKey: subtlePublicKey,
- coseKty: kty,
- coseAlg: alg,
+ cosePublicKey,
signature,
data,
+ shaHashOverride: attestationHashAlgorithm,
});
}
diff --git a/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts
index 18c9abd..5a10322 100644
--- a/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts
+++ b/packages/server/src/registration/verifications/tpm/verifyAttestationTPM.ts
@@ -174,7 +174,6 @@ export async function verifyAttestationTPM(options: AttestationFormatVerifierOpt
const attToBeSigned = isoUint8Array.concat([authData, clientDataHash]);
// Hash attToBeSigned using the algorithm specified in attStmt.alg to create attToBeSignedHash
- const hashAlg: string = coseAlgSHAHashMap[alg];
const attToBeSignedHash = await toHash(attToBeSigned, alg);
// Check that certInfo.extraData is equals to attToBeSignedHash.
@@ -305,7 +304,7 @@ export async function verifyAttestationTPM(options: AttestationFormatVerifierOpt
signature: sig,
data: certInfo,
leafCertificate: x5c[0],
- rsaHashAlgorithm: hashAlg
+ attestationHashAlgorithm: alg,
});
}
diff --git a/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
index cceedb8..1f3eb83 100644
--- a/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
@@ -107,12 +107,11 @@ export async function verifyAttestationAndroidKey(
}
const signatureBase = isoUint8Array.concat([authData, clientDataHash]);
- const hashAlg = coseAlgSHAHashMap[alg];
return verifySignature({
signature: sig,
data: signatureBase,
leafCertificate: x5c[0],
- rsaHashAlgorithm: hashAlg
+ attestationHashAlgorithm: alg,
});
}
diff --git a/packages/server/src/registration/verifications/verifyAttestationPacked.ts b/packages/server/src/registration/verifications/verifyAttestationPacked.ts
index a03f22b..0fc84b8 100644
--- a/packages/server/src/registration/verifications/verifyAttestationPacked.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationPacked.ts
@@ -118,13 +118,11 @@ export async function verifyAttestationPacked(
leafCertificate: x5c[0],
});
} else {
- const hashAlg: string = coseAlgSHAHashMap[alg];
-
verified = await verifySignature({
signature: sig,
data: signatureBase,
credentialPublicKey,
- rsaHashAlgorithm: hashAlg
+ attestationHashAlgorithm: alg
});
}