mirror of
https://github.com/danbulant/jose
synced 2026-05-19 04:18:52 +00:00
wip
[skip ci]
This commit is contained in:
parent
3ffb52b19e
commit
7bde9ff239
5 changed files with 77 additions and 17 deletions
|
|
@ -12,6 +12,7 @@ The following specifications are implemented by `jose`
|
|||
- JSON Web Algorithms (JWA) - [RFC7518][spec-jwa]
|
||||
- JSON Web Token (JWT) - [RFC7519][spec-jwt]
|
||||
- JSON Web Key Thumbprint - [RFC7638][spec-thumbprint]
|
||||
- JSON Web Key Thumbprint URI - [RFCXXXX][spec-thumbprint-uri]
|
||||
- JWS Unencoded Payload Option - [RFC7797][spec-b64]
|
||||
- CFRG Elliptic Curve ECDH and Signatures - [RFC8037][spec-okp]
|
||||
- secp256k1 EC Key curve support - [JOSE Registrations for WebAuthn Algorithms][spec-secp256k1]
|
||||
|
|
@ -58,8 +59,9 @@ import * as jose from 'https://deno.land/x/jose/index.ts'
|
|||
- Signing - [Compact](docs/classes/jws_compact_sign.CompactSign.md#readme), [Flattened](docs/classes/jws_flattened_sign.FlattenedSign.md#readme), [General](docs/classes/jws_general_sign.GeneralSign.md#readme)
|
||||
- Verification - [Compact](docs/functions/jws_compact_verify.compactVerify.md#readme), [Flattened](docs/functions/jws_flattened_verify.flattenedVerify.md#readme), [General](docs/functions/jws_general_verify.generalVerify.md#readme)
|
||||
- JSON Web Key (JWK)
|
||||
- [Thumbprints](docs/functions/jwk_thumbprint.calculateJwkThumbprint.md#readme)
|
||||
- [EmbeddedJWK](docs/functions/jwk_embedded.EmbeddedJWK.md#readme)
|
||||
- [Calculating JWK Thumbprint](docs/functions/jwk_thumbprint.calculateJwkThumbprint.md#readme)
|
||||
- [Calculating JWK Thumbprint URI](docs/functions/jwk_thumbprint.calculateJwkThumbprintUri.md#readme)
|
||||
- [Verification using a JWK Embedded in a JWT Header](docs/functions/jwk_embedded.EmbeddedJWK.md#readme)
|
||||
- JSON Web Key Set (JWKS)
|
||||
- [Verify using a local JWKSet](docs/functions/jwks_local.createLocalJWKSet.md#readme)
|
||||
- [Verify using a remote JWKSet](docs/functions/jwks_remote.createRemoteJWKSet.md#readme)
|
||||
|
|
@ -146,6 +148,7 @@ install size should not be a cause for concern.
|
|||
[spec-okp]: https://www.rfc-editor.org/rfc/rfc8037
|
||||
[spec-secp256k1]: https://www.rfc-editor.org/rfc/rfc8812
|
||||
[spec-thumbprint]: https://www.rfc-editor.org/rfc/rfc7638
|
||||
[spec-thumbprint-uri]: https://www.rfc-editor.org/rfc/rfcXXXX
|
||||
[support-sponsor]: https://github.com/sponsors/panva
|
||||
[conditional-exports]: https://nodejs.org/api/packages.html#packages_conditional_exports
|
||||
[webcrypto]: https://www.w3.org/TR/WebCryptoAPI/
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ import * as jose from 'https://deno.land/x/jose/index.ts'
|
|||
- Signing - [Compact](classes/jws_compact_sign.CompactSign.md#readme), [Flattened](classes/jws_flattened_sign.FlattenedSign.md#readme), [General](classes/jws_general_sign.GeneralSign.md#readme)
|
||||
- Verification - [Compact](functions/jws_compact_verify.compactVerify.md#readme), [Flattened](functions/jws_flattened_verify.flattenedVerify.md#readme), [General](functions/jws_general_verify.generalVerify.md#readme)
|
||||
- JSON Web Key (JWK)
|
||||
- [Thumbprints](functions/jwk_thumbprint.calculateJwkThumbprint.md#readme)
|
||||
- [EmbeddedJWK](functions/jwk_embedded.EmbeddedJWK.md#readme)
|
||||
- [Calculating JWK Thumbprint](functions/jwk_thumbprint.calculateJwkThumbprint.md#readme)
|
||||
- [Calculating JWK Thumbprint URI](functions/jwk_thumbprint.calculateJwkThumbprintUri.md#readme)
|
||||
- [Verification using a JWK Embedded in a JWT Header](functions/jwk_embedded.EmbeddedJWK.md#readme)
|
||||
- JSON Web Key Set (JWKS)
|
||||
- [Verify using a local JWKSet](functions/jwks_local.createLocalJWKSet.md#readme)
|
||||
- [Verify using a remote JWKSet](functions/jwks_remote.createRemoteJWKSet.md#readme)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export type { Signature } from './jws/general/sign.js'
|
|||
export { SignJWT } from './jwt/sign.js'
|
||||
export { EncryptJWT } from './jwt/encrypt.js'
|
||||
|
||||
export { calculateJwkThumbprint } from './jwk/thumbprint.js'
|
||||
export { calculateJwkThumbprint, calculateJwkThumbprintUri } from './jwk/thumbprint.js'
|
||||
export { EmbeddedJWK } from './jwk/embedded.js'
|
||||
|
||||
export { createLocalJWKSet } from './jwks/local.js'
|
||||
|
|
|
|||
|
|
@ -18,17 +18,18 @@ const check = (value: unknown, description: string) => {
|
|||
*
|
||||
* @param jwk JSON Web Key.
|
||||
* @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint.
|
||||
* Default is sha256. Accepted is "sha256", "sha384", "sha512".
|
||||
*
|
||||
* @example Usage
|
||||
* ```js
|
||||
* const thumbprint = await jose.calculateJwkThumbprint({
|
||||
* kty: 'RSA',
|
||||
* e: 'AQAB',
|
||||
* n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ'
|
||||
* kty: 'EC',
|
||||
* crv: 'P-256',
|
||||
* x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo',
|
||||
* y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww'
|
||||
* })
|
||||
*
|
||||
* console.log(thumbprint)
|
||||
* // 'w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8'
|
||||
* ```
|
||||
*/
|
||||
export async function calculateJwkThumbprint(
|
||||
|
|
@ -76,3 +77,31 @@ export async function calculateJwkThumbprint(
|
|||
const data = encoder.encode(JSON.stringify(components))
|
||||
return base64url(await digest(digestAlgorithm, data))
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a JSON Web Key (JWK) Thumbprint URI as per
|
||||
* [RFCXXXX](https://www.rfc-editor.org/rfc/rfcXXXX).
|
||||
*
|
||||
* @param jwk JSON Web Key.
|
||||
* @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint.
|
||||
*
|
||||
* @example Usage
|
||||
* ```js
|
||||
* const thumbprintUri = await jose.calculateJwkThumbprintUri({
|
||||
* kty: 'EC',
|
||||
* crv: 'P-256',
|
||||
* x: 'jJ6Flys3zK9jUhnOHf6G49Dyp5hah6CNP84-gY-n9eo',
|
||||
* y: 'nhI6iD5eFXgBTLt_1p3aip-5VbZeMhxeFSpjfEAf7Ww'
|
||||
* })
|
||||
*
|
||||
* console.log(thumbprint)
|
||||
* // 'urn:ietf:params:oauth:jwk-thumbprint:sha-256:w9eYdC6_s_tLQ8lH6PUpc0mddazaqtPgeC2IgWDiqY8'
|
||||
* ```
|
||||
*/
|
||||
export async function calculateJwkThumbprintUri(
|
||||
jwk: JWK,
|
||||
digestAlgorithm: 'sha256' | 'sha384' | 'sha512' = 'sha256',
|
||||
): Promise<string> {
|
||||
const thumbprint = await calculateJwkThumbprint(jwk, digestAlgorithm)
|
||||
return `urn:ietf:params:oauth:jwk-thumbprint:sha-${digestAlgorithm.slice(-3)}:${thumbprint}`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,44 @@
|
|||
import test from 'ava'
|
||||
import { keyRoot } from '../dist.mjs'
|
||||
|
||||
const { calculateJwkThumbprint } = await import(keyRoot)
|
||||
const { calculateJwkThumbprint, calculateJwkThumbprintUri } = await import(keyRoot)
|
||||
|
||||
const jwk = {
|
||||
kty: 'RSA',
|
||||
n: '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw',
|
||||
e: 'AQAB',
|
||||
alg: 'RS256',
|
||||
}
|
||||
|
||||
test('https://www.rfc-editor.org/rfc/rfc7638#section-3.1', async (t) => {
|
||||
t.is(await calculateJwkThumbprint(jwk), 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs')
|
||||
t.is(await calculateJwkThumbprint(jwk, 'sha256'), 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs')
|
||||
t.is(
|
||||
await calculateJwkThumbprint({
|
||||
kty: 'RSA',
|
||||
n: '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw',
|
||||
e: 'AQAB',
|
||||
alg: 'RS256',
|
||||
}),
|
||||
'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs',
|
||||
await calculateJwkThumbprint(jwk, 'sha384'),
|
||||
'R9_OfJjSjaw8Fuum86UzK5ixTdN9bo9BaqPSiseq89DWfmqCdpSgUHus-cxDUNc8',
|
||||
)
|
||||
t.is(
|
||||
await calculateJwkThumbprint(jwk, 'sha512'),
|
||||
'DpvEwocfn3FjeWWQjcJHzWrpKTIymKwgoL1xVgQcud48-qZDSRCr1zfWZQdHAJn_ciqXqPTSARyg-L-NyNGpVA',
|
||||
)
|
||||
})
|
||||
|
||||
test('https://www.rfc-editor.org/rfc/rfcXXXX', async (t) => {
|
||||
t.is(
|
||||
await calculateJwkThumbprintUri(jwk),
|
||||
'urn:ietf:params:oauth:jwk-thumbprint:sha-256:NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs',
|
||||
)
|
||||
t.is(
|
||||
await calculateJwkThumbprintUri(jwk, 'sha256'),
|
||||
'urn:ietf:params:oauth:jwk-thumbprint:sha-256:NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs',
|
||||
)
|
||||
t.is(
|
||||
await calculateJwkThumbprintUri(jwk, 'sha384'),
|
||||
'urn:ietf:params:oauth:jwk-thumbprint:sha-384:R9_OfJjSjaw8Fuum86UzK5ixTdN9bo9BaqPSiseq89DWfmqCdpSgUHus-cxDUNc8',
|
||||
)
|
||||
t.is(
|
||||
await calculateJwkThumbprintUri(jwk, 'sha512'),
|
||||
'urn:ietf:params:oauth:jwk-thumbprint:sha-512:DpvEwocfn3FjeWWQjcJHzWrpKTIymKwgoL1xVgQcud48-qZDSRCr1zfWZQdHAJn_ciqXqPTSARyg-L-NyNGpVA',
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue