From 21c23df1c5d7e2be2b6d1874bf536a7b4236dbb2 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 27 Jun 2023 10:57:10 -0700 Subject: [PATCH] Temporarily mark createPrivateKey/createPublicKey as unimplemented Implementing these cleanly will require a larger refactoring of the current key import logic supporting Web Crypto as the currently design makes a lot of assumptions that Web Crypto semantics are being used. For now we'll just mark these as unimplemented and revisit in a later iteration. --- src/node/internal/crypto_keys.ts | 196 +++++++++++++++++-------------- 1 file changed, 106 insertions(+), 90 deletions(-) diff --git a/src/node/internal/crypto_keys.ts b/src/node/internal/crypto_keys.ts index a87126752611..9c11a6c09846 100644 --- a/src/node/internal/crypto_keys.ts +++ b/src/node/internal/crypto_keys.ts @@ -30,7 +30,6 @@ import { Buffer } from 'node-internal:internal_buffer'; import { CryptoKey, - JsonWebKey, KeyData, KeyObjectType, KeyExportResult, @@ -44,8 +43,10 @@ import { CreateAsymmetricKeyOptions, GenerateKeyOptions, GenerateKeyPairOptions, - InnerCreateAsymmetricKeyOptions, InnerExportOptions, + // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. + // JsonWebKey, + // InnerCreateAsymmetricKeyOptions, default as cryptoImpl } from 'node-internal:crypto'; @@ -57,15 +58,17 @@ import { import { isAnyArrayBuffer, isArrayBuffer, - isSharedArrayBuffer, isArrayBufferView, isUint8Array, + // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. + // isSharedArrayBuffer, } from 'node-internal:internal_types'; import { ERR_INVALID_ARG_TYPE, - ERR_INVALID_ARG_VALUE, ERR_METHOD_NOT_IMPLEMENTED, + // TODO(soon): Uncomment these once createPrivateKey/createPublicKey are implemented. + // ERR_INVALID_ARG_VALUE, } from 'node-internal:internal_errors'; import { @@ -229,98 +232,110 @@ export function createSecretKey(key: KeyData, encoding?: string) : SecretKeyObje return KeyObject.from(cryptoImpl.createSecretKey(key)) as SecretKeyObject; } -const kPrivateKey = Symbol('privateKey'); -const kPublicKey = Symbol('publicKey'); - -function validateAsymmetricKeyOptions( - key: CreateAsymmetricKeyOptions | KeyData | CryptoKey | KeyObject, - type: Symbol) { - validateKeyData(key, 'key', { allowObject: true }); - let inner : InnerCreateAsymmetricKeyOptions = {}; - inner.format = 'pem'; - if (typeof key === 'string') { - inner.key = Buffer.from(key as string); - } else if (isArrayBufferView(key)) { - inner.key = key as ArrayBufferView; - } else if (isArrayBuffer(key)) { - inner.key = key as ArrayBuffer; - } else if (isSharedArrayBuffer(key)) { - inner.key = key as SharedArrayBuffer; - } else if (type === kPublicKey && key instanceof KeyObject) { - // Covers deriving public key from a private key. - if (key.type !== 'private') { - throw new ERR_INVALID_ARG_VALUE('key', key, 'must be a private key'); - } - inner.key = (key as KeyObject)[kHandle]; - } else if (type === kPublicKey && key instanceof CryptoKey) { - // Covers deriving public key from a private key. - if ((key as CryptoKey).type !== 'private') { - throw new ERR_INVALID_ARG_VALUE('key', key, 'must be a private key'); - } - inner.key = key as CryptoKey; - } else { - const options = key as CreateAsymmetricKeyOptions; - if (typeof options.key === 'string') { - inner.key = Buffer.from(options.key as string, options.encoding); - } else if (isArrayBufferView(options.key)) { - inner.key = options.key as ArrayBufferView; - } else if (isArrayBuffer(options.key)) { - inner.key = options.key as ArrayBuffer; - } else if (isSharedArrayBuffer(options.key)) { - inner.key = options.key as SharedArrayBuffer; - } else if (type === kPublicKey && key instanceof KeyObject) { - if ((options.key as KeyObject).type !== 'private') { - throw new ERR_INVALID_ARG_VALUE('options.key', options.key, 'must be a private key'); - } - inner.key = (options.key as KeyObject)[kHandle]; - } else if (type === kPublicKey && key instanceof CryptoKey) { - if ((options.key as CryptoKey).type !== 'private') { - throw new ERR_INVALID_ARG_VALUE('options.key', options.key, 'must be a private key'); - } - inner.key = options.key as CryptoKey; - } else { - inner.key = key as JsonWebKey; - } - validateKeyData(inner.key, 'options.key', { allowObject: true }); - - if (options.format !== undefined) { - validateString(options.format, 'options.format'); - inner.format = options.format; - } - if (options.type !== undefined) { - validateString(options.type, 'options.type'); - inner.type = options.type; - } - if (options.passphrase !== undefined) { - if (typeof options.passphrase === 'string') { - inner.passphrase = Buffer.from(options.passphrase, options.encoding); - } else { - if (!isUint8Array(options.passphrase)) { - throw new ERR_INVALID_ARG_TYPE('options.passphrase', [ - 'string', 'Uint8Array' - ], options.passphrase); - } - inner.passphrase = options.passphrase; - } - if (inner.passphrase.byteLength > 1024) { - throw new ERR_INVALID_ARG_VALUE('options.passphrase', options.passphrase.length, '<= 1024'); - } - } - } - return inner; -} +// TODO(soon): Fully implement createPrivateKey/createPublicKey. These are the +// equivalent of the WebCrypto API's importKey() method but operate synchronously +// and support a range of options not currently supported by WebCrypto. Implementing +// these will require either duplicating or significantly refactoring the current +// import key logic that supports Web Crypto now as the import logic is spread out +// over several locations and makes a number of assumptions that Web Crypto is being +// used. +// +// For now, users can use Web Crypto to import a CryptoKey then convert that into +// a KeyObject using KeyObject.from(). +// +// const kPrivateKey = Symbol('privateKey'); +// const kPublicKey = Symbol('publicKey'); + +// function validateAsymmetricKeyOptions( +// key: CreateAsymmetricKeyOptions | KeyData | CryptoKey | KeyObject, +// type: Symbol) { +// validateKeyData(key, 'key', { allowObject: true }); +// let inner : InnerCreateAsymmetricKeyOptions = {}; +// inner.format = 'pem'; +// if (typeof key === 'string') { +// inner.key = Buffer.from(key as string); +// } else if (isArrayBufferView(key)) { +// inner.key = key as ArrayBufferView; +// } else if (isArrayBuffer(key)) { +// inner.key = key as ArrayBuffer; +// } else if (isSharedArrayBuffer(key)) { +// inner.key = key as SharedArrayBuffer; +// } else if (type === kPublicKey && key instanceof KeyObject) { +// // Covers deriving public key from a private key. +// if (key.type !== 'private') { +// throw new ERR_INVALID_ARG_VALUE('key', key, 'must be a private key'); +// } +// inner.key = (key as KeyObject)[kHandle]; +// } else if (type === kPublicKey && key instanceof CryptoKey) { +// // Covers deriving public key from a private key. +// if ((key as CryptoKey).type !== 'private') { +// throw new ERR_INVALID_ARG_VALUE('key', key, 'must be a private key'); +// } +// inner.key = key as CryptoKey; +// } else { +// const options = key as CreateAsymmetricKeyOptions; +// if (typeof options.key === 'string') { +// inner.key = Buffer.from(options.key as string, options.encoding); +// } else if (isArrayBufferView(options.key)) { +// inner.key = options.key as ArrayBufferView; +// } else if (isArrayBuffer(options.key)) { +// inner.key = options.key as ArrayBuffer; +// } else if (isSharedArrayBuffer(options.key)) { +// inner.key = options.key as SharedArrayBuffer; +// } else if (type === kPublicKey && key instanceof KeyObject) { +// if ((options.key as KeyObject).type !== 'private') { +// throw new ERR_INVALID_ARG_VALUE('options.key', options.key, 'must be a private key'); +// } +// inner.key = (options.key as KeyObject)[kHandle]; +// } else if (type === kPublicKey && key instanceof CryptoKey) { +// if ((options.key as CryptoKey).type !== 'private') { +// throw new ERR_INVALID_ARG_VALUE('options.key', options.key, 'must be a private key'); +// } +// inner.key = options.key as CryptoKey; +// } else { +// inner.key = key as JsonWebKey; +// } +// validateKeyData(inner.key, 'options.key', { allowObject: true }); + +// if (options.format !== undefined) { +// validateString(options.format, 'options.format'); +// inner.format = options.format; +// } +// if (options.type !== undefined) { +// validateString(options.type, 'options.type'); +// inner.type = options.type; +// } +// if (options.passphrase !== undefined) { +// if (typeof options.passphrase === 'string') { +// inner.passphrase = Buffer.from(options.passphrase, options.encoding); +// } else { +// if (!isUint8Array(options.passphrase)) { +// throw new ERR_INVALID_ARG_TYPE('options.passphrase', [ +// 'string', 'Uint8Array' +// ], options.passphrase); +// } +// inner.passphrase = options.passphrase; +// } +// if (inner.passphrase.byteLength > 1024) { +// throw new ERR_INVALID_ARG_VALUE('options.passphrase', options.passphrase.length, '<= 1024'); +// } +// } +// } +// return inner; +// } export function createPrivateKey(key: string) : PrivateKeyObject; export function createPrivateKey(key: ArrayBuffer | ArrayBufferView) : PrivateKeyObject; export function createPrivateKey(key: CreateAsymmetricKeyOptions) : PrivateKeyObject; -export function createPrivateKey(key: CreateAsymmetricKeyOptions | KeyData) : PrivateKeyObject { +export function createPrivateKey(_key: CreateAsymmetricKeyOptions | KeyData) : PrivateKeyObject { // The options here are fairly complex. The key data can be a string, // ArrayBuffer, or ArrayBufferView. The first argument can be one of // these or an object with a key property that is one of these. If the // key data is a string, then it will be decoded using an encoding // (defaults to UTF8). - return KeyObject.from(cryptoImpl.createPrivateKey( - validateAsymmetricKeyOptions(key, kPrivateKey))) as PrivateKeyObject; + throw new ERR_METHOD_NOT_IMPLEMENTED('crypto.createPrivateKey'); + // return KeyObject.from(cryptoImpl.createPrivateKey( + // validateAsymmetricKeyOptions(key, kPrivateKey))) as PrivateKeyObject; } export function createPublicKey(key: string) : PublicKeyObject; @@ -330,7 +345,7 @@ export function createPublicKey(key: ArrayBufferView) : PublicKeyObject; export function createPublicKey(key: KeyObject) : PublicKeyObject; export function createPublicKey(key: CryptoKey) : PublicKeyObject; export function createPublicKey(key: CreateAsymmetricKeyOptions) : PublicKeyObject; -export function createPublicKey(key: CreateAsymmetricKeyOptions | KeyData | CryptoKey | KeyObject) +export function createPublicKey(_key: CreateAsymmetricKeyOptions | KeyData | CryptoKey | KeyObject) : PublicKeyObject { // The options here are a bit complicated. The key material itself can // either be a string, ArrayBuffer, or ArrayBufferView. It is also @@ -340,8 +355,9 @@ export function createPublicKey(key: CreateAsymmetricKeyOptions | KeyData | Cryp // it will be decoded using an encoding (defaults to UTF8). If a // CryptoKey or KeyObject is passed, it will be used to derived the // public key. - return KeyObject.from(cryptoImpl.createPublicKey( - validateAsymmetricKeyOptions(key, kPublicKey))) as PublicKeyObject; + throw new ERR_METHOD_NOT_IMPLEMENTED('crypto.createPublicKey'); + // return KeyObject.from(cryptoImpl.createPublicKey( + // validateAsymmetricKeyOptions(key, kPublicKey))) as PublicKeyObject; } // ======================================================================================