1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 08:33:43 -05:00

fix(ext/node): support public key point encoding in ECDH.generateKeys() (#22976)

Towards https://github.com/denoland/deno/issues/22921

Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
This commit is contained in:
Satya Rohith 2024-03-18 13:20:10 +05:30 committed by GitHub
parent 9c5ddf7c69
commit becdad531f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 31 additions and 8 deletions

View file

@ -10,6 +10,7 @@ use deno_core::OpState;
use deno_core::ResourceId;
use deno_core::StringOrBuffer;
use deno_core::ToJsBuffer;
use elliptic_curve::sec1::ToEncodedPoint;
use hkdf::Hkdf;
use num_bigint::BigInt;
use num_bigint_dig::BigUint;
@ -739,8 +740,6 @@ pub async fn op_node_dsa_generate_async(
fn ec_generate(
named_curve: &str,
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
use elliptic_curve::sec1::ToEncodedPoint;
let mut rng = rand::thread_rng();
// TODO(@littledivy): Support public key point encoding.
// Default is uncompressed.
@ -1054,14 +1053,16 @@ pub fn op_node_ecdh_generate_keys(
#[string] curve: &str,
#[buffer] pubbuf: &mut [u8],
#[buffer] privbuf: &mut [u8],
#[string] format: &str,
) -> Result<ResourceId, AnyError> {
let mut rng = rand::thread_rng();
let compress = format == "compressed";
match curve {
"secp256k1" => {
let privkey =
elliptic_curve::SecretKey::<k256::Secp256k1>::random(&mut rng);
let pubkey = privkey.public_key();
pubbuf.copy_from_slice(pubkey.to_sec1_bytes().as_ref());
pubbuf.copy_from_slice(pubkey.to_encoded_point(compress).as_ref());
privbuf.copy_from_slice(privkey.to_nonzero_scalar().to_bytes().as_ref());
Ok(0)
@ -1069,21 +1070,21 @@ pub fn op_node_ecdh_generate_keys(
"prime256v1" | "secp256r1" => {
let privkey = elliptic_curve::SecretKey::<NistP256>::random(&mut rng);
let pubkey = privkey.public_key();
pubbuf.copy_from_slice(pubkey.to_sec1_bytes().as_ref());
pubbuf.copy_from_slice(pubkey.to_encoded_point(compress).as_ref());
privbuf.copy_from_slice(privkey.to_nonzero_scalar().to_bytes().as_ref());
Ok(0)
}
"secp384r1" => {
let privkey = elliptic_curve::SecretKey::<NistP384>::random(&mut rng);
let pubkey = privkey.public_key();
pubbuf.copy_from_slice(pubkey.to_sec1_bytes().as_ref());
pubbuf.copy_from_slice(pubkey.to_encoded_point(compress).as_ref());
privbuf.copy_from_slice(privkey.to_nonzero_scalar().to_bytes().as_ref());
Ok(0)
}
"secp224r1" => {
let privkey = elliptic_curve::SecretKey::<NistP224>::random(&mut rng);
let pubkey = privkey.public_key();
pubbuf.copy_from_slice(pubkey.to_sec1_bytes().as_ref());
pubbuf.copy_from_slice(pubkey.to_encoded_point(compress).as_ref());
privbuf.copy_from_slice(privkey.to_nonzero_scalar().to_bytes().as_ref());
Ok(0)
}

View file

@ -1236,12 +1236,18 @@ export class ECDH {
generateKeys(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string;
generateKeys(
encoding?: BinaryToTextEncoding,
_format?: ECDHKeyFormat,
format: ECDHKeyFormat = "uncompressed",
): Buffer | string {
this.#pubbuf = Buffer.alloc(
format.trim() == "compressed"
? this.#curve.publicKeySizeCompressed
: this.#curve.publicKeySize,
);
op_node_ecdh_generate_keys(
this.#curve.name,
this.#pubbuf,
this.#privbuf,
format,
);
if (encoding !== undefined) {

View file

@ -16,7 +16,7 @@ export type Encoding =
| CharacterEncoding
| LegacyCharacterEncoding;
export type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid";
export type ECDHKeyFormat = "compressed" | "uncompressed";
export type BinaryLike = string | ArrayBufferView;

View file

@ -25,6 +25,7 @@ export type EllipticCurve = {
ephemeral: boolean;
privateKeySize: number;
publicKeySize: number;
publicKeySizeCompressed: number;
sharedSecretSize: number;
};
@ -33,30 +34,35 @@ export const ellipticCurves: Array<EllipticCurve> = [
name: "secp256k1",
privateKeySize: 32,
publicKeySize: 65,
publicKeySizeCompressed: 33,
sharedSecretSize: 32,
}, // Weierstrass-class EC used by Bitcoin
{
name: "prime256v1",
privateKeySize: 32,
publicKeySize: 65,
publicKeySizeCompressed: 33,
sharedSecretSize: 32,
}, // NIST P-256 EC
{
name: "secp256r1",
privateKeySize: 32,
publicKeySize: 65,
publicKeySizeCompressed: 33,
sharedSecretSize: 32,
}, // NIST P-256 EC (same as above)
{
name: "secp384r1",
privateKeySize: 48,
publicKeySize: 97,
publicKeySizeCompressed: 49,
sharedSecretSize: 48,
}, // NIST P-384 EC
{
name: "secp224r1",
privateKeySize: 28,
publicKeySize: 57,
publicKeySizeCompressed: 29,
sharedSecretSize: 28,
}, // NIST P-224 EC
];

View file

@ -2,6 +2,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import {
createECDH,
createHmac,
createPrivateKey,
createPublicKey,
@ -313,3 +314,12 @@ Deno.test("createPublicKey SPKI for DH", async function () {
assertEquals(pubKey.asymmetricKeyType, "ec");
assertEquals(privKey.asymmetricKeyType, "ec");
});
Deno.test("ECDH generateKeys compressed", function () {
const ecdh = createECDH("secp256k1");
const publicKey = ecdh.generateKeys("binary", "compressed");
assertEquals(publicKey.length, 33);
const uncompressedKey = ecdh.generateKeys("binary");
assertEquals(uncompressedKey.length, 65);
});