From f0a659d6be149a97dbf664774e4a0d11abc90e26 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Thu, 26 Oct 2023 12:35:13 +0530 Subject: [PATCH 01/13] fix(node): implement createPrivateKey (PEM) --- ext/node/ops/crypto/mod.rs | 35 +++++++++++ ext/node/polyfills/internal/crypto/cipher.ts | 3 +- ext/node/polyfills/internal/crypto/keys.ts | 63 +++++++++++++++----- test.mjs | 12 ++++ 4 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 test.mjs diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 372f7dcb50ef90..bad3535e05a406 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -1182,3 +1182,38 @@ pub async fn op_node_gen_prime_async( ) -> Result { Ok(spawn_blocking(move || gen_prime(size)).await?) } + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +pub enum AsymmetricKeyDetails { + Rsa { + modulus_length: usize, + public_exponent: usize, + }, + RsaPss { + modulus_length: usize, + public_exponent: usize, + hash_algorithm: String, + mgf1_hash_algorithm: String, + salt_length: usize, + }, + Dsa { + divisor_length: usize, + modulus_length: usize, + }, + Ec { + named_curve: String, + } +} + +#[op2] +#[serde] +pub fn op_node_create_private_key( + #[buffer] privkey: &[u8] +) -> Result { + // We only support PEM for now. + let pkey = pkcs8::PrivateKeyInfo::from_pkcs8_pem(std::str::from_utf8(privkey).unwrap())?; + + + Ok(()) +} \ No newline at end of file diff --git a/ext/node/polyfills/internal/crypto/cipher.ts b/ext/node/polyfills/internal/crypto/cipher.ts index cf1641326d7d06..f943fa1bce4233 100644 --- a/ext/node/polyfills/internal/crypto/cipher.ts +++ b/ext/node/polyfills/internal/crypto/cipher.ts @@ -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 be85b44a3e7454..d423d5b68e1bbf 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 { prepareKey } from "ext:deno_node/internal/crypto/cipher.ts"; import { ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, ERR_INVALID_ARG_TYPE, @@ -39,6 +40,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 +172,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"); @@ -220,9 +212,14 @@ export interface JsonWebKeyInput { } export function createPrivateKey( - _key: PrivateKeyInput | string | Buffer | JsonWebKeyInput, + key: PrivateKeyInput | string | Buffer | JsonWebKeyInput, ): KeyObject { - notImplemented("crypto.createPrivateKey"); + const { data } = prepareKey(key); + const details = ops.op_node_create_private_key(data); + + const handle = setOwnedKey(copyBuffer(data)); + + return new PrivateKeyObject(handle); } export function createPublicKey( @@ -316,6 +313,44 @@ export class SecretKeyObject extends KeyObject { } } +const kAsymmetricKeyType = Symbol('kAsymmetricKeyType'); +const kAsymmetricKeyDetails = Symbol('kAsymmetricKeyDetails'); + +class AsymmetricKeyObject extends KeyObject { + constructor(type: KeyObjectType, handle: unknown) { + super(type, handle); + } + + get asymmetricKeyType() { + return this[kAsymmetricKeyType] || + (this[kAsymmetricKeyType] = this[kHandle].getAsymmetricKeyType()); + } + + get asymmetricKeyDetails() { + switch (this.asymmetricKeyType) { + case 'rsa': + case 'rsa-pss': + case 'dsa': + case 'ec': + return this[kAsymmetricKeyDetails] || + (this[kAsymmetricKeyDetails] = normalizeKeyDetails( + this[kHandle].keyDetail({}), + )); + default: + return {}; + } +} + +class PrivateKeyObject extends AsymmetricKeyObject { + constructor(handle: unknown) { + super("private", handle); + } + + export(_options: unknown) { + notImplemented("crypto.KeyObject.prototype.asymmetricKeyDetails"); + } +} + export function setOwnedKey(key: Uint8Array): unknown { const handle = {}; KEY_STORE.set(handle, key); diff --git a/test.mjs b/test.mjs new file mode 100644 index 00000000000000..4ead31a42eb190 --- /dev/null +++ b/test.mjs @@ -0,0 +1,12 @@ +import { createPrivateKey } from "node:crypto"; +import { App, Octokit } from "npm:octokit@^2.0.10"; + +const app = new App({ + appId: " ", + privateKey: " " +}); + +const { data } = await app.octokit.request("/app"); + +app.log.warn("ok") +// createPrivateKey();A \ No newline at end of file From 53dd56437ed78b5c46fec6eb79365ecee06b1047 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Thu, 26 Oct 2023 13:33:15 +0530 Subject: [PATCH 02/13] x --- Cargo.lock | 1 + ext/node/Cargo.toml | 1 + ext/node/ops/crypto/mod.rs | 28 ++++++++++++++++++++++++---- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebd6900a6eec36..4a67c6b5dd8759 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1522,6 +1522,7 @@ dependencies = [ "brotli", "bytes", "cbc", + "const-oid", "data-encoding", "deno_core", "deno_fetch", diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml index f88d3a4020ed2c..20b1af1cf5b0a6 100644 --- a/ext/node/Cargo.toml +++ b/ext/node/Cargo.toml @@ -46,6 +46,7 @@ num-bigint-dig = "0.8.2" num-integer = "0.1.45" num-traits = "0.2.14" once_cell.workspace = true +const-oid = "*" p224.workspace = true p256.workspace = true p384.workspace = true diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index bad3535e05a406..409fbbf9ee7101 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -1188,7 +1188,7 @@ pub async fn op_node_gen_prime_async( pub enum AsymmetricKeyDetails { Rsa { modulus_length: usize, - public_exponent: usize, + public_exponent: BigInt, }, RsaPss { modulus_length: usize, @@ -1206,14 +1206,34 @@ pub enum AsymmetricKeyDetails { } } + +use rsa::pkcs1::der::DecodePem; + +use rsa::pkcs8; + +pub const RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1"); + #[op2] #[serde] pub fn op_node_create_private_key( - #[buffer] privkey: &[u8] + #[buffer] privkey: &[u8], ) -> Result { // We only support PEM for now. - let pkey = pkcs8::PrivateKeyInfo::from_pkcs8_pem(std::str::from_utf8(privkey).unwrap())?; + let pk_info = pkcs8::PrivateKeyInfo::from_pem(privkey.to_vec())?; + let alg = pk_info.algorithm.oid; - Ok(()) + if alg == RSA_ENCRYPTION_OID { + use rsa::pkcs1::der::Decode; + let private_key = rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?; + + let modulus_length = private_key.modulus.as_bytes().len() * 8; + return Ok(AsymmetricKeyDetails::Rsa { + modulus_length, + public_exponent: BigInt::from_bytes_be(num_bigint::Sign::Plus, private_key.public_exponent.as_bytes()), + }); + } + + todo!() } \ No newline at end of file From 318899bf242e3fa3fe409d2d23afe45c360d3b5d Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sat, 4 Nov 2023 16:57:54 +0530 Subject: [PATCH 03/13] fixes --- ext/node/Cargo.toml | 2 +- ext/node/lib.rs | 1 + ext/node/ops/crypto/mod.rs | 26 ++++++++++------ ext/node/polyfills/internal/crypto/keys.ts | 36 ++++++++-------------- ext/node/polyfills/internal/crypto/sig.ts | 11 ++++--- test.mjs | 33 ++++++++++++++++++-- 6 files changed, 68 insertions(+), 41 deletions(-) diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml index 08bbf3d84d49da..c88e7474626cd8 100644 --- a/ext/node/Cargo.toml +++ b/ext/node/Cargo.toml @@ -19,6 +19,7 @@ aes.workspace = true brotli.workspace = true bytes.workspace = true cbc.workspace = true +const-oid = "0.9.5" data-encoding.workspace = true deno_core.workspace = true deno_fetch.workspace = true @@ -47,7 +48,6 @@ num-bigint-dig = "0.8.2" num-integer = "0.1.45" num-traits = "0.2.14" once_cell.workspace = true -const-oid = "*" p224.workspace = true p256.workspace = true p384.workspace = true diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 730554f2d84d32..0428981c00f488 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -271,6 +271,7 @@ deno_core::extension!(deno_node, ops::require::op_require_package_imports_resolve

