/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
ext/node/polyfills/internal/crypto/cipher.ts
926 строк
25 KB
Kenta Moriuchi
chore: make prefer-primordials lint an internal plugin (#35978)
23 июл 2026, 11:53
Не верифицирован
23 июл 2026, 11:53
5b55d08
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. // Copyright Joyent, Inc. and Node.js contributors. All rights reserved. MIT license. // deno-lint-ignore-file no-explicit-any (function () { const { core, primordials } = __bootstrap; const { encode, } = core; const { ArrayBufferIsView, Boolean, Error, FunctionPrototypeCall, MathFloor, ObjectPrototypeIsPrototypeOf, ObjectSetPrototypeOf, SafeRegExp, SafeSet, SetPrototypeHas, StringPrototypeReplace, StringPrototypeStartsWith, StringPrototypeToLowerCase, SymbolSpecies, TypeError, TypeErrorPrototype, TypedArrayPrototypeAt, TypedArrayPrototypeGetByteLength, Uint8Array, } = primordials; const { op_node_aes_unwrap_key, op_node_aes_wrap_key, op_node_cipheriv_encrypt, op_node_cipheriv_final, op_node_cipheriv_set_aad, op_node_cipheriv_take, op_node_create_cipheriv, op_node_create_decipheriv, op_node_create_private_key, op_node_decipheriv_auth_tag, op_node_decipheriv_decrypt, op_node_decipheriv_final, op_node_decipheriv_set_aad, op_node_export_private_key_pem, op_node_export_secret_key, op_node_private_decrypt, op_node_private_encrypt, op_node_public_decrypt, op_node_public_encrypt, op_node_validate_oaep_hash, } = core.ops; const { Buffer } = core.loadExtScript("ext:deno_node/internal/buffer.mjs"); const lazyStream = core.createLazyLoader("node:stream"); const { createPrivateKey, createPublicKey, getArrayBufferOrView, } = core.loadExtScript("ext:deno_node/internal/crypto/keys.ts"); const { isKeyObject } = core.loadExtScript( "ext:deno_node/internal/crypto/_keys.ts", ); const { kHandle } = core.loadExtScript( "ext:deno_node/internal/crypto/constants.ts", ); const { getDefaultEncoding } = core.loadExtScript( "ext:deno_node/internal/crypto/util.ts", ); const { ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_UNKNOWN_ENCODING, NodeError, } = core.loadExtScript("ext:deno_node/internal/errors.ts"); const { isAnyArrayBuffer, isArrayBufferView, } = core.loadExtScript("ext:deno_node/internal/util/types.ts"); const { ERR_CRYPTO_INVALID_STATE, ERR_CRYPTO_UNKNOWN_CIPHER } = core .loadExtScript( "ext:deno_node/internal/errors.ts", ); const { StringDecoder } = core.loadExtScript( "ext:deno_node/string_decoder.ts", ); const { default: assert } = core.loadExtScript("ext:deno_node/assert.ts"); const { normalizeEncoding } = core.loadExtScript( "ext:deno_node/internal/util.mjs", ); let Transform; function getTransform() { if (!Transform) Transform = lazyStream().Transform; return Transform; } const FastBuffer = Buffer[SymbolSpecies]; function opensslError(code: string, reason: string): NodeError { const err = new NodeError(code, reason); (err as any).reason = reason; return err; } function isAesWrap(cipher: string): boolean { return cipher === "aes128-wrap" || cipher === "aes192-wrap" || cipher === "aes256-wrap" || cipher === "id-aes128-wrap-pad" || cipher === "id-aes192-wrap-pad" || cipher === "id-aes256-wrap-pad"; } function isStringOrBuffer( val: unknown, ): val is string | Buffer | ArrayBuffer | ArrayBufferView { return typeof val === "string" || isArrayBufferView(val) || isAnyArrayBuffer(val) || Buffer.isBuffer(val); } // Matches Node's `ArrayBuffer.isView(data)` check in // `lib/internal/crypto/cipher.js`: accepts string, Buffer, TypedArray // or DataView, but rejects raw ArrayBuffer / SharedArrayBuffer. function validateCipherUpdateData(data: unknown): void { if (typeof data !== "string" && !ArrayBufferIsView(data)) { throw new ERR_INVALID_ARG_TYPE( "data", ["string", "Buffer", "TypedArray", "DataView"], data, ); } } const NO_TAG = new Uint8Array(); function toU8( input: string | Uint8Array | KeyObject | null, ): Uint8Array { if (input == null) { return new Uint8Array(0); } if (isKeyObject(input)) { return op_node_export_secret_key(input[kHandle]); } return typeof input === "string" ? encode(input) : input; } function Cipheriv( cipher: string, key: any, iv: any, options?: any, ) { if (!ObjectPrototypeIsPrototypeOf(Cipheriv.prototype, this)) { return new Cipheriv(cipher, key, iv, options); } const authTagLength = getUIntOption(options, "authTagLength"); FunctionPrototypeCall(getTransform(), this, { transform(chunk, encoding, cb) { // deno-lint-ignore deno-internal/prefer-primordials -- `this` is a Transform stream this.push(this.update(chunk, encoding)); cb(); }, final(cb) { // deno-lint-ignore deno-internal/prefer-primordials -- `this` is a Transform stream this.push(this.final()); cb(); }, ...options, }); this._blockSize = getBlockSize(cipher); this._cache = new BlockModeCache(false, this._blockSize); this._isAesWrap = isAesWrap(cipher); if (this._isAesWrap) { this._aesWrapAlgorithm = cipher; this._aesWrapKey = toU8(key); this._aesWrapIv = toU8(iv); this._context = 1; // non-zero sentinel; not used for wrap ops } else { try { this._context = op_node_create_cipheriv( cipher, toU8(key), toU8(iv), authTagLength, ); } catch (e) { // The op reports an unrecognized algorithm as a TypeError that includes // the cipher name; surface Node's ERR_CRYPTO_UNKNOWN_CIPHER instead. if ( ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e) && StringPrototypeStartsWith(e.message, "Unknown cipher") ) { throw new ERR_CRYPTO_UNKNOWN_CIPHER(); } throw e; } if (this._context == 0) { throw new ERR_CRYPTO_UNKNOWN_CIPHER(); } } this._needsBlockCache = !this._isAesWrap && !(cipher == "aes-128-gcm" || cipher == "aes-256-gcm" || cipher == "aes-128-ctr" || cipher == "aes-192-ctr" || cipher == "aes-256-ctr" || cipher == "chacha20" || cipher == "chacha20-poly1305"); this._authTag = undefined; this._autoPadding = true; this._finalized = false; this._decoder = undefined; } ObjectSetPrototypeOf(Cipheriv.prototype, getTransform().prototype); ObjectSetPrototypeOf(Cipheriv, getTransform()); Cipheriv.prototype.final = function ( encoding: string = getDefaultEncoding(), ): Buffer | string { if (this._finalized) { throw new ERR_CRYPTO_INVALID_STATE("final"); } _lazyInitCipherDecoder(this, encoding); if (this._isAesWrap) { this._finalized = true; return encoding === "buffer" ? Buffer.from([]) : this._decoder!.end(); } const bs = this._blockSize; const buf = new FastBuffer(bs); const hasNoBufferedData = TypedArrayPrototypeGetByteLength(this._cache.cache) === 0; const shouldPadEmptyBlock = this._needsBlockCache && this._autoPadding; if (hasNoBufferedData && !shouldPadEmptyBlock) { const maybeTag = op_node_cipheriv_take(this._context); if (maybeTag) this._authTag = Buffer.from(maybeTag); this._finalized = true; return encoding === "buffer" ? Buffer.from([]) : this._decoder!.end(); } if ( !this._autoPadding && TypedArrayPrototypeGetByteLength(this._cache.cache) != bs ) { throw opensslError( "ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH", "wrong final block length", ); } const maybeTag = op_node_cipheriv_final( this._context, this._autoPadding, this._cache.cache, buf, ); if (maybeTag) { this._authTag = Buffer.from(maybeTag); this._finalized = true; return encoding === "buffer" ? Buffer.from([]) : this._decoder!.end(); } this._finalized = true; if (encoding !== "buffer") { return this._decoder!.end(buf); } return buf; }; Cipheriv.prototype.getAuthTag = function (): Buffer { if (!this._authTag) { throw new ERR_CRYPTO_INVALID_STATE("getAuthTag"); } return this._authTag; }; Cipheriv.prototype.setAAD = function ( buffer: ArrayBufferView, _options?: { plaintextLength: number; }, ) { if (this._finalized) { throw new ERR_CRYPTO_INVALID_STATE("setAAD"); } op_node_cipheriv_set_aad(this._context, buffer); return this; }; Cipheriv.prototype.setAutoPadding = function (autoPadding?: boolean) { this._autoPadding = !!autoPadding; return this; }; Cipheriv.prototype.update = function ( data: string | Buffer | ArrayBufferView, inputEncoding?: any, outputEncoding: any = getDefaultEncoding(), ): Buffer | string { if (this._finalized) { throw new ERR_CRYPTO_INVALID_STATE("update"); } validateCipherUpdateData(data); let buf = data; if (typeof data === "string") { buf = Buffer.from(data, inputEncoding); } // Match Node.js/OpenSSL behavior: reject inputs >= INT_MAX bytes if (buf.length >= 2 ** 31 - 1) { throw new Error("Trying to add data in unsupported state"); } _lazyInitCipherDecoder(this, outputEncoding); if (this._isAesWrap) { const output = Buffer.from( op_node_aes_wrap_key( this._aesWrapAlgorithm, this._aesWrapKey, this._aesWrapIv, buf, ), ); if (outputEncoding !== "buffer") { return this._decoder!.write(output); } return output; } let output: Buffer; if (!this._needsBlockCache) { output = Buffer.allocUnsafe(buf.length); op_node_cipheriv_encrypt(this._context, buf, output); if (outputEncoding !== "buffer") { return this._decoder!.write(output); } return output; } this._cache.add(buf); const input = this._cache.get(); if (input === null) { output = Buffer.alloc(0); } else { output = Buffer.allocUnsafe(input.length); op_node_cipheriv_encrypt(this._context, input, output); } if (outputEncoding !== "buffer") { return this._decoder!.write(output); } return output; }; function _lazyInitCipherDecoder(self: any, encoding: string) { if (encoding === "buffer") { return; } const normalizedEncoding = normalizeEncoding(encoding); self._decoder ||= new StringDecoder(normalizedEncoding); if (self._decoder.encoding !== normalizedEncoding) { if (normalizedEncoding === undefined) { throw new ERR_UNKNOWN_ENCODING(encoding); } assert(false, "Cannot change encoding"); } } /** Caches data and output the chunk of multiple of 16. * Used by CBC, ECB modes of block ciphers */ class BlockModeCache { cache: Uint8Array; blockSize: number; // The last chunk can be padded when decrypting. #lastChunkIsNonZero: boolean; constructor(lastChunkIsNotZero = false, blockSize = 16) { this.cache = new Uint8Array(0); this.blockSize = blockSize; this.#lastChunkIsNonZero = lastChunkIsNotZero; } add(data: Uint8Array) { const cache = this.cache; this.cache = new Uint8Array(cache.length + data.length); this.cache.set(cache); this.cache.set(data, cache.length); } /** Gets the chunk of the length of largest multiple of blockSize. * Used for preparing data for encryption/decryption */ get(): Uint8Array | null { const bs = this.blockSize; let len = this.cache.length; if (this.#lastChunkIsNonZero) { // Reduces the available chunk length by 1 to keep the last chunk len -= 1; } if (len < bs) { return null; } len = MathFloor(len / bs) * bs; const out = this.cache.subarray(0, len); this.cache = this.cache.subarray(len); return out; } set lastChunkIsNonZero(value: boolean) { this.#lastChunkIsNonZero = value; } } function getBlockSize(cipher: string): number { if (StringPrototypeStartsWith(cipher, "des")) { return 8; } return 16; } function getUIntOption(options, key) { let value; if (options && (value = options[key]) != null) { if (value >>> 0 !== value) { throw new ERR_INVALID_ARG_VALUE(`options.${key}`, value); } return value; } return -1; } function Decipheriv( cipher: string, key: any, iv: any, options?: any, ) { if (!ObjectPrototypeIsPrototypeOf(Decipheriv.prototype, this)) { return new Decipheriv(cipher, key, iv, options); } const authTagLength = getUIntOption(options, "authTagLength"); FunctionPrototypeCall(getTransform(), this, { transform(chunk, encoding, cb) { // deno-lint-ignore deno-internal/prefer-primordials -- `this` is a Transform stream this.push(this.update(chunk, encoding)); cb(); }, final(cb) { // deno-lint-ignore deno-internal/prefer-primordials -- `this` is a Transform stream this.push(this.final()); cb(); }, ...options, }); this._autoPadding = true; this._blockSize = getBlockSize(cipher); this._cache = new BlockModeCache(this._autoPadding, this._blockSize); this._isAesWrap = isAesWrap(cipher); if (this._isAesWrap) { this._aesWrapAlgorithm = cipher; this._aesWrapKey = toU8(key); this._aesWrapIv = toU8(iv); this._context = 1; // non-zero sentinel; not used for wrap ops } else { try { this._context = op_node_create_decipheriv( cipher, toU8(key), toU8(iv), authTagLength, ); } catch (e) { // The op reports an unrecognized algorithm as a TypeError that includes // the cipher name; surface Node's ERR_CRYPTO_UNKNOWN_CIPHER instead. if ( ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e) && StringPrototypeStartsWith(e.message, "Unknown cipher") ) { throw new ERR_CRYPTO_UNKNOWN_CIPHER(); } throw e; } if (this._context == 0) { throw new ERR_CRYPTO_UNKNOWN_CIPHER(); } } this._needsBlockCache = !this._isAesWrap && !(cipher == "aes-128-gcm" || cipher == "aes-256-gcm" || cipher == "aes-128-ctr" || cipher == "aes-192-ctr" || cipher == "aes-256-ctr" || cipher == "chacha20" || cipher == "chacha20-poly1305"); this._isGcmMode = cipher == "aes-128-gcm" || cipher == "aes-192-gcm" || cipher == "aes-256-gcm"; this._authTagLength = authTagLength; this._authTag = undefined; this._finalized = false; this._decoder = undefined; } ObjectSetPrototypeOf(Decipheriv.prototype, getTransform().prototype); ObjectSetPrototypeOf(Decipheriv, getTransform()); Decipheriv.prototype.final = function ( encoding: string = getDefaultEncoding(), ): Buffer | string { if (this._finalized) { throw new ERR_CRYPTO_INVALID_STATE("final"); } _lazyInitDecipherDecoder(this, encoding); if (this._isAesWrap) { this._finalized = true; return encoding === "buffer" ? Buffer.from([]) : this._decoder!.end(); } const bs = this._blockSize; let buf = new FastBuffer(bs); op_node_decipheriv_final( this._context, this._autoPadding, this._cache.cache, buf, this._authTag || NO_TAG, ); if ( !this._needsBlockCache || TypedArrayPrototypeGetByteLength(this._cache.cache) === 0 ) { this._finalized = true; return encoding === "buffer" ? Buffer.from([]) : this._decoder!.end(); } if (TypedArrayPrototypeGetByteLength(this._cache.cache) != bs) { throw opensslError( "ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH", "wrong final block length", ); } if (this._autoPadding) { const padLen = TypedArrayPrototypeAt(buf, -1); if (padLen === 0 || padLen > bs) { throw opensslError( "ERR_OSSL_EVP_BAD_DECRYPT", "bad decrypt", ); } buf = buf.subarray(0, bs - padLen); // Padded in Pkcs7 mode } this._finalized = true; if (encoding !== "buffer") { return this._decoder!.end(buf); } return buf; }; Decipheriv.prototype.setAAD = function ( buffer: ArrayBufferView, _options?: { plaintextLength: number; }, ) { if (this._finalized) { throw new ERR_CRYPTO_INVALID_STATE("setAAD"); } op_node_decipheriv_set_aad(this._context, buffer); return this; }; Decipheriv.prototype.setAuthTag = function ( buffer: any, _encoding?: string, ) { if (this._authTag) { throw new ERR_CRYPTO_INVALID_STATE("setAuthTag"); } // When no explicit `authTagLength` was given at decipher creation time, a // GCM authentication tag must be the full 128 bits (16 bytes); shorter tags // are only accepted when `authTagLength` is set. This used to be the DEP0182 // deprecation warning and is now a hard error (matching Node.js). // deno-lint-ignore deno-internal/prefer-primordials -- `buffer` may be Buffer/TypedArray/DataView const tagByteLength = buffer.byteLength; if ( this._isGcmMode && this._authTagLength === -1 && tagByteLength !== 16 ) { throw new TypeError( `Invalid authentication tag length: ${tagByteLength}`, ); } // deno-lint-ignore deno-internal/prefer-primordials -- `buffer` may be Buffer/TypedArray/DataView op_node_decipheriv_auth_tag(this._context, buffer.byteLength); this._authTag = buffer; return this; }; Decipheriv.prototype.setAutoPadding = function (autoPadding?: boolean) { this._autoPadding = Boolean(autoPadding); this._cache.lastChunkIsNonZero = this._autoPadding; return this; }; Decipheriv.prototype.update = function ( data: string | Buffer | ArrayBufferView, inputEncoding?: any, outputEncoding: any = getDefaultEncoding(), ): Buffer | string { if (this._finalized) { throw new ERR_CRYPTO_INVALID_STATE("update"); } validateCipherUpdateData(data); let buf = data; if (typeof data === "string") { buf = Buffer.from(data, inputEncoding); } // Match Node.js/OpenSSL behavior: reject inputs >= INT_MAX bytes if (buf.length >= 2 ** 31 - 1) { throw new Error("Trying to add data in unsupported state"); } _lazyInitDecipherDecoder(this, outputEncoding); if (this._isAesWrap) { const output = Buffer.from( op_node_aes_unwrap_key( this._aesWrapAlgorithm, this._aesWrapKey, this._aesWrapIv, buf, ), ); if (outputEncoding !== "buffer") { return this._decoder!.write(output); } return output; } let output; if (!this._needsBlockCache) { output = Buffer.allocUnsafe(buf.length); op_node_decipheriv_decrypt(this._context, buf, output); if (outputEncoding !== "buffer") { return this._decoder!.write(output); } return output; } this._cache.add(buf); const input = this._cache.get(); if (input === null) { output = Buffer.alloc(0); } else { output = new FastBuffer(input.length); op_node_decipheriv_decrypt(this._context, input, output); } if (outputEncoding !== "buffer") { return this._decoder!.write(output); } return output; }; function _lazyInitDecipherDecoder(self: any, encoding: string) { if (encoding === "buffer") { return; } const normalizedEncoding = normalizeEncoding(encoding); self._decoder ||= new StringDecoder(normalizedEncoding); if (self._decoder.encoding !== normalizedEncoding) { if (normalizedEncoding === undefined) { throw new ERR_UNKNOWN_ENCODING(encoding); } assert(false, "Cannot change encoding"); } } const ENCRYPT_UNSUPPORTED_KEY_TYPES = new SafeSet([ "rsa-pss", "dsa", "ec", "ed25519", "ed448", "x25519", "x448", ]); function checkUnsupportedKeyType(key) { const keyType = isKeyObject(key) ? key.asymmetricKeyType : key?.key?.asymmetricKeyType; if (keyType && SetPrototypeHas(ENCRYPT_UNSUPPORTED_KEY_TYPES, keyType)) { throw new Error("operation not supported for this keytype"); } } const WEBCRYPTO_SHA_HYPHEN_RE = new SafeRegExp("^(sha)-(?!3-)"); function normalizeOaepHash(hash: unknown): string | undefined { if (hash === undefined) return undefined; if (typeof hash !== "string") { throw new ERR_INVALID_ARG_TYPE("oaepHash", "string", hash); } if (!hash) return undefined; // Normalize to lowercase and strip WebCrypto-style hyphens // (e.g. "SHA-256" -> "sha256") but keep sha3/sha512 sub-variants // (e.g. "sha3-256", "sha512-224") intact. const normalized = StringPrototypeReplace( StringPrototypeToLowerCase(hash), WEBCRYPTO_SHA_HYPHEN_RE, "$1", ); // Validate before key parsing so unknown hash throws ERR_OSSL_EVP_INVALID_DIGEST // even when the key itself cannot be parsed as a private key. op_node_validate_oaep_hash(normalized); return normalized; } function bufferEncodingFrom(keyOptions: unknown): string | undefined { return (keyOptions as { encoding?: string } | null)?.encoding; } function validateOaepLabel( label: unknown, ): ArrayBufferView | ArrayBuffer | undefined { if (label === undefined) return undefined; if (!isArrayBufferView(label) && !isAnyArrayBuffer(label)) { throw new ERR_INVALID_ARG_TYPE( "oaepLabel", ["Buffer", "TypedArray", "DataView"], label, ); } return label as ArrayBufferView | ArrayBuffer; } function privateEncrypt( privateKey: ArrayBufferView | string | KeyObject, buffer: ArrayBufferView, ): Buffer { checkUnsupportedKeyType(privateKey); const { data } = prepareKey(privateKey); const padding = privateKey.padding || 1; const oaepHash = normalizeOaepHash(privateKey.oaepHash); const oaepLabel = validateOaepLabel(privateKey.oaepLabel); buffer = getArrayBufferOrView( buffer, "buffer", bufferEncodingFrom(privateKey), ); return Buffer.from( op_node_private_encrypt(data, buffer, padding, oaepHash, oaepLabel), ); } function privateDecrypt( privateKey: ArrayBufferView | string | KeyObject, buffer: ArrayBufferView, ): Buffer { checkUnsupportedKeyType(privateKey); const { data } = prepareKey(privateKey); // Node.js defaults privateDecrypt to RSA_PKCS1_OAEP_PADDING (4) const padding = privateKey.padding || 4; const oaepHash = normalizeOaepHash(privateKey.oaepHash); const oaepLabel = validateOaepLabel(privateKey.oaepLabel); buffer = getArrayBufferOrView( buffer, "buffer", bufferEncodingFrom(privateKey), ); return Buffer.from( op_node_private_decrypt(data, buffer, padding, oaepHash, oaepLabel), ); } function publicEncrypt( publicKey: ArrayBufferView | string | KeyObject, buffer: ArrayBufferView, ): Buffer { checkUnsupportedKeyType(publicKey); const { data } = prepareKey(publicKey); // Node.js defaults publicEncrypt to RSA_PKCS1_OAEP_PADDING (4) const padding = publicKey.padding || 4; const oaepHash = normalizeOaepHash(publicKey.oaepHash); const oaepLabel = validateOaepLabel(publicKey.oaepLabel); buffer = getArrayBufferOrView( buffer, "buffer", bufferEncodingFrom(publicKey), ); return Buffer.from( op_node_public_encrypt(data, buffer, padding, oaepHash, oaepLabel), ); } function prepareKey(key) { // TODO(@littledivy): handle these cases // - web CryptoKey if (isStringOrBuffer(key)) { return { data: getArrayBufferOrView(key, "key") }; } else if (isKeyObject(key) && key.type === "public") { const data = key.export({ type: "spki", format: "pem" }); return { data: getArrayBufferOrView(data, "key") }; } else if (isKeyObject(key) && key.type === "private") { const data = key.export({ type: "pkcs8", format: "pem" }); return { data: getArrayBufferOrView(data, "key") }; } else if (typeof key == "object") { const { key: data, encoding, passphrase, format, type } = key; if (isKeyObject(data)) { return prepareKey(data); } if (format === "jwk") { // Build a KeyObject from the JWK and export it as PEM so the // downstream op can consume it via the existing PEM parsing path. const isPrivate = typeof data === "object" && data !== null && typeof (data as { d?: unknown }).d === "string"; const keyObject = isPrivate ? createPrivateKey({ key: data, format: "jwk" }) : createPublicKey({ key: data, format: "jwk" }); return prepareKey(keyObject); } if (!isStringOrBuffer(data)) { throw new TypeError("Invalid key type"); } // If a passphrase is supplied with raw key material, decrypt the key via // the native key handle and re-export as unencrypted PKCS#8 PEM so the // downstream RSA ops can parse it. if (passphrase != null) { const keyFormat = format ?? (typeof data === "string" ? "pem" : "der"); const keyData = getArrayBufferOrView(data, "key", encoding); const passphraseData = getArrayBufferOrView(passphrase, "passphrase"); const handle = op_node_create_private_key( keyData, keyFormat, type ?? "", passphraseData, ); const pem = op_node_export_private_key_pem( handle, "pkcs8", null, null, ); return { data: getArrayBufferOrView(pem, "key") }; } return { data: getArrayBufferOrView(data, "key", encoding) }; } throw new TypeError("Invalid key type"); } function publicDecrypt( publicKey: ArrayBufferView | string | KeyObject, buffer: ArrayBufferView, ): Buffer { checkUnsupportedKeyType(publicKey); const { data } = prepareKey(publicKey); const padding = publicKey.padding || 1; buffer = getArrayBufferOrView( buffer, "buffer", bufferEncodingFrom(publicKey), ); return Buffer.from(op_node_public_decrypt(data, buffer, padding)); } return { isStringOrBuffer, Cipheriv, Decipheriv, privateEncrypt, privateDecrypt, publicEncrypt, publicDecrypt, prepareKey, default: { privateDecrypt, privateEncrypt, publicDecrypt, publicEncrypt, Cipheriv, Decipheriv, prepareKey, }, }; })();