英文:
How to convert JWK to PEM in NodeJS/Typescript
问题
我想从jwk
端点下载公钥并将其转换为jwt
的sing
函数所需的pem
格式。
export type Secret =
| string
| Buffer
| { key: string | Buffer; passphrase: string };
jwk
格式可以使用crypto
中的subtle
导入为JsonWebKey
类型的webKey
,并将其返回为CryptoKey
。
const pubKey = await subtle.importKey(
"jwk",
webKey,
{ hash: 'SHA-256', name: 'RSA-OAEP' },
true,
[]
);
CryptoKey
可以使用subtle.exportKey
导出,但结果是ByteArray
,将其转换为pem
需要两步:1. 将字节转换为字符,然后2. 转换为Base64,然后添加到-----BEGIN PUBLIC KEY-----
中,并在每64个字符后添加新行,这将产生无效的密钥。
/**
* 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>;
此外,公钥只能导出为spki
和jwk
,不支持raw
。
问题是如何尽可能简单地将jwk
转换为pem
!
英文:
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?!
答案1
得分: 1
以下是翻译好的内容:
"要诀是使用 static from(key: webcrypto.CryptoKey): KeyObject;
将 CryptoKey
转换为 KeyObject
,然后使用 KeyObject
的成员 export(options: KeyExportOptions<'pem'>): string | Buffer;
。
函数如下:
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();
}
Topaco's suggestion
使用 createPublicKey
可能更简单,它接受 JsonWebKeyInput
并生成 KeyObject
,可以轻松导出。
/**
* 创建并返回包含公钥的新密钥对象。如果 `key` 是字符串或 `Buffer`,则假定 `format` 为 `'pem'`;如果 `key` 是带有类型为 `'private'` 的 `KeyObject`,则从给定的私钥派生公钥;
* 否则,`key` 必须是具有上述属性的对象。
*
* 如果格式为 `'pem'`,则 `'key'` 也可以是 X.509 证书。
*
* 由于可以从私钥派生公钥,因此可以传递私钥而不是公钥。在这种情况下,此函数的行为就像已调用 {@link createPrivateKey} 一样,只是返回的 `KeyObject` 的类型将为 `'public'`,并且无法从返回的 `KeyObject` 中提取私钥。类似地,如果给定带有类型`'private'` 的 `KeyObject`,则将返回一个新的具有类型 `'public'` 的 `KeyObject`,并且无法从返回的对象中提取私钥。
* @since v11.6.0
*/
function createPublicKey(key: PublicKeyInput | string | Buffer | KeyObject | JsonWebKeyInput): KeyObject;
然后
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 trick is converting CryptoKey
to KeyObject
with static from(key: webcrypto.CryptoKey): KeyObject;
and then use 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();
}
Topaco's suggestion
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();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论