summaryrefslogtreecommitdiffhomepage
path: root/packages/server/src
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2022-11-06 09:06:02 -0800
committerMatthew Miller <matthew@millerti.me>2022-11-06 09:06:02 -0800
commitdc523d81bff8793ee4dc36b1273e08941fc7abaa (patch)
treed44b7e3ef48f79e3c532f313c4139cf6fa500645 /packages/server/src
parent6ca32c507f99c456c999234c546f8712f88e0ee5 (diff)
Switch to uint8array helpers
Diffstat (limited to 'packages/server/src')
-rw-r--r--packages/server/src/authentication/generateAuthenticationOptions.ts9
-rw-r--r--packages/server/src/authentication/verifyAuthenticationResponse.ts5
-rw-r--r--packages/server/src/helpers/convertAAGUIDToString.ts4
-rw-r--r--packages/server/src/helpers/convertCOSEtoPKCS.ts7
-rw-r--r--packages/server/src/helpers/convertCertBufferToPEM.ts3
-rw-r--r--packages/server/src/registration/generateRegistrationOptions.ts9
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts5
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.ts3
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationApple.ts5
-rw-r--r--packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts5
-rw-r--r--packages/server/src/registration/verifyRegistrationResponse.ts5
11 files changed, 44 insertions, 16 deletions
diff --git a/packages/server/src/authentication/generateAuthenticationOptions.ts b/packages/server/src/authentication/generateAuthenticationOptions.ts
index 1eab513..4c841d9 100644
--- a/packages/server/src/authentication/generateAuthenticationOptions.ts
+++ b/packages/server/src/authentication/generateAuthenticationOptions.ts
@@ -5,6 +5,7 @@ import type {
UserVerificationRequirement,
} from '@simplewebauthn/typescript-types';
import base64url from '../helpers/base64url'
+import uint8Array from '../helpers/uint8Array';
import { generateChallenge } from '../helpers/generateChallenge';
@@ -42,6 +43,14 @@ export function generateAuthenticationOptions(
rpID,
} = options;
+ /**
+ * Preserve ability to specify `string` values for challenges
+ */
+ let _challenge = challenge;
+ if (typeof _challenge === 'string') {
+ _challenge = uint8Array.fromString(_challenge);
+ }
+
return {
challenge: base64url.fromBuffer(_challenge),
allowCredentials: allowCredentials?.map(cred => ({
diff --git a/packages/server/src/authentication/verifyAuthenticationResponse.ts b/packages/server/src/authentication/verifyAuthenticationResponse.ts
index 7ae002e..9200758 100644
--- a/packages/server/src/authentication/verifyAuthenticationResponse.ts
+++ b/packages/server/src/authentication/verifyAuthenticationResponse.ts
@@ -12,6 +12,7 @@ import { parseAuthenticatorData } from '../helpers/parseAuthenticatorData';
import { isBase64URLString } from '../helpers/isBase64URLString';
import { parseBackupFlags } from '../helpers/parseBackupFlags';
import { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions';
+import uint8Array from '../helpers/uint8Array';
import base64url from '../helpers/base64url';
export type VerifyAuthenticationResponseOpts = {
@@ -149,14 +150,14 @@ export async function verifyAuthenticationResponse(
// Make sure the response's RP ID is ours
if (typeof expectedRPID === 'string') {
const expectedRPIDHash = toHash(Buffer.from(expectedRPID, 'ascii'));
- if (!rpIdHash.equals(expectedRPIDHash)) {
+ if (!uint8Array.areEqual(rpIdHash, expectedRPIDHash)) {
throw new Error(`Unexpected RP ID hash`);
}
} else {
// Go through each expected RP ID and try to find one that matches
const foundMatch = expectedRPID.some(expected => {
const expectedRPIDHash = toHash(Buffer.from(expected, 'ascii'));
- return rpIdHash.equals(expectedRPIDHash);
+ return uint8Array.areEqual(rpIdHash, expectedRPIDHash);
});
if (!foundMatch) {
diff --git a/packages/server/src/helpers/convertAAGUIDToString.ts b/packages/server/src/helpers/convertAAGUIDToString.ts
index 3dc837c..80dc63c 100644
--- a/packages/server/src/helpers/convertAAGUIDToString.ts
+++ b/packages/server/src/helpers/convertAAGUIDToString.ts
@@ -1,9 +1,11 @@
+import uint8Array from './uint8Array';
+
/**
* Convert the aaguid buffer in authData into a UUID string
*/
export function convertAAGUIDToString(aaguid: Uint8Array): string {
// Raw Hex: adce000235bcc60a648b0b25f1f05503
- const hex = aaguid.toString('hex');
+ const hex = uint8Array.toHex(aaguid);
const segments: string[] = [
hex.slice(0, 8), // 8
diff --git a/packages/server/src/helpers/convertCOSEtoPKCS.ts b/packages/server/src/helpers/convertCOSEtoPKCS.ts
index 158fb36..0ee6a97 100644
--- a/packages/server/src/helpers/convertCOSEtoPKCS.ts
+++ b/packages/server/src/helpers/convertCOSEtoPKCS.ts
@@ -1,5 +1,6 @@
import { COSEAlgorithmIdentifier } from '@simplewebauthn/typescript-types';
import { decodeCborFirst } from './decodeCbor';
+import uint8Array from './uint8array';
/**
* Takes COSE-encoded public key and converts it to PKCS key
@@ -7,19 +8,19 @@ import { decodeCborFirst } from './decodeCbor';
export function convertCOSEtoPKCS(cosePublicKey: Uint8Array): Uint8Array {
const struct: COSEPublicKey = decodeCborFirst(cosePublicKey);
- const tag = Buffer.from([0x04]);
const x = struct.get(COSEKEYS.x);
const y = struct.get(COSEKEYS.y);
+ const tag = Uint8Array.from([0x04]);
if (!x) {
throw new Error('COSE public key was missing x');
}
if (y) {
- return Buffer.concat([tag, x as Buffer, y as Buffer]);
+ return uint8Array.concat([tag, x as Uint8Array, y as Uint8Array]);
}
- return Buffer.concat([tag, x as Buffer]);
+ return uint8Array.concat([tag, x as Uint8Array]);
}
export type COSEPublicKey = Map<COSEAlgorithmIdentifier, number | Buffer>;
diff --git a/packages/server/src/helpers/convertCertBufferToPEM.ts b/packages/server/src/helpers/convertCertBufferToPEM.ts
index 5339282..faf9001 100644
--- a/packages/server/src/helpers/convertCertBufferToPEM.ts
+++ b/packages/server/src/helpers/convertCertBufferToPEM.ts
@@ -1,5 +1,6 @@
import type { Base64URLString } from '@simplewebauthn/typescript-types';
+import uint8Array from './uint8Array';
import base64url from './base64url';
/**
@@ -14,7 +15,7 @@ export function convertCertBufferToPEM(certBuffer: Uint8Array | Base64URLString)
if (typeof certBuffer === 'string') {
b64cert = base64url.toBase64(certBuffer);
} else {
- b64cert = certBuffer.toString('base64');
+ b64cert = uint8Array.toBase64(certBuffer);
}
let PEMKey = '';
diff --git a/packages/server/src/registration/generateRegistrationOptions.ts b/packages/server/src/registration/generateRegistrationOptions.ts
index 12138b0..6273246 100644
--- a/packages/server/src/registration/generateRegistrationOptions.ts
+++ b/packages/server/src/registration/generateRegistrationOptions.ts
@@ -10,6 +10,7 @@ import type {
import { generateChallenge } from '../helpers/generateChallenge';
import base64url from '../helpers/base64url';
+import uint8Array from '../helpers/uint8Array';
export type GenerateRegistrationOptionsOpts = {
rpName: string;
@@ -151,6 +152,14 @@ export function generateRegistrationOptions(
authenticatorSelection.requireResidentKey = authenticatorSelection.residentKey === 'required';
}
+ /**
+ * Preserve ability to specify `string` values for challenges
+ */
+ let _challenge = challenge;
+ if (typeof _challenge === 'string') {
+ _challenge = uint8Array.fromString(_challenge);
+ }
+
return {
challenge: base64url.fromBuffer(_challenge),
rp: {
diff --git a/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
index 55a0612..6c89df8 100644
--- a/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationAndroidKey.ts
@@ -8,6 +8,7 @@ import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM';
import { validateCertificatePath } from '../../helpers/validateCertificatePath';
import { verifySignature } from '../../helpers/verifySignature';
import { COSEALGHASH, convertCOSEtoPKCS } from '../../helpers/convertCOSEtoPKCS';
+import uint8Array from '../../helpers/uint8Array';
import { MetadataService } from '../../services/metadataService';
import { verifyAttestationWithMetadata } from '../../metadata/verifyAttestationWithMetadata';
@@ -36,14 +37,14 @@ export async function verifyAttestationAndroidKey(
// Check that credentialPublicKey matches the public key in the attestation certificate
// Find the public cert in the certificate as PKCS
const parsedCert = AsnParser.parse(x5c[0], Certificate);
- const parsedCertPubKey = Buffer.from(
+ const parsedCertPubKey = new Uint8Array(
parsedCert.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey,
);
// Convert the credentialPublicKey to PKCS
const credPubKeyPKCS = convertCOSEtoPKCS(credentialPublicKey);
- if (!credPubKeyPKCS.equals(parsedCertPubKey)) {
+ if (!uint8Array.areEqual(credPubKeyPKCS, parsedCertPubKey)) {
throw new Error('Credential public key does not equal leaf cert public key (AndroidKey)');
}
diff --git a/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.ts b/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.ts
index 4c1e685..65e5c00 100644
--- a/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationAndroidSafetyNet.ts
@@ -7,6 +7,7 @@ import { verifySignature } from '../../helpers/verifySignature';
import { getCertificateInfo } from '../../helpers/getCertificateInfo';
import { validateCertificatePath } from '../../helpers/validateCertificatePath';
import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM';
+import uint8Array from '../../helpers/uint8Array';
import { MetadataService } from '../../services/metadataService';
import { verifyAttestationWithMetadata } from '../../metadata/verifyAttestationWithMetadata';
@@ -65,7 +66,7 @@ export async function verifyAttestationAndroidSafetyNet(
const nonceBase = Buffer.concat([authData, clientDataHash]);
const nonceBuffer = toHash(nonceBase);
- const expectedNonce = nonceBuffer.toString('base64');
+ const expectedNonce = uint8Array.toBase64(nonceBuffer);
if (nonce !== expectedNonce) {
throw new Error('Could not verify payload nonce (SafetyNet)');
diff --git a/packages/server/src/registration/verifications/verifyAttestationApple.ts b/packages/server/src/registration/verifications/verifyAttestationApple.ts
index e0c7890..fc12f9d 100644
--- a/packages/server/src/registration/verifications/verifyAttestationApple.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationApple.ts
@@ -7,6 +7,7 @@ import { validateCertificatePath } from '../../helpers/validateCertificatePath';
import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM';
import { toHash } from '../../helpers/toHash';
import { convertCOSEtoPKCS } from '../../helpers/convertCOSEtoPKCS';
+import uint8Array from '../../helpers/uint8Array';
export async function verifyAttestationApple(
options: AttestationFormatVerifierOpts,
@@ -55,7 +56,7 @@ export async function verifyAttestationApple(
*/
const extNonce = Buffer.from(extCertNonce.extnValue.buffer).slice(6);
- if (!nonce.equals(extNonce)) {
+ if (!uint8Array.areEqual(nonce, extNonce)) {
throw new Error(`credCert nonce was not expected value (Apple)`);
}
@@ -65,7 +66,7 @@ export async function verifyAttestationApple(
const credPubKeyPKCS = convertCOSEtoPKCS(credentialPublicKey);
const credCertSubjectPublicKey = Buffer.from(subjectPublicKeyInfo.subjectPublicKey);
- if (!credPubKeyPKCS.equals(credCertSubjectPublicKey)) {
+ if (!uint8Array.areEqual(credPubKeyPKCS, credCertSubjectPublicKey)) {
throw new Error('Credential public key does not equal credCert public key (Apple)');
}
diff --git a/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts b/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts
index 3c79b9e..e73c22f 100644
--- a/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts
+++ b/packages/server/src/registration/verifications/verifyAttestationFIDOU2F.ts
@@ -4,6 +4,7 @@ import { convertCOSEtoPKCS } from '../../helpers/convertCOSEtoPKCS';
import { convertCertBufferToPEM } from '../../helpers/convertCertBufferToPEM';
import { validateCertificatePath } from '../../helpers/validateCertificatePath';
import { verifySignature } from '../../helpers/verifySignature';
+import uint8Array from '../../helpers/uint8Array';
/**
* Verify an attestation response with fmt 'fido-u2f'
@@ -17,7 +18,7 @@ export async function verifyAttestationFIDOU2F(
rpIdHash,
credentialID,
credentialPublicKey,
- aaguid = '',
+ aaguid,
rootCertificates,
} = options;
@@ -43,7 +44,7 @@ export async function verifyAttestationFIDOU2F(
}
// FIDO spec says that aaguid _must_ equal 0x00 here to be legit
- const aaguidToHex = Number.parseInt(aaguid.toString('hex'), 16);
+ const aaguidToHex = Number.parseInt(uint8Array.toHex(aaguid), 16);
if (aaguidToHex !== 0x00) {
throw new Error(`AAGUID "${aaguidToHex}" was not expected value`);
}
diff --git a/packages/server/src/registration/verifyRegistrationResponse.ts b/packages/server/src/registration/verifyRegistrationResponse.ts
index efe7531..60140a4 100644
--- a/packages/server/src/registration/verifyRegistrationResponse.ts
+++ b/packages/server/src/registration/verifyRegistrationResponse.ts
@@ -18,6 +18,7 @@ import { decodeCredentialPublicKey } from '../helpers/decodeCredentialPublicKey'
import { COSEKEYS } from '../helpers/convertCOSEtoPKCS';
import { convertAAGUIDToString } from '../helpers/convertAAGUIDToString';
import { parseBackupFlags } from '../helpers/parseBackupFlags';
+import uint8Array from '../helpers/uint8Array';
import { SettingsService } from '../services/settingsService';
import { supportedCOSEAlgorithmIdentifiers } from './generateRegistrationOptions';
@@ -141,14 +142,14 @@ export async function verifyRegistrationResponse(
if (expectedRPID) {
if (typeof expectedRPID === 'string') {
const expectedRPIDHash = toHash(Buffer.from(expectedRPID, 'ascii'));
- if (!rpIdHash.equals(expectedRPIDHash)) {
+ if (!uint8Array.areEqual(rpIdHash, expectedRPIDHash)) {
throw new Error(`Unexpected RP ID hash`);
}
} else {
// Go through each expected RP ID and try to find one that matches
const foundMatch = expectedRPID.some(expected => {
const expectedRPIDHash = toHash(Buffer.from(expected, 'ascii'));
- return rpIdHash.equals(expectedRPIDHash);
+ return uint8Array.areEqual(rpIdHash, expectedRPIDHash);
});
if (!foundMatch) {