Skip to content

Commit 4c0809c

Browse files
committed
src: improve EC JWK import performance
1 parent abff716 commit 4c0809c

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

deps/ncrypto/ncrypto.cc

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3526,8 +3526,38 @@ bool ECKeyPointer::setPublicKey(const ECPointPointer& pub) {
35263526
bool ECKeyPointer::setPublicKeyRaw(const BignumPointer& x,
35273527
const BignumPointer& y) {
35283528
if (!key_) return false;
3529-
return EC_KEY_set_public_key_affine_coordinates(
3530-
key_.get(), x.get(), y.get()) == 1;
3529+
const EC_GROUP* group = EC_KEY_get0_group(key_.get());
3530+
if (group == nullptr) return false;
3531+
3532+
// For curves with cofactor h=1, use EC_POINT_oct2point +
3533+
// EC_KEY_set_public_key instead of EC_KEY_set_public_key_affine_coordinates.
3534+
// The latter internally calls EC_KEY_check_key() which performs a scalar
3535+
// multiplication (n*Q) for order validation — redundant when h=1 since every
3536+
// on-curve point already has order n. EC_POINT_oct2point validates the point
3537+
// is on the curve, which is sufficient. For curves with h!=1, fall back to
3538+
// the full check.
3539+
auto cofactor = BignumPointer::New();
3540+
if (!cofactor || !EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) ||
3541+
!cofactor.isOne()) {
3542+
return EC_KEY_set_public_key_affine_coordinates(
3543+
key_.get(), x.get(), y.get()) == 1;
3544+
}
3545+
3546+
// Field element byte length: ceil(degree_bits / 8).
3547+
size_t field_len = (EC_GROUP_get_degree(group) + 7) / 8;
3548+
// Build an uncompressed point: 0x04 || x || y, each padded to field_len.
3549+
size_t uncompressed_len = 1 + 2 * field_len;
3550+
auto buf = DataPointer::Alloc(uncompressed_len);
3551+
if (!buf) return false;
3552+
unsigned char* ptr = static_cast<unsigned char*>(buf.get());
3553+
ptr[0] = POINT_CONVERSION_UNCOMPRESSED;
3554+
x.encodePaddedInto(ptr + 1, field_len);
3555+
y.encodePaddedInto(ptr + 1 + field_len, field_len);
3556+
3557+
auto point = ECPointPointer::New(group);
3558+
if (!point) return false;
3559+
if (!point.setFromBuffer({ptr, uncompressed_len}, group)) return false;
3560+
return EC_KEY_set_public_key(key_.get(), point.get()) == 1;
35313561
}
35323562

35333563
bool ECKeyPointer::setPrivateKey(const BignumPointer& priv) {

0 commit comments

Comments
 (0)