Skip to content

Commit

Permalink
fix(CF Workers): improve miniflare compat with different Node.js vers…
Browse files Browse the repository at this point in the history
…ions, get ready for future non-proprietary support

closes #446
closes #495
closes #497
  • Loading branch information
panva committed Feb 7, 2023
1 parent 2d783e0 commit 3406b9f
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 48 deletions.
8 changes: 4 additions & 4 deletions src/lib/crypto_key.ts
Expand Up @@ -71,12 +71,12 @@ export function checkSigCryptoKey(key: CryptoKey, alg: string, ...usages: KeyUsa
if (actual !== expected) throw unusable(`SHA-${expected}`, 'algorithm.hash')
break
}
case isCloudflareWorkers() && 'EdDSA': {
if (!isAlgorithm(key.algorithm, 'NODE-ED25519')) throw unusable('NODE-ED25519')
break
}
case 'EdDSA': {
if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') {
if (isCloudflareWorkers()) {
if (isAlgorithm(key.algorithm, 'NODE-ED25519')) break
throw unusable('Ed25519, Ed448, or NODE-ED25519')
}
throw unusable('Ed25519 or Ed448')
}
break
Expand Down
38 changes: 25 additions & 13 deletions src/runtime/browser/asn1.ts
Expand Up @@ -135,12 +135,6 @@ const genericImport = async (
keyUsages = isPublic ? [] : ['deriveBits']
break
}
case isCloudflareWorkers() && 'EdDSA': {
const namedCurve = getNamedCurve(keyData).toUpperCase()
algorithm = { name: `NODE-${namedCurve}`, namedCurve: `NODE-${namedCurve}` }
keyUsages = isPublic ? ['verify'] : ['sign']
break
}
case 'EdDSA':
algorithm = { name: getNamedCurve(keyData) }
keyUsages = isPublic ? ['verify'] : ['sign']
Expand All @@ -149,13 +143,31 @@ const genericImport = async (
throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value')
}

return crypto.subtle.importKey(
keyFormat,
keyData,
algorithm,
options?.extractable ?? false,
keyUsages,
)
try {
return await crypto.subtle.importKey(
keyFormat,
keyData,
algorithm,
options?.extractable ?? false,
keyUsages,
)
} catch (err) {
if (
algorithm.name === 'Ed25519' &&
(<Error>err)?.name === 'NotSupportedError' &&
isCloudflareWorkers()
) {
algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }
return await crypto.subtle.importKey(
keyFormat,
keyData,
algorithm,
options?.extractable ?? false,
keyUsages,
)
}
throw err
}
}

export const fromPKCS8: PEMImportFunction = (pem, alg, options?) => {
Expand Down
31 changes: 17 additions & 14 deletions src/runtime/browser/generate.ts
Expand Up @@ -109,17 +109,6 @@ export async function generateKeyPair(alg: string, options?: GenerateKeyPairOpti
algorithm = { name: 'ECDSA', namedCurve: 'P-521' }
keyUsages = ['sign', 'verify']
break
case isCloudflareWorkers() && 'EdDSA':
switch (options?.crv) {
case undefined:
case 'Ed25519':
algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }
keyUsages = ['sign', 'verify']
break
default:
throw new JOSENotSupported('Invalid or unsupported crv option provided')
}
break
case 'EdDSA':
keyUsages = ['sign', 'verify']
const crv = options?.crv ?? 'Ed25519'
Expand Down Expand Up @@ -160,7 +149,21 @@ export async function generateKeyPair(alg: string, options?: GenerateKeyPairOpti
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')
}

return <Promise<{ publicKey: CryptoKey; privateKey: CryptoKey }>>(
crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages)
)
try {
return <{ publicKey: CryptoKey; privateKey: CryptoKey }>(
await crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages)
)
} catch (err) {
if (
algorithm.name === 'Ed25519' &&
(<Error>err)?.name === 'NotSupportedError' &&
isCloudflareWorkers()
) {
algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }
return <{ publicKey: CryptoKey; privateKey: CryptoKey }>(
await crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages)
)
}
throw err
}
}
27 changes: 13 additions & 14 deletions src/runtime/browser/jwk_to_key.ts
Expand Up @@ -106,19 +106,6 @@ function subtleMapping(jwk: JWK): {
}
break
}
case isCloudflareWorkers() && 'OKP':
if (jwk.alg !== 'EdDSA') {
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')
}
switch (jwk.crv) {
case 'Ed25519':
algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }
keyUsages = jwk.d ? ['sign'] : ['verify']
break
default:
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')
}
break
case 'OKP': {
switch (jwk.alg) {
case 'EdDSA':
Expand Down Expand Up @@ -159,6 +146,18 @@ const parse: JWKImportFunction = async (jwk: JWK): Promise<CryptoKey> => {
const keyData: JWK = { ...jwk }
delete keyData.alg
delete keyData.use
return crypto.subtle.importKey('jwk', keyData, ...rest)
try {
return await crypto.subtle.importKey('jwk', keyData, ...rest)
} catch (err) {
if (
algorithm.name === 'Ed25519' &&
(<Error>err)?.name === 'NotSupportedError' &&
isCloudflareWorkers()
) {
rest[0] = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }
return await crypto.subtle.importKey('jwk', keyData, ...rest)
}
throw err
}
}
export default parse
7 changes: 4 additions & 3 deletions src/runtime/browser/subtle_dsa.ts
Expand Up @@ -21,10 +21,11 @@ export default function subtleDsa(alg: string, algorithm: KeyAlgorithm | EcKeyAl
case 'ES384':
case 'ES512':
return { hash, name: 'ECDSA', namedCurve: (<EcKeyAlgorithm>algorithm).namedCurve }
case isCloudflareWorkers() && 'EdDSA':
const { namedCurve } = <EcKeyAlgorithm>algorithm
return <EcKeyAlgorithm>{ name: namedCurve, namedCurve }
case 'EdDSA':
if (isCloudflareWorkers() && algorithm.name === 'NODE-ED25519') {
return { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }
}

return { name: algorithm.name }
default:
throw new JOSENotSupported(
Expand Down

0 comments on commit 3406b9f

Please sign in to comment.