55// deno-lint-ignore-file prefer-primordials
66
77import {
8+ op_node_dh_check ,
89 op_node_dh_compute_secret ,
910 op_node_dh_keys_generate_and_export ,
1011 op_node_diffie_hellman ,
1112 op_node_ecdh_compute_public_key ,
1213 op_node_ecdh_compute_secret ,
1314 op_node_ecdh_encode_pubkey ,
1415 op_node_ecdh_generate_keys ,
16+ op_node_ecdh_validate_private_key ,
17+ op_node_ecdh_validate_public_key ,
1518 op_node_gen_prime ,
1619} from "ext:core/ops" ;
1720
@@ -21,6 +24,7 @@ import {
2124} from "ext:deno_node/internal/util/types.ts" ;
2225import {
2326 ERR_CRYPTO_ECDH_INVALID_FORMAT ,
27+ ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY ,
2428 ERR_CRYPTO_INCOMPATIBLE_KEY ,
2529 ERR_CRYPTO_UNKNOWN_DH_GROUP ,
2630 ERR_INVALID_ARG_TYPE ,
@@ -177,8 +181,7 @@ export class DiffieHellmanImpl {
177181
178182 this . #checkGenerator( ) ;
179183
180- // TODO(lev): actually implement this value
181- this . verifyError = 0 ;
184+ this . verifyError = op_node_dh_check ( this . #prime, this . #generator) ;
182185 }
183186
184187 #checkGenerator( ) : number {
@@ -1338,10 +1341,30 @@ export function ECDH(curve: string) {
13381341 return new ECDHImpl ( curve ) ;
13391342}
13401343
1344+ function validateEcdhFormat ( format : ECDHKeyFormat | string ) : void {
1345+ if (
1346+ format !== "compressed" &&
1347+ format !== "uncompressed" &&
1348+ format !== "hybrid"
1349+ ) {
1350+ throw new ERR_CRYPTO_ECDH_INVALID_FORMAT ( String ( format ) ) ;
1351+ }
1352+ }
1353+
1354+ function ecdhEncode (
1355+ buffer : Buffer ,
1356+ encoding ?: BinaryToTextEncoding | "buffer" ,
1357+ ) : Buffer | string {
1358+ if ( encoding === undefined || encoding === "buffer" ) {
1359+ return buffer ;
1360+ }
1361+ return buffer . toString ( encoding ) ;
1362+ }
1363+
13411364export class ECDHImpl {
13421365 #curve: EllipticCurve ; // the selected curve
1343- #privbuf: Buffer ; // the private key
1344- #pubbuf: Buffer ; // the public key
1366+ #privbuf: Buffer | null = null ; // the private key
1367+ #pubbuf: Buffer | null = null ; // the public key
13451368
13461369 constructor ( curve : string ) {
13471370 validateString ( curve , "curve" ) ;
@@ -1352,8 +1375,6 @@ export class ECDHImpl {
13521375 }
13531376
13541377 this . #curve = c ;
1355- this . #pubbuf = Buffer . alloc ( this . #curve. publicKeySize ) ;
1356- this . #privbuf = Buffer . alloc ( this . #curve. privateKeySize ) ;
13571378 }
13581379
13591380 static convertKey (
@@ -1424,19 +1445,41 @@ export class ECDHImpl {
14241445 ) : string ;
14251446 computeSecret (
14261447 otherPublicKey : ArrayBufferView | string ,
1427- _inputEncoding ?: BinaryToTextEncoding ,
1428- _outputEncoding ?: BinaryToTextEncoding ,
1448+ inputEncoding ?: BinaryToTextEncoding ,
1449+ outputEncoding ?: BinaryToTextEncoding ,
14291450 ) : Buffer | string {
1451+ if ( this . #privbuf === null ) {
1452+ throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY ( ) ;
1453+ }
1454+
1455+ const otherBuf = typeof otherPublicKey === "string"
1456+ ? Buffer . from ( otherPublicKey , inputEncoding )
1457+ : Buffer . from (
1458+ otherPublicKey . buffer ,
1459+ otherPublicKey . byteOffset ,
1460+ otherPublicKey . byteLength ,
1461+ ) ;
1462+
14301463 const secretBuf = Buffer . alloc ( this . #curve. sharedSecretSize ) ;
14311464
1432- op_node_ecdh_compute_secret (
1433- this . #curve. name ,
1434- this . #privbuf,
1435- otherPublicKey ,
1436- secretBuf ,
1437- ) ;
1465+ try {
1466+ op_node_ecdh_compute_secret (
1467+ this . #curve. name ,
1468+ this . #privbuf,
1469+ this . #pubbuf,
1470+ otherBuf ,
1471+ secretBuf ,
1472+ ) ;
1473+ } catch ( e ) {
1474+ // deno-lint-ignore no-explicit-any
1475+ const err = e as any ;
1476+ if ( err && err . message === "Invalid key pair" ) {
1477+ throw new Error ( "Invalid key pair" ) ;
1478+ }
1479+ throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY ( ) ;
1480+ }
14381481
1439- return secretBuf ;
1482+ return ecdhEncode ( secretBuf , outputEncoding ?? "buffer" ) ;
14401483 }
14411484
14421485 generateKeys ( ) : Buffer ;
@@ -1445,31 +1488,41 @@ export class ECDHImpl {
14451488 encoding ?: BinaryToTextEncoding ,
14461489 format : ECDHKeyFormat = "uncompressed" ,
14471490 ) : Buffer | string {
1448- this . #pubbuf = Buffer . alloc (
1491+ validateEcdhFormat ( format ) ;
1492+ const pubbuf = Buffer . alloc (
14491493 format == "compressed"
14501494 ? this . #curve. publicKeySizeCompressed
14511495 : this . #curve. publicKeySize ,
14521496 ) ;
1497+ const privbuf = Buffer . alloc ( this . #curve. privateKeySize ) ;
14531498 op_node_ecdh_generate_keys (
14541499 this . #curve. name ,
1455- this . # pubbuf,
1456- this . # privbuf,
1500+ pubbuf ,
1501+ privbuf ,
14571502 format ,
14581503 ) ;
1504+ this . #pubbuf = pubbuf ;
1505+ this . #privbuf = privbuf ;
14591506
1460- if ( encoding !== undefined ) {
1461- return this . #pubbuf. toString ( encoding ) ;
1507+ if ( format === "hybrid" ) {
1508+ const compressedBuf = Buffer . from ( op_node_ecdh_encode_pubkey (
1509+ this . #curve. name ,
1510+ pubbuf ,
1511+ true ,
1512+ ) ) ;
1513+ pubbuf [ 0 ] = compressedBuf [ 0 ] + 4 ;
14621514 }
1463- return this . #pubbuf;
1515+
1516+ return ecdhEncode ( pubbuf , encoding ?? "buffer" ) ;
14641517 }
14651518
14661519 getPrivateKey ( ) : Buffer ;
14671520 getPrivateKey ( encoding : BinaryToTextEncoding ) : string ;
14681521 getPrivateKey ( encoding ?: BinaryToTextEncoding ) : Buffer | string {
1469- if ( encoding !== undefined ) {
1470- return this . #privbuf . toString ( encoding ) ;
1522+ if ( this . #privbuf === null ) {
1523+ throw new Error ( "Failed to get ECDH private key" ) ;
14711524 }
1472- return this . #privbuf;
1525+ return ecdhEncode ( this . #privbuf, encoding ?? "buffer" ) ;
14731526 }
14741527
14751528 getPublicKey ( ) : Buffer ;
@@ -1478,6 +1531,10 @@ export class ECDHImpl {
14781531 encoding ?: BinaryToTextEncoding ,
14791532 format : ECDHKeyFormat = "uncompressed" ,
14801533 ) : Buffer | string {
1534+ if ( this . #pubbuf === null ) {
1535+ throw new Error ( "Failed to get ECDH public key" ) ;
1536+ }
1537+ validateEcdhFormat ( format ) ;
14811538 const pubbuf = Buffer . from ( op_node_ecdh_encode_pubkey (
14821539 this . #curve. name ,
14831540 this . #pubbuf,
@@ -1491,10 +1548,7 @@ export class ECDHImpl {
14911548 ) ) ;
14921549 pubbuf [ 0 ] = compressedBuf [ 0 ] + 4 ;
14931550 }
1494- if ( encoding !== undefined ) {
1495- return pubbuf . toString ( encoding ) ;
1496- }
1497- return pubbuf ;
1551+ return ecdhEncode ( pubbuf , encoding ?? "buffer" ) ;
14981552 }
14991553
15001554 setPrivateKey ( privateKey : ArrayBufferView ) : void ;
@@ -1503,21 +1557,25 @@ export class ECDHImpl {
15031557 privateKey : ArrayBufferView | string ,
15041558 encoding ?: BinaryToTextEncoding ,
15051559 ) : Buffer | string {
1506- this . # privbuf = typeof privateKey === "string"
1560+ const privbuf = typeof privateKey === "string"
15071561 ? Buffer . from ( privateKey , encoding )
1508- : Buffer . from ( privateKey ) ;
1509- this . #pubbuf = Buffer . alloc ( this . #curve. publicKeySize ) ;
1510-
1511- op_node_ecdh_compute_public_key (
1512- this . #curve. name ,
1513- this . #privbuf,
1514- this . #pubbuf,
1515- ) ;
1562+ : Buffer . from (
1563+ privateKey . buffer ,
1564+ privateKey . byteOffset ,
1565+ privateKey . byteLength ,
1566+ ) ;
15161567
1517- if ( encoding !== undefined ) {
1518- return this . #pubbuf . toString ( encoding ) ;
1568+ if ( ! op_node_ecdh_validate_private_key ( this . #curve . name , privbuf ) ) {
1569+ throw new Error ( "Private key is not valid for specified curve" ) ;
15191570 }
1520- return this . #pubbuf;
1571+
1572+ const pubbuf = Buffer . alloc ( this . #curve. publicKeySize ) ;
1573+ op_node_ecdh_compute_public_key ( this . #curve. name , privbuf , pubbuf ) ;
1574+
1575+ this . #privbuf = privbuf ;
1576+ this . #pubbuf = pubbuf ;
1577+
1578+ return pubbuf ;
15211579 }
15221580
15231581 setPublicKey ( publicKey : ArrayBufferView ) : void ;
@@ -1526,9 +1584,17 @@ export class ECDHImpl {
15261584 publicKey : ArrayBufferView | string ,
15271585 encoding ?: BinaryToTextEncoding ,
15281586 ) : void {
1529- this . # pubbuf = typeof publicKey === "string"
1587+ const pubbuf = typeof publicKey === "string"
15301588 ? Buffer . from ( publicKey , encoding )
1531- : Buffer . from ( publicKey ) ;
1589+ : Buffer . from (
1590+ publicKey . buffer ,
1591+ publicKey . byteOffset ,
1592+ publicKey . byteLength ,
1593+ ) ;
1594+ if ( ! op_node_ecdh_validate_public_key ( this . #curve. name , pubbuf ) ) {
1595+ throw new Error ( "Failed to convert Buffer to EC_POINT" ) ;
1596+ }
1597+ this . #pubbuf = pubbuf ;
15321598 }
15331599}
15341600
0 commit comments