, ops::require::op_require_break_on_next_statement, ops::util::op_node_guess_handle_type, + ops::crypto::op_node_create_private_key, ], esm_entry_point = "ext:deno_node/02_init.js", esm = [ diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 517a811de0ff38..e5198255dc5e78 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -1175,31 +1175,31 @@ pub async fn op_node_gen_prime_async( } #[derive(serde::Serialize)] +#[serde(tag = "type")] #[serde(rename_all = "camelCase")] pub enum AsymmetricKeyDetails { + #[serde(rename = "rsa")] Rsa { modulus_length: usize, public_exponent: BigInt, }, + #[serde(rename = "rsa-pss")] RsaPss { modulus_length: usize, public_exponent: usize, hash_algorithm: String, mgf1_hash_algorithm: String, - salt_length: usize, + salt_length: usize, }, + #[serde(rename = "dsa")] Dsa { divisor_length: usize, modulus_length: usize, }, - Ec { - named_curve: String, - } + #[serde(rename = "ec")] + Ec { named_curve: String }, } - -use rsa::pkcs1::der::DecodePem; - use rsa::pkcs8; pub const RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier = @@ -1211,7 +1211,10 @@ pub fn op_node_create_private_key( #[buffer] privkey: &[u8], ) -> Result { // We only support PEM for now. - let pk_info = pkcs8::PrivateKeyInfo::from_pem(privkey.to_vec())?; + let (label, doc) = + pkcs8::SecretDocument::from_pem(std::str::from_utf8(privkey).unwrap())?; + let pk_info = pkcs8::PrivateKeyInfo::try_from(doc.as_bytes())?; + assert_eq!(label, "PRIVATE KEY"); let alg = pk_info.algorithm.oid; @@ -1222,9 +1225,12 @@ pub fn op_node_create_private_key( let modulus_length = private_key.modulus.as_bytes().len() * 8; return Ok(AsymmetricKeyDetails::Rsa { modulus_length, - public_exponent: BigInt::from_bytes_be(num_bigint::Sign::Plus, private_key.public_exponent.as_bytes()), + public_exponent: BigInt::from_bytes_be( + num_bigint::Sign::Plus, + private_key.public_exponent.as_bytes(), + ), }); } todo!() -} \ No newline at end of file +} diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts index d423d5b68e1bbf..84b131d04ea6be 100644 --- a/ext/node/polyfills/internal/crypto/keys.ts +++ b/ext/node/polyfills/internal/crypto/keys.ts @@ -216,10 +216,8 @@ export function createPrivateKey( ): KeyObject { const { data } = prepareKey(key); const details = ops.op_node_create_private_key(data); - const handle = setOwnedKey(copyBuffer(data)); - - return new PrivateKeyObject(handle); + return new PrivateKeyObject(handle, details); } export function createPublicKey( @@ -313,41 +311,33 @@ export class SecretKeyObject extends KeyObject { } } -const kAsymmetricKeyType = Symbol('kAsymmetricKeyType'); -const kAsymmetricKeyDetails = Symbol('kAsymmetricKeyDetails'); +const kAsymmetricKeyType = Symbol("kAsymmetricKeyType"); +const kAsymmetricKeyDetails = Symbol("kAsymmetricKeyDetails"); class AsymmetricKeyObject extends KeyObject { - constructor(type: KeyObjectType, handle: unknown) { + constructor(type: KeyObjectType, handle: unknown, details: unknown) { super(type, handle); + console.log(details); + this[kAsymmetricKeyType] = details.type; + this[kAsymmetricKeyDetails] = details; } get asymmetricKeyType() { - return this[kAsymmetricKeyType] || - (this[kAsymmetricKeyType] = this[kHandle].getAsymmetricKeyType()); + return this[kAsymmetricKeyType]; } get asymmetricKeyDetails() { - switch (this.asymmetricKeyType) { - case 'rsa': - case 'rsa-pss': - case 'dsa': - case 'ec': - return this[kAsymmetricKeyDetails] || - (this[kAsymmetricKeyDetails] = normalizeKeyDetails( - this[kHandle].keyDetail({}), - )); - default: - return {}; - } + return this[kAsymmetricKeyDetails]; + } } class PrivateKeyObject extends AsymmetricKeyObject { - constructor(handle: unknown) { - super("private", handle); + constructor(handle: unknown, details: unknown) { + super("private", handle, details); } export(_options: unknown) { - notImplemented("crypto.KeyObject.prototype.asymmetricKeyDetails"); + notImplemented("crypto.PrivateKeyObject.prototype.export"); } } diff --git a/ext/node/polyfills/internal/crypto/sig.ts b/ext/node/polyfills/internal/crypto/sig.ts index ebbd11dc6ca1dc..c5eb34fae3b90f 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(), diff --git a/test.mjs b/test.mjs index 4ead31a42eb190..21fc878debf043 100644 --- a/test.mjs +++ b/test.mjs @@ -3,10 +3,37 @@ import { App, Octokit } from "npm:octokit@^2.0.10"; const app = new App({ appId: " ", - privateKey: " " + privateKey: `-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDYKBqT674QjFgP +LciOxf8UNtfIligtwGc+RjuNRdzT2z7sduGPqxfW7y6MYm/tP92GjUKNf2/XzLkI +Ay5pPtHKv21YTAH4GOFqNJL3FzYVJtf8zZmvFhXY2BVIhu6JFkaFCBYC4+Is5nMM +kP12FZvf6LbTTVQVMRV5wyRXP1gzQ16fHE9c115mhzJSVkohtqHw5mFfEV/I7DEB +QRTn+hvv5r4gGc7qn9gewwmlOh+6ow1lc7WNWNn7kigsW9hgLGsGZvkaUge0jOLs +QPzEWSdzmiOnpMxYLK1XjC73G3+0OHUjtRdG9q3cr7/yqKO5uI0Ays1q40t2UZrH +rMBeFSi/AgMBAAECggEAE7NMANFKiE2SNQfyMHkBL4F0FzcAQHM5taZHBTAp2TEx +QfHvyt1IFfHEp0zNcK0SbpHvT+AefGePMZjAoRz1l+nseFCtGUSDPt+9yUFXT4Qz +yTmf2SJFKXdAMVUC5oGeOb+r6eWFFpyGPc31G88KXtTh3M4+bJQFpgxQApemXT2K +vvkUppWr/LKIrLQ9TboBAWOOMtuZ0+nDbCzFwdRvQ1itR/Jbq4swt4+PTXKkWrHN +gXoxCoMXaS/QW4BxzlnCAFelEvguF95VKPFgzf6AvHp7mun4tHYgePxugsG4xpRR +U3fCBIqHp8LunG8TpCIY4jeUE4vfNgxWgJ/E+oSOWQKBgQDundzft515Ul2k+wb2 +HaQbaVafYyDmwK/Ji8tthFVJqYPo7eWFbIsedAEGUBzxYd8WRJS59/jyV/MQ3mGS +Y2leCOVo/oGIxqugJNQl0NSnUYleXeweTWMeUhbbMPGutMHLe9hGByzOBwE4G1Oj +Yb8bu41WMzT9T1YBm8cuBQS02wKBgQDn5145sxlMDezj0kcOU+gQLXJfsIPhVIsf +aiLlH78BLDOTH3J+INMYnI869r1bCOlUjNjf3bdBgPA+YQQIPExmhQARAPk1riEp +x7O9egpcxlYzE7yNtR5LeEh5kW+nlSr6EcPPONJlHYgyv9DGxjhnA3lI93rBcqYy +0xSFF41O7QKBgQCiW2deEWFkm1Z8WxFxhNmUjSgTay+H0rPJPwU7jz84z86hPr1c ++23tWqEX2orW8vEIBcHsh30r6AvK/oUFRf77rLHrrsAUgJlmbair0lvfPOtq+h0e +wSkgCFrk6XiIlxUFj06o11j1Fm8N7goKsQeHpyWT8WOst76deZEdDu0U4QKBgEs/ +HqrYO0AbUJ9HrriubyE4reDwtIob1ZyW4sW3vFFUF1QIoyzb18Mnoa3/O8fbJ2LA +5OoW1gySGuIStq05a4zkYPYje7l4S9hzrRWxEMWzsWqXX9oXR8IzQEj58OHOnAhS +VVfa1yHqKDRXWxX0YX7DeMo9Sv6UBet95C2fS8GtAoGALvUAEM/LEj/NY+J0542F ++b8FyXtosQ1mSKBV03JmmglDfQW/+O0Illuy8CmfIuqftLwHyc15u5cAIDd5a8jm +S8l+7/KYETXYGCA1mwB/Dr/LJwbVEQ/mw1ne6FrJ4MORd/2GWuvzrqTKrwRcJ+O9 +mZ3aPB+XECOydno9s4rsxII= +-----END PRIVATE KEY----- +`, }); const { data } = await app.octokit.request("/app"); -app.log.warn("ok") -// createPrivateKey();A \ No newline at end of file +app.log.warn("ok"); From 12125eed37da5cb5b03f2e143db6eaaab0b71f39 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sat, 4 Nov 2023 22:22:52 +0530 Subject: [PATCH 04/13] rsa pss --- ext/node/ops/crypto/mod.rs | 226 +++++++++++++++++++++++++++++++++---- 1 file changed, 204 insertions(+), 22 deletions(-) diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index e5198255dc5e78..4ae90f26042d82 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -17,6 +17,10 @@ use rand::distributions::Distribution; use rand::distributions::Uniform; use rand::thread_rng; use rand::Rng; +use rsa::pkcs8::der::asn1; +use rsa::pkcs8::der::Decode; +use rsa::pkcs8::der::Encode; +use rsa::pkcs8::der::Reader; use std::future::Future; use std::rc::Rc; @@ -1186,10 +1190,9 @@ pub enum AsymmetricKeyDetails { #[serde(rename = "rsa-pss")] RsaPss { modulus_length: usize, - public_exponent: usize, + public_exponent: BigInt, hash_algorithm: String, - mgf1_hash_algorithm: String, - salt_length: usize, + salt_length: u32, }, #[serde(rename = "dsa")] Dsa { @@ -1202,35 +1205,214 @@ pub enum AsymmetricKeyDetails { use rsa::pkcs8; +use once_cell::sync::Lazy; +const ID_SHA1_OID: rsa::pkcs8::ObjectIdentifier = + rsa::pkcs8::ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); +const ID_MFG1: rsa::pkcs8::ObjectIdentifier = + rsa::pkcs8::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8"); + +// Default HashAlgorithm for RSASSA-PSS-params (sha1) +// +// sha1 HashAlgorithm ::= { +// algorithm id-sha1, +// parameters SHA1Parameters : NULL +// } +// +// SHA1Parameters ::= NULL +static SHA1_HASH_ALGORITHM: Lazy> = Lazy::new(|| + rsa::pkcs8::AlgorithmIdentifierRef { + // id-sha1 + oid: ID_SHA1_OID, + // NULL + parameters: Some(asn1::AnyRef::from(asn1::Null)), + }); + +// TODO(@littledivy): `pkcs8` should provide AlgorithmIdentifier to Any conversion. +static ENCODED_SHA1_HASH_ALGORITHM: Lazy> = + Lazy::new(|| SHA1_HASH_ALGORITHM.to_der().unwrap()); + +// Default MaskGenAlgrithm for RSASSA-PSS-params (mgf1SHA1) +// +// mgf1SHA1 MaskGenAlgorithm ::= { +// algorithm id-mgf1, +// parameters HashAlgorithm : sha1 +// } +static MGF1_SHA1_MASK_ALGORITHM: Lazy< + rsa::pkcs8::AlgorithmIdentifierRef<'static>, +> = Lazy::new(|| rsa::pkcs8::AlgorithmIdentifierRef { + // id-mgf1 + oid: ID_MFG1, + // sha1 + parameters: Some( + asn1::AnyRef::from_der(&ENCODED_SHA1_HASH_ALGORITHM).unwrap(), + ), +}); + pub const RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier = const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1"); +pub const RSASSA_PSS_OID: const_oid::ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"); + +// The parameters field associated with OID id-RSASSA-PSS +// Defined in RFC 3447, section A.2.3 +// +// RSASSA-PSS-params ::= SEQUENCE { +// hashAlgorithm [0] HashAlgorithm DEFAULT sha1, +// maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, +// saltLength [2] INTEGER DEFAULT 20, +// trailerField [3] TrailerField DEFAULT trailerFieldBC +// } +pub struct PssPrivateKeyParameters<'a> { + pub hash_algorithm: rsa::pkcs8::AlgorithmIdentifierRef<'a>, + pub mask_gen_algorithm: rsa::pkcs8::AlgorithmIdentifierRef<'a>, + pub salt_length: u32, +} + +// Context-specific tag number for hashAlgorithm. +const HASH_ALGORITHM_TAG: rsa::pkcs8::der::TagNumber = + rsa::pkcs8::der::TagNumber::new(0); + +// Context-specific tag number for maskGenAlgorithm. +const MASK_GEN_ALGORITHM_TAG: rsa::pkcs8::der::TagNumber = + rsa::pkcs8::der::TagNumber::new(1); + +// Context-specific tag number for saltLength. +const SALT_LENGTH_TAG: rsa::pkcs8::der::TagNumber = + rsa::pkcs8::der::TagNumber::new(2); + +impl<'a> TryFrom> + for PssPrivateKeyParameters<'a> +{ + type Error = rsa::pkcs8::der::Error; + + fn try_from( + any: rsa::pkcs8::der::asn1::AnyRef<'a>, + ) -> rsa::pkcs8::der::Result { + any.sequence(|decoder| { + let hash_algorithm = decoder + .context_specific::( + HASH_ALGORITHM_TAG, + pkcs8::der::TagMode::Explicit, + )? + .map(TryInto::try_into) + .transpose()? + .unwrap_or(*SHA1_HASH_ALGORITHM); + + let mask_gen_algorithm = decoder + .context_specific::( + MASK_GEN_ALGORITHM_TAG, + pkcs8::der::TagMode::Explicit, + )? + .map(TryInto::try_into) + .transpose()? + .unwrap_or(*MGF1_SHA1_MASK_ALGORITHM); + + let salt_length = decoder + .context_specific::( + SALT_LENGTH_TAG, + pkcs8::der::TagMode::Explicit, + )? + .map(TryInto::try_into) + .transpose()? + .unwrap_or(20); + + Ok(Self { + hash_algorithm, + mask_gen_algorithm, + salt_length, + }) + }) + } +} + +fn parse_private_key( + key: &[u8], + format: &str, + type_: &str, +) -> Result { + use rsa::pkcs1::DecodeRsaPrivateKey; + + match format { + "pem" => { + let (label, doc) = + pkcs8::SecretDocument::from_pem(std::str::from_utf8(key).unwrap())?; + if label != "PRIVATE KEY" { + return Err(type_error("Invalid PEM label")); + } + Ok(doc) + } + "der" => { + match type_ { + "pkcs8" => pkcs8::SecretDocument::from_pkcs8_der(key) + .map_err(|_| type_error("Invalid PKCS8 private key")), + "pkcs1" => pkcs8::SecretDocument::from_pkcs1_der(key) + .map_err(|_| type_error("Invalid PKCS1 private key")), + // TODO(@littledivy): sec1 type + _ => { + return Err(type_error(format!("Unsupported key type: {}", type_))) + } + } + } + _ => Err(type_error(format!("Unsupported key format: {}", format))), + } +} #[op2] #[serde] pub fn op_node_create_private_key( - #[buffer] privkey: &[u8], + #[buffer] key: &[u8], + #[string] format: &str, + #[string] type_: &str, ) -> Result { - // We only support PEM for now. - let (label, doc) = - pkcs8::SecretDocument::from_pem(std::str::from_utf8(privkey).unwrap())?; + use rsa::pkcs1::der::Decode; + + let doc = parse_private_key(key, format, type_)?; let pk_info = pkcs8::PrivateKeyInfo::try_from(doc.as_bytes())?; - assert_eq!(label, "PRIVATE KEY"); let alg = pk_info.algorithm.oid; - if alg == RSA_ENCRYPTION_OID { - use rsa::pkcs1::der::Decode; - let private_key = rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?; - - let modulus_length = private_key.modulus.as_bytes().len() * 8; - return Ok(AsymmetricKeyDetails::Rsa { - modulus_length, - public_exponent: BigInt::from_bytes_be( - num_bigint::Sign::Plus, - private_key.public_exponent.as_bytes(), - ), - }); - } + match alg { + RSA_ENCRYPTION_OID => { + let private_key = + rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?; + let modulus_length = private_key.modulus.as_bytes().len() * 8; + + Ok(AsymmetricKeyDetails::Rsa { + modulus_length, + public_exponent: BigInt::from_bytes_be( + num_bigint::Sign::Plus, + private_key.public_exponent.as_bytes(), + ), + }) + } + RSASSA_PSS_OID => { + let params = PssPrivateKeyParameters::try_from( + pk_info + .algorithm + .parameters + .ok_or_else(|| type_error("Malformed parameters".to_string()))?, + ) + .map_err(|_| type_error("Malformed parameters".to_string()))?; + + let hash_alg = params.hash_algorithm; + let hash_algorithm = match hash_alg.oid { + ID_SHA1_OID => "sha1", + _ => return Err(type_error("Unsupported hash algorithm")), + }; - todo!() + let private_key = + rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?; + let modulus_length = private_key.modulus.as_bytes().len() * 8; + Ok(AsymmetricKeyDetails::RsaPss { + modulus_length, + public_exponent: BigInt::from_bytes_be( + num_bigint::Sign::Plus, + private_key.public_exponent.as_bytes(), + ), + hash_algorithm: hash_algorithm.to_string(), + salt_length: params.salt_length, + }) + } + _ => Err(type_error("Unsupported algorithm")), + } } From 6bfba810dfaffad9f93a4f21fe657e578197778d Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sat, 4 Nov 2023 22:37:02 +0530 Subject: [PATCH 05/13] x --- ext/node/ops/crypto/mod.rs | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 4ae90f26042d82..154c4d83a07937 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -1194,11 +1194,6 @@ pub enum AsymmetricKeyDetails { hash_algorithm: String, salt_length: u32, }, - #[serde(rename = "dsa")] - Dsa { - divisor_length: usize, - modulus_length: usize, - }, #[serde(rename = "ec")] Ec { named_curve: String }, } @@ -1210,6 +1205,12 @@ const ID_SHA1_OID: rsa::pkcs8::ObjectIdentifier = rsa::pkcs8::ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); const ID_MFG1: rsa::pkcs8::ObjectIdentifier = rsa::pkcs8::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8"); +pub const ID_SECP256R1_OID: const_oid::ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7"); +pub const ID_SECP384R1_OID: const_oid::ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.3.132.0.34"); +pub const ID_SECP521R1_OID: const_oid::ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.3.132.0.35"); // Default HashAlgorithm for RSASSA-PSS-params (sha1) // @@ -1219,8 +1220,8 @@ const ID_MFG1: rsa::pkcs8::ObjectIdentifier = // } // // SHA1Parameters ::= NULL -static SHA1_HASH_ALGORITHM: Lazy> = Lazy::new(|| - rsa::pkcs8::AlgorithmIdentifierRef { +static SHA1_HASH_ALGORITHM: Lazy> = + Lazy::new(|| rsa::pkcs8::AlgorithmIdentifierRef { // id-sha1 oid: ID_SHA1_OID, // NULL @@ -1252,6 +1253,8 @@ pub const RSA_ENCRYPTION_OID: const_oid::ObjectIdentifier = const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1"); pub const RSASSA_PSS_OID: const_oid::ObjectIdentifier = const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"); +pub const EC_OID: const_oid::ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.10045.2.1"); // The parameters field associated with OID id-RSASSA-PSS // Defined in RFC 3447, section A.2.3 @@ -1413,6 +1416,22 @@ pub fn op_node_create_private_key( salt_length: params.salt_length, }) } + EC_OID => { + let named_curve = pk_info + .algorithm + .parameters_oid() + .map_err(|_| type_error("malformed parameters"))?; + let named_curve = match named_curve { + ID_SECP256R1_OID => "p256", + ID_SECP384R1_OID => "p384", + ID_SECP521R1_OID => "p521", + _ => return Err(type_error("Unsupported named curve")), + }; + + Ok(AsymmetricKeyDetails::Ec { + named_curve: named_curve.to_string(), + }) + } _ => Err(type_error("Unsupported algorithm")), } } From 5308d16b97e60ad7b0269861de0b3532f146d7ce Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sat, 4 Nov 2023 22:38:37 +0530 Subject: [PATCH 06/13] x --- ext/node/ops/crypto/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 154c4d83a07937..54c5f1b3f4819f 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -13,10 +13,12 @@ use hkdf::Hkdf; use num_bigint::BigInt; use num_bigint_dig::BigUint; use num_traits::FromPrimitive; +use once_cell::sync::Lazy; use rand::distributions::Distribution; use rand::distributions::Uniform; use rand::thread_rng; use rand::Rng; +use rsa::pkcs8; use rsa::pkcs8::der::asn1; use rsa::pkcs8::der::Decode; use rsa::pkcs8::der::Encode; @@ -1198,9 +1200,6 @@ pub enum AsymmetricKeyDetails { Ec { named_curve: String }, } -use rsa::pkcs8; - -use once_cell::sync::Lazy; const ID_SHA1_OID: rsa::pkcs8::ObjectIdentifier = rsa::pkcs8::ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); const ID_MFG1: rsa::pkcs8::ObjectIdentifier = From 0de0aa34fd670d6d2de0854cbcadd3d2717a5481 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sat, 4 Nov 2023 22:39:03 +0530 Subject: [PATCH 07/13] x --- ext/node/polyfills/internal/crypto/keys.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts index 84b131d04ea6be..1a8373aa304ad1 100644 --- a/ext/node/polyfills/internal/crypto/keys.ts +++ b/ext/node/polyfills/internal/crypto/keys.ts @@ -17,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"; From ee3183ba79e59d4b58880ccd036ebde4f38cf169 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 5 Nov 2023 09:59:14 +0530 Subject: [PATCH 08/13] x --- ext/node/ops/crypto/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 54c5f1b3f4819f..5632f9d0382664 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -1350,9 +1350,7 @@ fn parse_private_key( "pkcs1" => pkcs8::SecretDocument::from_pkcs1_der(key) .map_err(|_| type_error("Invalid PKCS1 private key")), // TODO(@littledivy): sec1 type - _ => { - return Err(type_error(format!("Unsupported key type: {}", type_))) - } + _ => Err(type_error(format!("Unsupported key type: {}", type_))), } } _ => Err(type_error(format!("Unsupported key format: {}", format))), From 830786220f4dbe0e4bfb4a45bacb6c4131a351b1 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 5 Nov 2023 10:35:37 +0530 Subject: [PATCH 09/13] works --- ext/node/ops/crypto/mod.rs | 20 +++++++++++--- ext/node/polyfills/internal/crypto/cipher.ts | 2 +- ext/node/polyfills/internal/crypto/keys.ts | 28 +++++++++++++++++--- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 5632f9d0382664..74cb55da0feaf5 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -3,6 +3,7 @@ use deno_core::error::generic_error; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op2; +use deno_core::serde_v8::BigInt as V8BigInt; use deno_core::unsync::spawn_blocking; use deno_core::JsBuffer; use deno_core::OpState; @@ -1187,12 +1188,12 @@ pub enum AsymmetricKeyDetails { #[serde(rename = "rsa")] Rsa { modulus_length: usize, - public_exponent: BigInt, + public_exponent: V8BigInt, }, #[serde(rename = "rsa-pss")] RsaPss { modulus_length: usize, - public_exponent: BigInt, + public_exponent: V8BigInt, hash_algorithm: String, salt_length: u32, }, @@ -1202,6 +1203,12 @@ pub enum AsymmetricKeyDetails { const ID_SHA1_OID: rsa::pkcs8::ObjectIdentifier = rsa::pkcs8::ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); +const ID_SHA256_OID: rsa::pkcs8::ObjectIdentifier = + rsa::pkcs8::ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.1"); +const ID_SHA384_OID: rsa::pkcs8::ObjectIdentifier = + rsa::pkcs8::ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.2"); +const ID_SHA512_OID: rsa::pkcs8::ObjectIdentifier = + rsa::pkcs8::ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.3"); const ID_MFG1: rsa::pkcs8::ObjectIdentifier = rsa::pkcs8::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8"); pub const ID_SECP256R1_OID: const_oid::ObjectIdentifier = @@ -1382,7 +1389,8 @@ pub fn op_node_create_private_key( public_exponent: BigInt::from_bytes_be( num_bigint::Sign::Plus, private_key.public_exponent.as_bytes(), - ), + ) + .into(), }) } RSASSA_PSS_OID => { @@ -1397,6 +1405,9 @@ pub fn op_node_create_private_key( let hash_alg = params.hash_algorithm; let hash_algorithm = match hash_alg.oid { ID_SHA1_OID => "sha1", + ID_SHA256_OID => "sha256", + ID_SHA384_OID => "sha384", + ID_SHA512_OID => "sha512", _ => return Err(type_error("Unsupported hash algorithm")), }; @@ -1408,7 +1419,8 @@ pub fn op_node_create_private_key( public_exponent: BigInt::from_bytes_be( num_bigint::Sign::Plus, private_key.public_exponent.as_bytes(), - ), + ) + .into(), hash_algorithm: hash_algorithm.to_string(), salt_length: params.salt_length, }) diff --git a/ext/node/polyfills/internal/crypto/cipher.ts b/ext/node/polyfills/internal/crypto/cipher.ts index f943fa1bce4233..5fec98ff0c5b49 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); diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts index 1a8373aa304ad1..c3ea65bcbc7e9c 100644 --- a/ext/node/polyfills/internal/crypto/keys.ts +++ b/ext/node/polyfills/internal/crypto/keys.ts @@ -8,7 +8,7 @@ import { kHandle, kKeyObject, } from "ext:deno_node/internal/crypto/constants.ts"; -import { prepareKey } from "ext:deno_node/internal/crypto/cipher.ts"; +import { isStringOrBuffer } from "ext:deno_node/internal/crypto/cipher.ts"; import { ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE, ERR_INVALID_ARG_TYPE, @@ -210,11 +210,31 @@ 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 { - const { data } = prepareKey(key); - const details = ops.op_node_create_private_key(data); +): 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); } From 5e4d4cc80c8766b6d7aa638a939314effa1c1ce8 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 5 Nov 2023 10:36:00 +0530 Subject: [PATCH 10/13] x --- test.mjs | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 test.mjs diff --git a/test.mjs b/test.mjs deleted file mode 100644 index 21fc878debf043..00000000000000 --- a/test.mjs +++ /dev/null @@ -1,39 +0,0 @@ -import { createPrivateKey } from "node:crypto"; -import { App, Octokit } from "npm:octokit@^2.0.10"; - -const app = new App({ - appId: " ", - privateKey: `-----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDYKBqT674QjFgP -LciOxf8UNtfIligtwGc+RjuNRdzT2z7sduGPqxfW7y6MYm/tP92GjUKNf2/XzLkI -Ay5pPtHKv21YTAH4GOFqNJL3FzYVJtf8zZmvFhXY2BVIhu6JFkaFCBYC4+Is5nMM -kP12FZvf6LbTTVQVMRV5wyRXP1gzQ16fHE9c115mhzJSVkohtqHw5mFfEV/I7DEB -QRTn+hvv5r4gGc7qn9gewwmlOh+6ow1lc7WNWNn7kigsW9hgLGsGZvkaUge0jOLs -QPzEWSdzmiOnpMxYLK1XjC73G3+0OHUjtRdG9q3cr7/yqKO5uI0Ays1q40t2UZrH -rMBeFSi/AgMBAAECggEAE7NMANFKiE2SNQfyMHkBL4F0FzcAQHM5taZHBTAp2TEx -QfHvyt1IFfHEp0zNcK0SbpHvT+AefGePMZjAoRz1l+nseFCtGUSDPt+9yUFXT4Qz -yTmf2SJFKXdAMVUC5oGeOb+r6eWFFpyGPc31G88KXtTh3M4+bJQFpgxQApemXT2K -vvkUppWr/LKIrLQ9TboBAWOOMtuZ0+nDbCzFwdRvQ1itR/Jbq4swt4+PTXKkWrHN -gXoxCoMXaS/QW4BxzlnCAFelEvguF95VKPFgzf6AvHp7mun4tHYgePxugsG4xpRR -U3fCBIqHp8LunG8TpCIY4jeUE4vfNgxWgJ/E+oSOWQKBgQDundzft515Ul2k+wb2 -HaQbaVafYyDmwK/Ji8tthFVJqYPo7eWFbIsedAEGUBzxYd8WRJS59/jyV/MQ3mGS -Y2leCOVo/oGIxqugJNQl0NSnUYleXeweTWMeUhbbMPGutMHLe9hGByzOBwE4G1Oj -Yb8bu41WMzT9T1YBm8cuBQS02wKBgQDn5145sxlMDezj0kcOU+gQLXJfsIPhVIsf -aiLlH78BLDOTH3J+INMYnI869r1bCOlUjNjf3bdBgPA+YQQIPExmhQARAPk1riEp -x7O9egpcxlYzE7yNtR5LeEh5kW+nlSr6EcPPONJlHYgyv9DGxjhnA3lI93rBcqYy -0xSFF41O7QKBgQCiW2deEWFkm1Z8WxFxhNmUjSgTay+H0rPJPwU7jz84z86hPr1c -+23tWqEX2orW8vEIBcHsh30r6AvK/oUFRf77rLHrrsAUgJlmbair0lvfPOtq+h0e -wSkgCFrk6XiIlxUFj06o11j1Fm8N7goKsQeHpyWT8WOst76deZEdDu0U4QKBgEs/ -HqrYO0AbUJ9HrriubyE4reDwtIob1ZyW4sW3vFFUF1QIoyzb18Mnoa3/O8fbJ2LA -5OoW1gySGuIStq05a4zkYPYje7l4S9hzrRWxEMWzsWqXX9oXR8IzQEj58OHOnAhS -VVfa1yHqKDRXWxX0YX7DeMo9Sv6UBet95C2fS8GtAoGALvUAEM/LEj/NY+J0542F -+b8FyXtosQ1mSKBV03JmmglDfQW/+O0Illuy8CmfIuqftLwHyc15u5cAIDd5a8jm -S8l+7/KYETXYGCA1mwB/Dr/LJwbVEQ/mw1ne6FrJ4MORd/2GWuvzrqTKrwRcJ+O9 -mZ3aPB+XECOydno9s4rsxII= ------END PRIVATE KEY----- -`, -}); - -const { data } = await app.octokit.request("/app"); - -app.log.warn("ok"); From bd614d3876c64b2b99384cd65a655ea86d7628ee Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 5 Nov 2023 12:25:21 +0530 Subject: [PATCH 11/13] add tests --- cli/tests/unit_node/crypto/crypto_key_test.ts | 26 +++++++++++++++++++ .../unit_node/crypto/ec_private_secp256r1.pem | 5 ++++ ext/node/ops/crypto/mod.rs | 4 ++- ext/node/polyfills/internal/crypto/keys.ts | 3 +-- 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 cli/tests/unit_node/crypto/ec_private_secp256r1.pem diff --git a/cli/tests/unit_node/crypto/crypto_key_test.ts b/cli/tests/unit_node/crypto/crypto_key_test.ts index 672c9fa7f06788..0e56d825503ed4 100644 --- a/cli/tests/unit_node/crypto/crypto_key_test.ts +++ b/cli/tests/unit_node/crypto/crypto_key_test.ts @@ -2,6 +2,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. import { + createPrivateKey, createSecretKey, generateKeyPair, generateKeyPairSync, @@ -202,3 +203,28 @@ for (const primeLength of [1024, 2048, 4096]) { }, }); } + +const rsaPrivateKey = Deno.readTextFileSync( + new URL("../testdata/rsa_private.pem", import.meta.url), +); + +Deno.test("createPrivateKey rsa", function () { + const key = createPrivateKey(rsaPrivateKey); + assertEquals(key.type, "private"); + assertEquals(key.asymmetricKeyType, "rsa"); + assertEquals(key.asymmetricKeyDetails?.modulusLength, 2048); + assertEquals(key.asymmetricKeyDetails?.publicExponent, 65537n); +}); + +// openssl ecparam -name secp256r1 -genkey -noout -out a.pem +// openssl pkcs8 -topk8 -nocrypt -in a.pem -out b.pem +const ecPrivateKey = Deno.readTextFileSync( + new URL("./ec_private_secp256r1.pem", import.meta.url), +); + +Deno.test("createPrivateKey ec", function () { + const key = createPrivateKey(ecPrivateKey); + assertEquals(key.type, "private"); + assertEquals(key.asymmetricKeyType, "ec"); + assertEquals(key.asymmetricKeyDetails?.namedCurve, "p256"); +}); diff --git a/cli/tests/unit_node/crypto/ec_private_secp256r1.pem b/cli/tests/unit_node/crypto/ec_private_secp256r1.pem new file mode 100644 index 00000000000000..f1d5c5769fc31e --- /dev/null +++ b/cli/tests/unit_node/crypto/ec_private_secp256r1.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgbT/dwqGGyRs19qy8 +XPyAZVluvTE9N6hIbyVuFyZobrahRANCAATeWMJqmunAZ6o2lumC79MklBB3Z7ZF +ToryVl8HXevci1d/R+OZ6FjYnoICxw3rMXiKMDtUTAFi2ikL20O4+62M +-----END PRIVATE KEY----- diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 74cb55da0feaf5..a9f3584c272633 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -1183,14 +1183,15 @@ pub async fn op_node_gen_prime_async( #[derive(serde::Serialize)] #[serde(tag = "type")] -#[serde(rename_all = "camelCase")] pub enum AsymmetricKeyDetails { #[serde(rename = "rsa")] + #[serde(rename_all = "camelCase")] Rsa { modulus_length: usize, public_exponent: V8BigInt, }, #[serde(rename = "rsa-pss")] + #[serde(rename_all = "camelCase")] RsaPss { modulus_length: usize, public_exponent: V8BigInt, @@ -1198,6 +1199,7 @@ pub enum AsymmetricKeyDetails { salt_length: u32, }, #[serde(rename = "ec")] + #[serde(rename_all = "camelCase")] Ec { named_curve: String }, } diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts index c3ea65bcbc7e9c..e0c44cbf9c40c4 100644 --- a/ext/node/polyfills/internal/crypto/keys.ts +++ b/ext/node/polyfills/internal/crypto/keys.ts @@ -336,9 +336,8 @@ const kAsymmetricKeyDetails = Symbol("kAsymmetricKeyDetails"); class AsymmetricKeyObject extends KeyObject { constructor(type: KeyObjectType, handle: unknown, details: unknown) { super(type, handle); - console.log(details); this[kAsymmetricKeyType] = details.type; - this[kAsymmetricKeyDetails] = details; + this[kAsymmetricKeyDetails] = { ...details }; } get asymmetricKeyType() { From 3f44e3db065701d90358de7b1ae28bd968bceb32 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Thu, 9 Nov 2023 10:08:36 +0530 Subject: [PATCH 12/13] review --- cli/tests/unit_node/crypto/crypto_key_test.ts | 4 ++-- ext/node/ops/crypto/mod.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/tests/unit_node/crypto/crypto_key_test.ts b/cli/tests/unit_node/crypto/crypto_key_test.ts index 0e56d825503ed4..ff432e52101254 100644 --- a/cli/tests/unit_node/crypto/crypto_key_test.ts +++ b/cli/tests/unit_node/crypto/crypto_key_test.ts @@ -205,7 +205,7 @@ for (const primeLength of [1024, 2048, 4096]) { } const rsaPrivateKey = Deno.readTextFileSync( - new URL("../testdata/rsa_private.pem", import.meta.url), + import.meta.resolve!("../testdata/rsa_private.pem"), ); Deno.test("createPrivateKey rsa", function () { @@ -219,7 +219,7 @@ Deno.test("createPrivateKey rsa", function () { // openssl ecparam -name secp256r1 -genkey -noout -out a.pem // openssl pkcs8 -topk8 -nocrypt -in a.pem -out b.pem const ecPrivateKey = Deno.readTextFileSync( - new URL("./ec_private_secp256r1.pem", import.meta.url), + import.meta.resolve!("./ec_private_secp256r1.pem"), ); Deno.test("createPrivateKey ec", function () { diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index a9f3584c272633..35940da77d339b 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -1203,6 +1203,7 @@ pub enum AsymmetricKeyDetails { Ec { named_curve: String }, } +// https://oidref.com/ const ID_SHA1_OID: rsa::pkcs8::ObjectIdentifier = rsa::pkcs8::ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); const ID_SHA256_OID: rsa::pkcs8::ObjectIdentifier = From 3128d6b8216b0785fb73b0f1137373e0a09653cc Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Thu, 9 Nov 2023 10:34:41 +0530 Subject: [PATCH 13/13] oh --- cli/tests/unit_node/crypto/crypto_key_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/tests/unit_node/crypto/crypto_key_test.ts b/cli/tests/unit_node/crypto/crypto_key_test.ts index ff432e52101254..0e56d825503ed4 100644 --- a/cli/tests/unit_node/crypto/crypto_key_test.ts +++ b/cli/tests/unit_node/crypto/crypto_key_test.ts @@ -205,7 +205,7 @@ for (const primeLength of [1024, 2048, 4096]) { } const rsaPrivateKey = Deno.readTextFileSync( - import.meta.resolve!("../testdata/rsa_private.pem"), + new URL("../testdata/rsa_private.pem", import.meta.url), ); Deno.test("createPrivateKey rsa", function () { @@ -219,7 +219,7 @@ Deno.test("createPrivateKey rsa", function () { // openssl ecparam -name secp256r1 -genkey -noout -out a.pem // openssl pkcs8 -topk8 -nocrypt -in a.pem -out b.pem const ecPrivateKey = Deno.readTextFileSync( - import.meta.resolve!("./ec_private_secp256r1.pem"), + new URL("./ec_private_secp256r1.pem", import.meta.url), ); Deno.test("createPrivateKey ec", function () {