From 5241de05730af38806dbe69159086ed01b793feb Mon Sep 17 00:00:00 2001 From: Matthieu Sieben Date: Fri, 12 Apr 2024 15:22:57 +0200 Subject: [PATCH] fix(jwk-webcrypto): prefer jwk algorithms that yield smaller signatures --- packages/jwk-webcrypto/src/util.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/jwk-webcrypto/src/util.ts b/packages/jwk-webcrypto/src/util.ts index fc7c3a3f900..9bd35b7c85f 100644 --- a/packages/jwk-webcrypto/src/util.ts +++ b/packages/jwk-webcrypto/src/util.ts @@ -126,7 +126,8 @@ export async function generateKeypair( extractable = false, ): Promise { const errors: unknown[] = [] - for (const alg of algs) { + const algsSorted = Array.from(algs).sort(compareAlgos) + for (const alg of algsSorted) { try { return await crypto.subtle.generateKey( toSubtleAlgorithm(alg), @@ -140,3 +141,29 @@ export async function generateKeypair( throw new AggregateError(errors, 'Failed to generate keypair') } + +/** + * 256K > ES (256 > 384 > 512) > PS (256 > 384 > 512) > RS (256 > 384 > 512) > other (in original order) + */ +function compareAlgos(a: string, b: string): number { + if (a === 'ES256K') return -1 + if (b === 'ES256K') return 1 + + for (const prefix of ['ES', 'PS', 'RS']) { + if (a.startsWith(prefix)) { + if (b.startsWith(prefix)) { + const aLen = parseInt(a.slice(2, 5)) + const bLen = parseInt(b.slice(2, 5)) + + // Prefer shorter key lengths + return aLen - bLen + } + return -1 + } else if (b.startsWith(prefix)) { + return 1 + } + } + + // Don't know how to compare, keep original order + return 0 +}