diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2023-11-09 09:56:59 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-09 23:26:59 +0530 |
commit | c4029f6af22b373bf22383453cb4e2159f3b5b72 (patch) | |
tree | 588594d5d5eb98689101565fb76c6a546cc9e78a /ext/node/polyfills/internal/crypto | |
parent | ee7fd0a2127e6a435023bf9a43de60130117697d (diff) |
fix(node): implement createPrivateKey (#20981)
Towards #18455
Diffstat (limited to 'ext/node/polyfills/internal/crypto')
-rw-r--r-- | ext/node/polyfills/internal/crypto/cipher.ts | 5 | ||||
-rw-r--r-- | ext/node/polyfills/internal/crypto/keys.ts | 75 | ||||
-rw-r--r-- | ext/node/polyfills/internal/crypto/sig.ts | 11 |
3 files changed, 69 insertions, 22 deletions
diff --git a/ext/node/polyfills/internal/crypto/cipher.ts b/ext/node/polyfills/internal/crypto/cipher.ts index cf1641326..5fec98ff0 100644 --- a/ext/node/polyfills/internal/crypto/cipher.ts +++ b/ext/node/polyfills/internal/crypto/cipher.ts @@ -28,7 +28,7 @@ import { isArrayBufferView, } from "ext:deno_node/internal/util/types.ts"; -function isStringOrBuffer(val) { +export function isStringOrBuffer(val) { return typeof val === "string" || isArrayBufferView(val) || isAnyArrayBuffer(val); @@ -456,7 +456,7 @@ export function publicEncrypt( return ops.op_node_public_encrypt(data, buffer, padding); } -function prepareKey(key) { +export function prepareKey(key) { // TODO(@littledivy): handle these cases // - node KeyObject // - web CryptoKey @@ -485,5 +485,6 @@ export default { publicEncrypt, Cipheriv, Decipheriv, + prepareKey, getCipherInfo, }; diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts index be85b44a3..e0c44cbf9 100644 --- a/ext/node/polyfills/internal/crypto/keys.ts +++ b/ext/node/polyfills/internal/crypto/keys.ts @@ -8,6 +8,7 @@ import { kHandle, kKeyObject, } from "ext:deno_node/internal/crypto/constants.ts"; +import { isStringOrBuffer } from "ext:deno_node/internal/crypto/cipher.ts"; import { ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, ERR_INVALID_ARG_TYPE, @@ -16,7 +17,6 @@ import { import { notImplemented } from "ext:deno_node/_utils.ts"; import type { KeyFormat, - KeyType, PrivateKeyInput, PublicKeyInput, } from "ext:deno_node/internal/crypto/types.ts"; @@ -39,6 +39,9 @@ import { forgivingBase64UrlEncode as encodeToBase64Url, } from "ext:deno_web/00_infra.js"; +const { core } = globalThis.__bootstrap; +const { ops } = core; + export const getArrayBufferOrView = hideStackFrames( ( buffer, @@ -168,18 +171,6 @@ export class KeyObject { return this[kKeyType]; } - get asymmetricKeyDetails(): AsymmetricKeyDetails | undefined { - notImplemented("crypto.KeyObject.prototype.asymmetricKeyDetails"); - - return undefined; - } - - get asymmetricKeyType(): KeyType | undefined { - notImplemented("crypto.KeyObject.prototype.asymmetricKeyType"); - - return undefined; - } - get symmetricKeySize(): number | undefined { notImplemented("crypto.KeyObject.prototype.symmetricKeySize"); @@ -219,10 +210,33 @@ export interface JsonWebKeyInput { format: "jwk"; } +function prepareAsymmetricKey(key) { + if (isStringOrBuffer(key)) { + return { format: "pem", data: getArrayBufferOrView(key, "key") }; + } else if (typeof key == "object") { + const { key: data, encoding, format, type } = key; + if (!isStringOrBuffer(data)) { + throw new TypeError("Invalid key type"); + } + + return { + data: getArrayBufferOrView(data, "key", encoding), + format: format ?? "pem", + encoding, + type, + }; + } + + throw new TypeError("Invalid key type"); +} + export function createPrivateKey( - _key: PrivateKeyInput | string | Buffer | JsonWebKeyInput, -): KeyObject { - notImplemented("crypto.createPrivateKey"); + key: PrivateKeyInput | string | Buffer | JsonWebKeyInput, +): PrivateKeyObject { + const { data, format, type } = prepareAsymmetricKey(key); + const details = ops.op_node_create_private_key(data, format, type); + const handle = setOwnedKey(copyBuffer(data)); + return new PrivateKeyObject(handle, details); } export function createPublicKey( @@ -316,6 +330,35 @@ export class SecretKeyObject extends KeyObject { } } +const kAsymmetricKeyType = Symbol("kAsymmetricKeyType"); +const kAsymmetricKeyDetails = Symbol("kAsymmetricKeyDetails"); + +class AsymmetricKeyObject extends KeyObject { + constructor(type: KeyObjectType, handle: unknown, details: unknown) { + super(type, handle); + this[kAsymmetricKeyType] = details.type; + this[kAsymmetricKeyDetails] = { ...details }; + } + + get asymmetricKeyType() { + return this[kAsymmetricKeyType]; + } + + get asymmetricKeyDetails() { + return this[kAsymmetricKeyDetails]; + } +} + +class PrivateKeyObject extends AsymmetricKeyObject { + constructor(handle: unknown, details: unknown) { + super("private", handle, details); + } + + export(_options: unknown) { + notImplemented("crypto.PrivateKeyObject.prototype.export"); + } +} + export function setOwnedKey(key: Uint8Array): unknown { const handle = {}; KEY_STORE.set(handle, key); diff --git a/ext/node/polyfills/internal/crypto/sig.ts b/ext/node/polyfills/internal/crypto/sig.ts index ebbd11dc6..c5eb34fae 100644 --- a/ext/node/polyfills/internal/crypto/sig.ts +++ b/ext/node/polyfills/internal/crypto/sig.ts @@ -19,7 +19,10 @@ import type { PrivateKeyInput, PublicKeyInput, } from "ext:deno_node/internal/crypto/types.ts"; -import { KeyObject } from "ext:deno_node/internal/crypto/keys.ts"; +import { + getKeyMaterial, + KeyObject, +} from "ext:deno_node/internal/crypto/keys.ts"; import { createHash, Hash } from "ext:deno_node/internal/crypto/hash.ts"; import { KeyFormat, KeyType } from "ext:deno_node/internal/crypto/types.ts"; import { isArrayBufferView } from "ext:deno_node/internal/util/types.ts"; @@ -87,9 +90,9 @@ export class SignImpl extends Writable { keyType = "rsa"; keyFormat = "pem"; } else { - // TODO(kt3k): Add support for the case when privateKey is a KeyObject, - // CryptoKey, etc - notImplemented("crypto.Sign.prototype.sign with non BinaryLike input"); + keyData = getKeyMaterial(privateKey); + keyType = "rsa"; + keyFormat = "pem"; } const ret = Buffer.from(ops.op_node_sign( this.hash.digest(), |