1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 16:19:12 -05:00

fix(ext/node): ECDH.publicKey() point encoding (#23013)

This commit is contained in:
Divy Srivastava 2024-03-21 14:11:54 +05:30 committed by GitHub
parent 210f2911ce
commit 1f60b8af97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 93 additions and 4 deletions

View file

@ -240,6 +240,7 @@ deno_core::extension!(deno_node,
ops::crypto::op_node_ecdh_generate_keys,
ops::crypto::op_node_ecdh_compute_secret,
ops::crypto::op_node_ecdh_compute_public_key,
ops::crypto::op_node_ecdh_encode_pubkey,
ops::crypto::x509::op_node_x509_parse,
ops::crypto::x509::op_node_x509_ca,
ops::crypto::x509::op_node_x509_check_email,

View file

@ -1047,6 +1047,75 @@ pub async fn op_node_scrypt_async(
.await?
}
#[op2]
#[buffer]
pub fn op_node_ecdh_encode_pubkey(
#[string] curve: &str,
#[buffer] pubkey: &[u8],
compress: bool,
) -> Result<Vec<u8>, AnyError> {
use elliptic_curve::sec1::FromEncodedPoint;
match curve {
"secp256k1" => {
let pubkey =
elliptic_curve::PublicKey::<k256::Secp256k1>::from_encoded_point(
&elliptic_curve::sec1::EncodedPoint::<k256::Secp256k1>::from_bytes(
pubkey,
)?,
);
// CtOption does not expose its variants.
if pubkey.is_none().into() {
return Err(type_error("Invalid public key"));
}
let pubkey = pubkey.unwrap();
Ok(pubkey.to_encoded_point(compress).as_ref().to_vec())
}
"prime256v1" | "secp256r1" => {
let pubkey = elliptic_curve::PublicKey::<NistP256>::from_encoded_point(
&elliptic_curve::sec1::EncodedPoint::<NistP256>::from_bytes(pubkey)?,
);
// CtOption does not expose its variants.
if pubkey.is_none().into() {
return Err(type_error("Invalid public key"));
}
let pubkey = pubkey.unwrap();
Ok(pubkey.to_encoded_point(compress).as_ref().to_vec())
}
"secp384r1" => {
let pubkey = elliptic_curve::PublicKey::<NistP384>::from_encoded_point(
&elliptic_curve::sec1::EncodedPoint::<NistP384>::from_bytes(pubkey)?,
);
// CtOption does not expose its variants.
if pubkey.is_none().into() {
return Err(type_error("Invalid public key"));
}
let pubkey = pubkey.unwrap();
Ok(pubkey.to_encoded_point(compress).as_ref().to_vec())
}
"secp224r1" => {
let pubkey = elliptic_curve::PublicKey::<NistP224>::from_encoded_point(
&elliptic_curve::sec1::EncodedPoint::<NistP224>::from_bytes(pubkey)?,
);
// CtOption does not expose its variants.
if pubkey.is_none().into() {
return Err(type_error("Invalid public key"));
}
let pubkey = pubkey.unwrap();
Ok(pubkey.to_encoded_point(compress).as_ref().to_vec())
}
&_ => Err(type_error("Unsupported curve")),
}
}
#[op2(fast)]
pub fn op_node_ecdh_generate_keys(
#[string] curve: &str,

View file

@ -9,6 +9,7 @@ import {
op_node_dh_generate2,
op_node_ecdh_compute_public_key,
op_node_ecdh_compute_secret,
op_node_ecdh_encode_pubkey,
op_node_ecdh_generate_keys,
op_node_gen_prime,
} from "ext:core/ops";
@ -1239,7 +1240,7 @@ export class ECDH {
format: ECDHKeyFormat = "uncompressed",
): Buffer | string {
this.#pubbuf = Buffer.alloc(
format.trim() == "compressed"
format == "compressed"
? this.#curve.publicKeySizeCompressed
: this.#curve.publicKeySize,
);
@ -1269,12 +1270,17 @@ export class ECDH {
getPublicKey(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string;
getPublicKey(
encoding?: BinaryToTextEncoding,
_format?: ECDHKeyFormat,
format: ECDHKeyFormat = "uncompressed",
): Buffer | string {
const pubbuf = Buffer.from(op_node_ecdh_encode_pubkey(
this.#curve.name,
this.#pubbuf,
format == "compressed",
));
if (encoding !== undefined) {
return this.#pubbuf.toString(encoding);
return pubbuf.toString(encoding);
}
return this.#pubbuf;
return pubbuf;
}
setPrivateKey(privateKey: ArrayBufferView): void;

View file

@ -341,3 +341,16 @@ Deno.test("ECDH generateKeys compressed", function () {
const uncompressedKey = ecdh.generateKeys("binary");
assertEquals(uncompressedKey.length, 65);
});
Deno.test("ECDH getPublicKey compressed", function () {
const ecdh = createECDH("secp256k1");
for (const format of ["compressed", "uncompressed"] as const) {
ecdh.generateKeys("binary", format);
const compressedKey = ecdh.getPublicKey("binary", "compressed");
assertEquals(compressedKey.length, 33);
const uncompressedKey = ecdh.getPublicKey("binary");
assertEquals(uncompressedKey.length, 65);
}
});