Skip to content

Commit

Permalink
feat: add X.509/SPKI/PKCS8 key import and SPKI/PKCS8 export functions
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Sep 22, 2021
1 parent 798e7cd commit a2af0f4
Show file tree
Hide file tree
Showing 22 changed files with 1,517 additions and 108 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,29 @@ If you or your business use `jose`, please consider becoming a [sponsor][support
- Encrypted JSON Web Tokens
- [Encryption](docs/classes/jwt_encrypt.EncryptJWT.md#readme)
- [Decryption & Claims Set Validation](docs/functions/jwt_decrypt.jwtDecrypt.md#readme)
- Key Import
- [JWK Import](docs/functions/key_import.importJWK.md#readme)
- [Public Key Import (SPKI)](docs/functions/key_import.importSPKI.md#readme)
- [Public Key Import (X.509 Certificate)](docs/functions/key_import.importX509.md#readme)
- [Private Key Import (PKCS #8)](docs/functions/key_import.importPKCS8.md#readme)
- JSON Web Encryption (JWE)
- Encryption - [Compact](docs/classes/jwe_compact_encrypt.CompactEncrypt.md#readme), [Flattened](docs/classes/jwe_flattened_encrypt.FlattenedEncrypt.md#readme)
- Decryption - [Compact](docs/functions/jwe_compact_decrypt.compactDecrypt.md#readme), [Flattened](docs/functions/jwe_flattened_decrypt.flattenedDecrypt.md#readme), [General](docs/functions/jwe_general_decrypt.generalDecrypt.md#readme)
- JSON Web Signature (JWS)
- 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)
- [Parsing (JWK to KeyLike)](docs/functions/jwk_parse.parseJwk.md#readme)
- [Conversion (KeyLike to JWK)](docs/functions/jwk_from_key_like.fromKeyLike.md#readme)
- [Thumbprints](docs/functions/jwk_thumbprint.calculateThumbprint.md#readme)
- [EmbeddedJWK](docs/functions/jwk_embedded.EmbeddedJWK.md#readme)
- JSON Web Key Set (JWKS)
- [Verify using a remote JWKSet](docs/functions/jwks_remote.createRemoteJWKSet.md#readme)
- Key Pair or Secret Generation (Generate KeyLike)
- Key Pair or Secret Generation
- [Asymmetric Key Pair Generation](docs/functions/util_generate_key_pair.generateKeyPair.md#readme)
- [Symmetric Secret Generation](docs/functions/util_generate_secret.generateSecret.md#readme)
- Key Export
- [JWK Export](docs/functions/key_export.exportJWK.md#readme)
- [Private Key Export](docs/functions/key_export.exportPKCS8.md#readme)
- [Public Key Export](docs/functions/key_export.exportSPKI.md#readme)
- Utilities
- [Decoding Token's Protected Header](docs/functions/util_decode_protected_header.decodeProtectedHeader.md#readme)
- [Unsecured JWT](docs/classes/jwt_unsecured.UnsecuredJWT.md#readme)
Expand Down
13 changes: 10 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,29 @@ If you or your business use `jose`, please consider becoming a [sponsor][support
- Encrypted JSON Web Tokens
- [Encryption](classes/jwt_encrypt.EncryptJWT.md#readme)
- [Decryption & Claims Set Validation](functions/jwt_decrypt.jwtDecrypt.md#readme)
- Key Import
- [JWK Import](functions/key_import.importJWK.md#readme)
- [Public Key Import (SPKI)](functions/key_import.importSPKI.md#readme)
- [Public Key Import (X.509 Certificate)](functions/key_import.importX509.md#readme)
- [Private Key Import (PKCS #8)](functions/key_import.importPKCS8.md#readme)
- JSON Web Encryption (JWE)
- Encryption - [Compact](classes/jwe_compact_encrypt.CompactEncrypt.md#readme), [Flattened](classes/jwe_flattened_encrypt.FlattenedEncrypt.md#readme)
- Decryption - [Compact](functions/jwe_compact_decrypt.compactDecrypt.md#readme), [Flattened](functions/jwe_flattened_decrypt.flattenedDecrypt.md#readme), [General](functions/jwe_general_decrypt.generalDecrypt.md#readme)
- JSON Web Signature (JWS)
- 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)
- [Parsing (JWK to KeyLike)](functions/jwk_parse.parseJwk.md#readme)
- [Conversion (KeyLike to JWK)](functions/jwk_from_key_like.fromKeyLike.md#readme)
- [Thumbprints](functions/jwk_thumbprint.calculateThumbprint.md#readme)
- [EmbeddedJWK](functions/jwk_embedded.EmbeddedJWK.md#readme)
- JSON Web Key Set (JWKS)
- [Verify using a remote JWKSet](functions/jwks_remote.createRemoteJWKSet.md#readme)
- Key Pair or Secret Generation (Generate KeyLike)
- Key Pair or Secret Generation
- [Asymmetric Key Pair Generation](functions/util_generate_key_pair.generateKeyPair.md#readme)
- [Symmetric Secret Generation](functions/util_generate_secret.generateSecret.md#readme)
- Key Export
- [JWK Export](functions/key_export.exportJWK.md#readme)
- [Private Key Export](functions/key_export.exportPKCS8.md#readme)
- [Public Key Export](functions/key_export.exportSPKI.md#readme)
- Utilities
- [Decoding Token's Protected Header](functions/util_decode_protected_header.decodeProtectedHeader.md#readme)
- [Unsecured JWT](classes/jwt_unsecured.UnsecuredJWT.md#readme)
Expand Down
24 changes: 19 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
"description": "Universal 'JSON Web Almost Everything' - JWA, JWS, JWE, JWT, JWK with no dependencies",
"keywords": [
"browser",
"cloudflare",
"compact",
"decode",
"decrypt",
"detached",
"deno",
"cloudflare",
"workers",
"detached",
"ec",
"ecdsa",
"eddsa",
Expand All @@ -32,14 +31,19 @@
"oct",
"okp",
"payload",
"pem",
"pkcs8",
"rsa",
"secp256k1",
"sign",
"signature",
"spki",
"universal",
"validate",
"verify",
"webcrypto"
"webcrypto",
"workers",
"x509"
],
"homepage": "https://github.com/panva/jose",
"repository": "panva/jose",
Expand Down Expand Up @@ -165,6 +169,16 @@
"import": "./dist/node/esm/jwt/verify.js",
"require": "./dist/node/cjs/jwt/verify.js"
},
"./key/export": {
"browser": "./dist/browser/key/export.js",
"import": "./dist/node/esm/key/export.js",
"require": "./dist/node/cjs/key/export.js"
},
"./key/import": {
"browser": "./dist/browser/key/import.js",
"import": "./dist/node/esm/key/import.js",
"require": "./dist/node/cjs/key/import.js"
},
"./util/base64url": {
"browser": "./dist/browser/util/base64url.js",
"import": "./dist/node/esm/util/base64url.js",
Expand Down Expand Up @@ -235,7 +249,7 @@
"coverage-cryptokey": "npm run-script runtime-node && c8 npm run-script test-cryptokey",
"coverage-webcrypto": "npm run-script runtime-node-webcrypto && c8 npm run-script test-webcrypto",
"docs": "run-s docs:*",
"docs:generate": "typedoc --allReflectionsHaveOwnDocument --excludePrivate --excludeProtected --gitRevision main --readme none --plugin typedoc-plugin-markdown --out docs --excludeExternals --tsconfig ./tsconfig/browser.json --hideGenerator --hideBreadcrumbs src/types.d.ts src/jwt/*.ts src/jwe/**/*.ts src/jws/**/*.ts src/jwk/*.ts src/jwks/*.ts src/util/*.ts",
"docs:generate": "typedoc --allReflectionsHaveOwnDocument --excludePrivate --excludeProtected --gitRevision main --readme none --plugin typedoc-plugin-markdown --out docs --excludeExternals --tsconfig ./tsconfig/browser.json --hideGenerator --hideBreadcrumbs src/types.d.ts src/jwt/*.ts src/jwe/**/*.ts src/jws/**/*.ts src/jwk/*.ts src/jwks/*.ts src/util/*.ts src/key/*.ts",
"esbuild-find": "find src -type f -name '*.ts' -not -path '*/runtime/*/*' -not -name '*.d.ts' -print0",
"runtime-browser": "run-s runtime:clear runtime:browser:* runtime:refs",
"runtime-deno": "npm run-script runtime-browser && mkdir -p dist/deno && cp -r src/. dist/deno && rm -r dist/deno/runtime/browser dist/deno/runtime/node && rm dist/deno/.prettierrc.json",
Expand Down
28 changes: 1 addition & 27 deletions src/jwk/from_key_like.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,7 @@ import asJWK from '../runtime/key_to_jwk.js'
import type { JWK, KeyLike } from '../types.d'

/**
* Converts a runtime-specific key representation (KeyLike) to a JWK.
*
* @param key Key representation to transform to a JWK.
*
* @example ESM import
* ```js
* import { fromKeyLike } from 'jose/jwk/from_key_like'
* ```
*
* @example CJS import
* ```js
* const { fromKeyLike } = require('jose/jwk/from_key_like')
* ```
*
* @example Deno import
* ```js
* import { fromKeyLike } from 'https://deno.land/x/jose@VERSION/jwk/from_key_like.ts'
* ```
*
* @example Usage
* ```js
* const privateJwk = await fromKeyLike(privateKey)
* const publicJwk = await fromKeyLike(publicKey)
*
* console.log(privateJwk)
* console.log(publicJwk)
* ```
* @deprecated use `jose/key/export`
*/
async function fromKeyLike(key: KeyLike): Promise<JWK> {
return asJWK(key)
Expand Down
42 changes: 1 addition & 41 deletions src/jwk/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,7 @@ import isObject from '../lib/is_object.js'
import type { JWK, KeyLike } from '../types.d'

/**
* Converts a JWK to a runtime-specific key representation (KeyLike). Either
* JWK "alg" (Algorithm) Parameter must be present or the optional "alg" argument. When
* running on a platform using [Web Cryptography API](https://www.w3.org/TR/WebCryptoAPI/)
* the jwk parameters "use", "key_ops", and "ext" are also used in the resulting `CryptoKey`.
*
* @param jwk JSON Web Key.
* @param alg JSON Web Algorithm identifier to be used with the converted key.
* Default is the "alg" property on the JWK.
* @param octAsKeyObject Forces a symmetric key to be converted to a KeyObject or
* CryptoKey. Default is true unless JWK "ext" (Extractable) is true.
*
* @example ESM import
* ```js
* import { parseJwk } from 'jose/jwk/parse'
* ```
*
* @example CJS import
* ```js
* const { parseJwk } = require('jose/jwk/parse')
* ```
*
* @example Deno import
* ```js
* import { parseJwk } from 'https://deno.land/x/jose@VERSION/jwk/parse.ts'
* ```
*
* @example Usage
* ```js
* const ecPublicKey = await parseJwk({
* crv: 'P-256',
* kty: 'EC',
* x: 'ySK38C1jBdLwDsNWKzzBHqKYEE5Cgv-qjWvorUXk9fw',
* y: '_LeQBw07cf5t57Iavn4j-BqJsAD1dpoz8gokd3sBsOo'
* }, 'ES256')
*
* const rsaPublicKey = await parseJwk({
* kty: 'RSA',
* e: 'AQAB',
* n: '12oBZRhCiZFJLcPg59LkZZ9mdhSMTKAQZYq32k_ti5SBB6jerkh-WzOMAO664r_qyLkqHUSp3u5SbXtseZEpN3XPWGKSxjsy-1JyEFTdLSYe6f9gfrmxkUF_7DTpq0gn6rntP05g2-wFW50YO7mosfdslfrTJYWHFhJALabAeYirYD7-9kqq9ebfFMF4sRRELbv9oi36As6Q9B3Qb5_C1rAzqfao_PCsf9EPsTZsVVVkA5qoIAr47lo1ipfiBPxUCCNSdvkmDTYgvvRm6ZoMjFbvOtgyts55fXKdMWv7I9HMD5HwE9uW839PWA514qhbcIsXEYSFMPMV6fnlsiZvQQ'
* }, 'PS256')
* ```
* @deprecated use `jose/key/import`
*/
async function parseJwk(jwk: JWK, alg?: string, octAsKeyObject?: boolean): Promise<KeyLike> {
if (!isObject(jwk)) {
Expand Down
100 changes: 100 additions & 0 deletions src/key/export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { toSPKI as exportPublic } from '../runtime/asn1.js'
import { toPKCS8 as exportPrivate } from '../runtime/asn1.js'

import { fromKeyLike } from '../jwk/from_key_like.js'
import type { KeyLike } from '../types.d'

/**
* Exports a runtime-specific public key representation (KeyObject or CryptoKey) to an PEM-encoded SPKI string format.
*
* @param key Key representation to transform to an PEM-encoded SPKI string format.
*
* @example ESM import
* ```js
* import { exportSPKI } from 'jose/key/export'
* ```
*
* @example CJS import
* ```js
* const { exportSPKI } = require('jose/key/export')
* ```
*
* @example Deno import
* ```js
* import { exportSPKI } from 'https://deno.land/x/jose@VERSION/key/export.ts'
* ```
*
* @example Usage
* ```js
* const spkiPem = await exportSPKI(publicKey)
*
* console.log(spkiPem)
* ```
*/
export async function exportSPKI(key: Exclude<KeyLike, Uint8Array>): Promise<string> {
return exportPublic(key)
}

/**
* Exports a runtime-specific private key representation (KeyObject or CryptoKey) to an PEM-encoded PKCS8 string format.
*
* @param key Key representation to transform to an PEM-encoded PKCS8 string format.
*
* @example ESM import
* ```js
* import { exportPKCS8 } from 'jose/key/export'
* ```
*
* @example CJS import
* ```js
* const { exportPKCS8 } = require('jose/key/export')
* ```
*
* @example Deno import
* ```js
* import { exportPKCS8 } from 'https://deno.land/x/jose@VERSION/key/export.ts'
* ```
*
* @example Usage
* ```js
* const pkcs8Pem = await exportPKCS8(privateKey)
*
* console.log(pkcs8Pem)
* ```
*/
export async function exportPKCS8(key: Exclude<KeyLike, Uint8Array>): Promise<string> {
return exportPrivate(key)
}

/**
* Exports a runtime-specific key representation (KeyLike) to a JWK.
*
* @param key Key representation to export as JWK.
*
* @example ESM import
* ```js
* import { exportJWK } from 'jose/key/export'
* ```
*
* @example CJS import
* ```js
* const { exportJWK } = require('jose/key/export')
* ```
*
* @example Deno import
* ```js
* import { exportJWK } from 'https://deno.land/x/jose@VERSION/key/export.ts'
* ```
*
* @example Usage
* ```js
* const privateJwk = await exportJWK(privateKey)
* const publicJwk = await exportJWK(publicKey)
*
* console.log(privateJwk)
* console.log(publicJwk)
* ```
*/
export const exportJWK: typeof fromKeyLike = (...args) => fromKeyLike(...args)

export type { KeyLike }
Loading

0 comments on commit a2af0f4

Please sign in to comment.