Skip to content

Commit f3633ef

Browse files
authored
src: improve EC JWK import performance
PR-URL: #62396 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 7ffbb76 commit f3633ef

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
@@ -3538,8 +3538,38 @@ bool ECKeyPointer::setPublicKey(const ECPointPointer& pub) {
35383538
bool ECKeyPointer::setPublicKeyRaw(const BignumPointer& x,
35393539
const BignumPointer& y) {
35403540
if (!key_) return false;
3541-
return EC_KEY_set_public_key_affine_coordinates(
3542-
key_.get(), x.get(), y.get()) == 1;
3541+
const EC_GROUP* group = EC_KEY_get0_group(key_.get());
3542+
if (group == nullptr) return false;
3543+
3544+
// For curves with cofactor h=1, use EC_POINT_oct2point +
3545+
// EC_KEY_set_public_key instead of EC_KEY_set_public_key_affine_coordinates.
3546+
// The latter internally calls EC_KEY_check_key() which performs a scalar
3547+
// multiplication (n*Q) for order validation — redundant when h=1 since every
3548+
// on-curve point already has order n. EC_POINT_oct2point validates the point
3549+
// is on the curve, which is sufficient. For curves with h!=1, fall back to
3550+
// the full check.
3551+
auto cofactor = BignumPointer::New();
3552+
if (!cofactor || !EC_GROUP_get_cofactor(group, cofactor.get(), nullptr) ||
3553+
!cofactor.isOne()) {
3554+
return EC_KEY_set_public_key_affine_coordinates(
3555+
key_.get(), x.get(), y.get()) == 1;
3556+
}
3557+
3558+
// Field element byte length: ceil(degree_bits / 8).
3559+
size_t field_len = (EC_GROUP_get_degree(group) + 7) / 8;
3560+
// Build an uncompressed point: 0x04 || x || y, each padded to field_len.
3561+
size_t uncompressed_len = 1 + 2 * field_len;
3562+
auto buf = DataPointer::Alloc(uncompressed_len);
3563+
if (!buf) return false;
3564+
unsigned char* ptr = static_cast<unsigned char*>(buf.get());
3565+
ptr[0] = POINT_CONVERSION_UNCOMPRESSED;
3566+
x.encodePaddedInto(ptr + 1, field_len);
3567+
y.encodePaddedInto(ptr + 1 + field_len, field_len);
3568+
3569+
auto point = ECPointPointer::New(group);
3570+
if (!point) return false;
3571+
if (!point.setFromBuffer({ptr, uncompressed_len}, group)) return false;
3572+
return EC_KEY_set_public_key(key_.get(), point.get()) == 1;
35433573
}
35443574

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

0 commit comments

Comments
 (0)