I'd like to download public key from jwk
endpoint and convert it into pem
format that is required in sing
function for jwt
.
export type Secret =
| string
| Buffer
| { key: string | Buffer; passphrase: string };
The jwk
format can be imported with subtle
from crypto
as the webKey
of JsonWebKey
type and returned as CryptoKey
const pubKey = await subtle.importKey(
"jwk",
webKey,
{ hash: 'SHA-256', name: 'RSA-OAEP' },
true,
[]
);
The CryptoKey
can be exported with subtle.exportKey
but the result is in ByteArray
and converting it to pem
with 1. converting bytes to chars then 2. to base64 and adding it to -----BEGIN PUBLIC KEY-----
with envelope with adding new line every 64 characters produces an invalid key .
/**
* Exports the given key into the specified format, if supported.
*
* If the `<CryptoKey>` is not extractable, the returned promise will reject.
*
* When `format` is either `'pkcs8'` or `'spki'` and the export is successful,
* the returned promise will be resolved with an `<ArrayBuffer>` containing the exported key data.
*
* When `format` is `'jwk'` and the export is successful, the returned promise will be resolved with a
* JavaScript object conforming to the {@link https://tools.ietf.org/html/rfc7517 JSON Web Key} specification.
* @param format Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`.
* @returns `<Promise>` containing `<ArrayBuffer>`.
* @since v15.0.0
*/
exportKey(format: 'jwk', key: CryptoKey): Promise<JsonWebKey>;
exportKey(format: Exclude<KeyFormat, 'jwk'>, key: CryptoKey): Promise<ArrayBuffer>;
Also, the pub key can be exported only to spki
and jwk
the raw
is not supported.
The question in how to convert jwk
to pem
as simply as possible?!
The trick is converting CryptoKey
to KeyObject
with static from(key: webcrypto.CryptoKey): KeyObject;
and then use export(options: KeyExportOptions<'pem'>): string | Buffer;
export(options: KeyExportOptions<'pem'>): string | Buffer;
that is member of KeyObject
.
The function would be
export async function jwkToPem(webKey: JsonWebKey): Promise<string> {
const cryptoKey = await subtle.importKey(
"jwk",
webKey,
{ hash: 'SHA-256', name: 'RSA-OAEP' },
true,
[]
);
return KeyObject.from(cryptoKey).export({ format: "pem", type: "pkcs1"}).toString();
}
It could be even easier using createPublicKey
that accepts JsonWebKeyInput
and produces KeyObject
that could be easily exported.
/**
* Creates and returns a new key object containing a public key. If `key` is a
* string or `Buffer`, `format` is assumed to be `'pem'`; if `key` is a `KeyObject`with type `'private'`, the public key is derived from the given private key;
* otherwise, `key` must be an object with the properties described above.
*
* If the format is `'pem'`, the `'key'` may also be an X.509 certificate.
*
* Because public keys can be derived from private keys, a private key may be
* passed instead of a public key. In that case, this function behaves as if {@link createPrivateKey} had been called, except that the type of the
* returned `KeyObject` will be `'public'` and that the private key cannot be
* extracted from the returned `KeyObject`. Similarly, if a `KeyObject` with type`'private'` is given, a new `KeyObject` with type `'public'` will be returned
* and it will be impossible to extract the private key from the returned object.
* @since v11.6.0
*/
function createPublicKey(key: PublicKeyInput | string | Buffer | KeyObject | JsonWebKeyInput): KeyObject;
then
export async function jwkToPem(webKey: JsonWebKey): Promise<string> {
const pubKey: KeyObject = createPublicKey({
key: webKey,
format: 'jwk'
});
return pubKey.export({ format: "pem", type: "pkcs1"}).toString();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.