summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/unit_node/crypto/crypto_sign_test.ts46
-rw-r--r--cli/tests/unit_node/testdata/rsa_private_pkcs1.pem27
-rw-r--r--ext/node/ops/crypto/mod.rs47
-rw-r--r--ext/node/polyfills/internal/crypto/cipher.ts3
-rw-r--r--ext/node/polyfills/internal/crypto/keys.ts2
-rw-r--r--ext/node/polyfills/internal/crypto/sig.ts23
6 files changed, 106 insertions, 42 deletions
diff --git a/cli/tests/unit_node/crypto/crypto_sign_test.ts b/cli/tests/unit_node/crypto/crypto_sign_test.ts
index 58107b563..b04cae407 100644
--- a/cli/tests/unit_node/crypto/crypto_sign_test.ts
+++ b/cli/tests/unit_node/crypto/crypto_sign_test.ts
@@ -1,6 +1,9 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-import { assert, assertEquals } from "../../../../test_util/std/assert/mod.ts";
+import {
+ assert,
+ assertEquals,
+} from "../../../../test_util/std/testing/asserts.ts";
import { createSign, createVerify, sign, verify } from "node:crypto";
import { Buffer } from "node:buffer";
@@ -9,6 +12,11 @@ const rsaPrivatePem = Buffer.from(
new URL("../testdata/rsa_private.pem", import.meta.url),
),
);
+const rsaPrivatePkcs1Pem = Buffer.from(
+ await Deno.readFile(
+ new URL("../testdata/rsa_private_pkcs1.pem", import.meta.url),
+ ),
+);
const rsaPublicPem = Buffer.from(
await Deno.readFile(
new URL("../testdata/rsa_public.pem", import.meta.url),
@@ -86,3 +94,39 @@ Deno.test({
}
},
});
+
+Deno.test({
+ name: "crypto.createPrivateKey|sign - RSA PEM",
+ fn() {
+ for (const testCase of table) {
+ for (const algorithm of testCase.algorithms) {
+ assertEquals(
+ createSign(algorithm).update(data).sign(rsaPrivatePem, "hex"),
+ testCase.signature,
+ );
+ assertEquals(
+ sign(algorithm, data, rsaPrivatePem),
+ Buffer.from(testCase.signature, "hex"),
+ );
+ }
+ }
+ },
+});
+
+Deno.test({
+ name: "crypto.createPrivateKey|sign - RSA PKCS1 PEM",
+ fn() {
+ for (const testCase of table) {
+ for (const algorithm of testCase.algorithms) {
+ assertEquals(
+ createSign(algorithm).update(data).sign(rsaPrivatePkcs1Pem, "hex"),
+ testCase.signature,
+ );
+ assertEquals(
+ sign(algorithm, data, rsaPrivatePkcs1Pem),
+ Buffer.from(testCase.signature, "hex"),
+ );
+ }
+ }
+ },
+});
diff --git a/cli/tests/unit_node/testdata/rsa_private_pkcs1.pem b/cli/tests/unit_node/testdata/rsa_private_pkcs1.pem
new file mode 100644
index 000000000..215e5cc51
--- /dev/null
+++ b/cli/tests/unit_node/testdata/rsa_private_pkcs1.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAt9xYiIonscC3vz/A2ceR7KhZZlDu/5bye53nCVTcKnWd2seY
+6UAdKersX6njr83Dd5OVe1BW/wJvp5EjWTAGYbFswlNmeD44edEGM939B6Lq+/8i
+BkrTi8mGN4YCytivE24YI0D4XZMPfkLSpab2y/Hy4DjQKBq1ThZ0UBnK+9IhX37J
+u/ZoGYSlTIGIhzyaiYBh7wrZBoPczIEu6et/kN2VnnbRUtkYTF97ggcv5h+hDpUQ
+jQW0ZgOMcTc8n+RkGpIt0/iM/bTjI3Tz/gsFdi6hHcpZgbopPL630296iByyigQC
+PJVzdusFrQN5DeC+zT/nGypQkZanLb4ZspSx9QIDAQABAoIBAQCS2erYu8gyoGPi
+3E/zYgQ6ishFAZWzDWSFubwD5wSm4SSAzvViL/RbO6kqS25xR569DmLRiHzD17VI
+mJMsNECUnPrqR2TL256OJZaXrNHh3I1lUwVhEzjeKMsL4/ys+d70XPXoiocVblVs
+moDXEIGEqa48ywPvVE3Fngeuxrsq3/GCVBNiwtt0YjAOZxmKEh31UZdHO+YI+wNF
+/Z8KQCPscN5HGlR0SIQOlqMANz49aKStrevdvjS1UcpabzDEkuK84g3saJhcpAhb
+pGFmAf5GTjkkhE0rE1qDF15dSqrKGfCFtOjUeK17SIEN7E322ChmTReZ1hYGfoSV
+cdFntUINAoGBAPFKL5QeJ6wZu8R/ru11wTG6sQA0Jub2hGccPXpbnPrT+3CACOLI
+JTCLy/xTKW3dqRHj/wZEe+jUw88w7jwGb1BkWr4BI8tDvY9jQLP1jyuLWRfrxXbp
+4Z0oeBBwBeCI/ZG7FIvdDTqWxn1aj3Tmh6s4ByqEdtwrrrJPcBUNl01fAoGBAMMR
+3RGE/ca6X6xz6kgUD6TtHVhiiRJK1jm/u+q0n7i/MBkeDgTZkHYS7lPc0yIdtqaI
+Plz5yzwHnAvuMrv8LSdkjwioig2yQa3tAij8kXxqs7wN5418DMV2s1OJBrPthYPs
+bv4im2iI8V63JQS4ZMYQbckq8ABYccTpOnxXDy0rAoGBAKkvzHa+QjERhjB9GyoT
+1FhLQIsVBmYSWrp1+cGO9V6HPxoeHJzvm+wTSf/uS/FmaINL6+j4Ii4a6gWgmJts
+I6cqBtqNsAx5vjQJczf8KdxthBYa0sXTrsfktXNJKUXMqIgDtp9vazQ2vozs8AQX
+FPAAhD3SzgkJdCBBRSTt97ZfAoGAWAziKpxLKL7LnL4dzDcx8JIPIuwnTxh0plCD
+dCffyLaT8WJ9lXbXHFTjOvt8WfPrlDP/Ylxmfkw5BbGZOP1VLGjZn2DkH9aMiwNm
+bDXFPdG0G3hzQovx/9fajiRV4DWghLHeT9wzJfZabRRiI0VQR472300AVEeX4vgb
+rDBn600CgYEAk7czBCT9rHn/PNwCa17hlTy88C4vXkwbz83Oa+aX5L4e5gw5lhcR
+2ZuZHLb2r6oMt9rlD7EIDItSs+u21LOXWPTAlazdnpYUyw/CzogM/PN+qNwMRXn5
+uXFFhmlP2mVg2EdELTahXch8kWqHaCSX53yvqCtRKu/j76V31TfQZGM=
+-----END RSA PRIVATE KEY-----
diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs
index 4aaa3f494..97c3d76aa 100644
--- a/ext/node/ops/crypto/mod.rs
+++ b/ext/node/ops/crypto/mod.rs
@@ -19,6 +19,7 @@ use rand::distributions::Distribution;
use rand::distributions::Uniform;
use rand::thread_rng;
use rand::Rng;
+use rsa::pkcs1::DecodeRsaPrivateKey;
use rsa::pkcs8;
use rsa::pkcs8::der::asn1;
use rsa::pkcs8::der::Decode;
@@ -363,23 +364,32 @@ pub fn op_node_sign(
#[buffer] digest: &[u8],
#[string] digest_type: &str,
#[serde] key: StringOrBuffer,
- #[string] key_type: &str,
- #[string] key_format: &str,
+ #[string] _type: &str,
+ #[string] format: &str,
) -> Result<ToJsBuffer, AnyError> {
- match key_type {
- "rsa" => {
+ let (label, doc) =
+ pkcs8::SecretDocument::from_pem(std::str::from_utf8(&key).unwrap())?;
+
+ let oid;
+ let pkey = match format {
+ "pem" => {
+ if label == "PRIVATE KEY" {
+ let pk_info = pkcs8::PrivateKeyInfo::try_from(doc.as_bytes())?;
+ oid = pk_info.algorithm.oid;
+ pk_info.private_key
+ } else if label == "RSA PRIVATE KEY" {
+ oid = RSA_ENCRYPTION_OID;
+ doc.as_bytes()
+ } else {
+ return Err(type_error("Invalid PEM label"));
+ }
+ }
+ _ => return Err(type_error("Unsupported key format")),
+ };
+ match oid {
+ RSA_ENCRYPTION_OID => {
use rsa::pkcs1v15::SigningKey;
- let key = match key_format {
- "pem" => RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)
- .map_err(|_| type_error("Invalid RSA private key"))?,
- // TODO(kt3k): Support der and jwk formats
- _ => {
- return Err(type_error(format!(
- "Unsupported key format: {}",
- key_format
- )))
- }
- };
+ let key = RsaPrivateKey::from_pkcs1_der(pkey)?;
Ok(
match digest_type {
"sha224" => {
@@ -408,10 +418,7 @@ pub fn op_node_sign(
.into(),
)
}
- _ => Err(type_error(format!(
- "Signing with {} keys is not supported yet",
- key_type
- ))),
+ _ => Err(type_error("Unsupported signing key")),
}
}
@@ -1345,8 +1352,6 @@ fn parse_private_key(
format: &str,
type_: &str,
) -> Result<pkcs8::SecretDocument, AnyError> {
- use rsa::pkcs1::DecodeRsaPrivateKey;
-
match format {
"pem" => {
let (label, doc) =
diff --git a/ext/node/polyfills/internal/crypto/cipher.ts b/ext/node/polyfills/internal/crypto/cipher.ts
index 5fec98ff0..9b63db538 100644
--- a/ext/node/polyfills/internal/crypto/cipher.ts
+++ b/ext/node/polyfills/internal/crypto/cipher.ts
@@ -31,7 +31,8 @@ import {
export function isStringOrBuffer(val) {
return typeof val === "string" ||
isArrayBufferView(val) ||
- isAnyArrayBuffer(val);
+ isAnyArrayBuffer(val) ||
+ Buffer.isBuffer(val);
}
const { ops, encode } = globalThis.__bootstrap.core;
diff --git a/ext/node/polyfills/internal/crypto/keys.ts b/ext/node/polyfills/internal/crypto/keys.ts
index e0c44cbf9..6a4fb2149 100644
--- a/ext/node/polyfills/internal/crypto/keys.ts
+++ b/ext/node/polyfills/internal/crypto/keys.ts
@@ -210,7 +210,7 @@ export interface JsonWebKeyInput {
format: "jwk";
}
-function prepareAsymmetricKey(key) {
+export function prepareAsymmetricKey(key) {
if (isStringOrBuffer(key)) {
return { format: "pem", data: getArrayBufferOrView(key, "key") };
} else if (typeof key == "object") {
diff --git a/ext/node/polyfills/internal/crypto/sig.ts b/ext/node/polyfills/internal/crypto/sig.ts
index c5eb34fae..9e8af8d08 100644
--- a/ext/node/polyfills/internal/crypto/sig.ts
+++ b/ext/node/polyfills/internal/crypto/sig.ts
@@ -20,8 +20,8 @@ import type {
PublicKeyInput,
} from "ext:deno_node/internal/crypto/types.ts";
import {
- getKeyMaterial,
KeyObject,
+ prepareAsymmetricKey,
} 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";
@@ -80,26 +80,13 @@ export class SignImpl extends Writable {
privateKey: BinaryLike | SignKeyObjectInput | SignPrivateKeyInput,
encoding?: BinaryToTextEncoding,
): Buffer | string {
- let keyData: Uint8Array;
- let keyType: KeyType;
- let keyFormat: KeyFormat;
- if (typeof privateKey === "string" || isArrayBufferView(privateKey)) {
- // if the key is BinaryLike, interpret it as a PEM encoded RSA key
- // deno-lint-ignore no-explicit-any
- keyData = privateKey as any;
- keyType = "rsa";
- keyFormat = "pem";
- } else {
- keyData = getKeyMaterial(privateKey);
- keyType = "rsa";
- keyFormat = "pem";
- }
+ const { data, format, type } = prepareAsymmetricKey(privateKey);
const ret = Buffer.from(ops.op_node_sign(
this.hash.digest(),
this.#digestType,
- keyData!,
- keyType,
- keyFormat,
+ data!,
+ type,
+ format,
));
return encoding ? ret.toString(encoding) : ret;
}