Skip to content

Commit

Permalink
refactor: catch type errors when decoding various base64url strings
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Sep 2, 2023
1 parent 935e920 commit 9024e87
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 14 deletions.
34 changes: 29 additions & 5 deletions src/jwe/flattened/decrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,11 @@ export async function flattenedDecrypt(

let encryptedKey!: Uint8Array
if (jwe.encrypted_key !== undefined) {
encryptedKey = base64url(jwe.encrypted_key!)
try {
encryptedKey = base64url(jwe.encrypted_key!)
} catch {
throw new JWEInvalid('Failed to base64url decode the encrypted_key')
}
}

let resolvedKey = false
Expand All @@ -205,8 +209,18 @@ export async function flattenedDecrypt(
cek = generateCek(enc)
}

const iv = base64url(jwe.iv)
const tag = base64url(jwe.tag)
let iv: Uint8Array
let tag: Uint8Array
try {
iv = base64url(jwe.iv)
} catch {
throw new JWEInvalid('Failed to base64url decode the iv')
}
try {
tag = base64url(jwe.tag)
} catch {
throw new JWEInvalid('Failed to base64url decode the tag')
}

const protectedHeader: Uint8Array = encoder.encode(jwe.protected ?? '')
let additionalData: Uint8Array
Expand All @@ -217,7 +231,13 @@ export async function flattenedDecrypt(
additionalData = protectedHeader
}

let plaintext = await decrypt(enc, cek, base64url(jwe.ciphertext), iv, tag, additionalData)
let ciphertext: Uint8Array
try {
ciphertext = base64url(jwe.ciphertext)
} catch {
throw new JWEInvalid('Failed to base64url decode the ciphertext')
}
let plaintext = await decrypt(enc, cek, ciphertext, iv, tag, additionalData)

if (joseHeader.zip === 'DEF') {
plaintext = await (options?.inflateRaw || inflate)(plaintext)
Expand All @@ -230,7 +250,11 @@ export async function flattenedDecrypt(
}

if (jwe.aad !== undefined) {
result.additionalAuthenticatedData = base64url(jwe.aad!)
try {
result.additionalAuthenticatedData = base64url(jwe.aad!)
} catch {
throw new JWEInvalid('Failed to base64url decode the aad')
}
}

if (jwe.unprotected !== undefined) {
Expand Down
8 changes: 6 additions & 2 deletions src/jws/flattened/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export async function flattenedVerify(
try {
signature = base64url(jws.signature)
} catch {
throw new JWSInvalid('Failed to parse the base64url encoded signature')
throw new JWSInvalid('Failed to base64url decode the signature')
}
const verified = await verify(alg, key, signature, data)

Expand All @@ -183,7 +183,11 @@ export async function flattenedVerify(

let payload: Uint8Array
if (b64) {
payload = base64url(jws.payload)
try {
payload = base64url(jws.payload)
} catch {
throw new JWSInvalid('Failed to base64url decode the payload')
}
} else if (typeof jws.payload === 'string') {
payload = encoder.encode(jws.payload)
} else {
Expand Down
34 changes: 29 additions & 5 deletions src/lib/decrypt_key_management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,21 @@ async function decryptKeyManagement(
if (joseHeader.apu !== undefined) {
if (typeof joseHeader.apu !== 'string')
throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`)
partyUInfo = base64url(joseHeader.apu)
try {
partyUInfo = base64url(joseHeader.apu)
} catch {
throw new JWEInvalid('Failed to base64url decode the apu')
}
}

if (joseHeader.apv !== undefined) {
if (typeof joseHeader.apv !== 'string')
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`)
partyVInfo = base64url(joseHeader.apv)
try {
partyVInfo = base64url(joseHeader.apv)
} catch {
throw new JWEInvalid('Failed to base64url decode the apv')
}
}

const sharedSecret = await ECDH.deriveKey(
Expand Down Expand Up @@ -105,7 +113,13 @@ async function decryptKeyManagement(
if (typeof joseHeader.p2s !== 'string')
throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`)

return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, base64url(joseHeader.p2s))
let p2s: Uint8Array
try {
p2s = base64url(joseHeader.p2s)
} catch {
throw new JWEInvalid('Failed to base64url decode the p2s')
}
return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, p2s)
}
case 'A128KW':
case 'A192KW':
Expand All @@ -127,8 +141,18 @@ async function decryptKeyManagement(
if (typeof joseHeader.tag !== 'string')
throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`)

const iv = base64url(joseHeader.iv)
const tag = base64url(joseHeader.tag)
let iv: Uint8Array
try {
iv = base64url(joseHeader.iv)
} catch {
throw new JWEInvalid('Failed to base64url decode the iv')
}
let tag: Uint8Array
try {
tag = base64url(joseHeader.tag)
} catch {
throw new JWEInvalid('Failed to base64url decode the tag')
}

return aesGcmKw(alg, key, encryptedKey, iv, tag)
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/browser/asn1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export const fromX509: PEMImportFunction = (pem, alg, options?) => {
spki = getSPKI(pem)
} catch (cause) {
// @ts-ignore
throw new TypeError('failed to parse the X.509 certificate', { cause })
throw new TypeError('Failed to parse the X.509 certificate', { cause })
}
return fromSPKI(spki, alg, options)
}
2 changes: 1 addition & 1 deletion src/util/decode_jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function decodeJwt(jwt: string) {
try {
decoded = base64url(payload)
} catch {
throw new JWTInvalid('Failed to parse the base64url encoded payload')
throw new JWTInvalid('Failed to base64url decode the payload')
}

let result: unknown
Expand Down

0 comments on commit 9024e87

Please sign in to comment.