@@ -21,6 +21,7 @@ import {
2121} from "ext:deno_node/internal/util/types.ts" ;
2222import {
2323 ERR_CRYPTO_ECDH_INVALID_FORMAT ,
24+ ERR_CRYPTO_INCOMPATIBLE_KEY ,
2425 ERR_CRYPTO_UNKNOWN_DH_GROUP ,
2526 ERR_INVALID_ARG_TYPE ,
2627 ERR_INVALID_ARG_VALUE ,
@@ -1539,6 +1540,45 @@ ECDH.prototype.setPublicKey = deprecate(
15391540 "DEP0031" ,
15401541) ;
15411542
1543+ function statelessDH (
1544+ privateKeyObject : KeyObject ,
1545+ publicKeyObject : KeyObject ,
1546+ ) : Buffer {
1547+ // getKeyObjectHandle validates key.type and throws ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE
1548+ // for incompatible key kinds (e.g. secret instead of private), so we must
1549+ // call it before doing the asymmetricKeyType cross-check below.
1550+ const privateKey = getKeyObjectHandle ( privateKeyObject , kConsumePrivate ) ;
1551+ const publicKey = getKeyObjectHandle ( publicKeyObject , kConsumePublic ) ;
1552+
1553+ // Check that the asymmetric key types are compatible. EC and DH report
1554+ // mismatching domain parameters from the underlying op when the curves or
1555+ // group parameters differ; everything else (e.g. x25519 vs x448) is a key
1556+ // type mismatch and should surface as ERR_CRYPTO_INCOMPATIBLE_KEY.
1557+ const privType = privateKeyObject . asymmetricKeyType ;
1558+ const pubType = publicKeyObject . asymmetricKeyType ;
1559+ if ( privType !== undefined && pubType !== undefined && privType !== pubType ) {
1560+ throw new ERR_CRYPTO_INCOMPATIBLE_KEY (
1561+ "key types for Diffie-Hellman" ,
1562+ `${ privType } and ${ pubType } ` ,
1563+ ) ;
1564+ }
1565+
1566+ try {
1567+ const bytes = op_node_diffie_hellman ( privateKey , publicKey ) ;
1568+ return Buffer . from ( bytes ) ;
1569+ } catch ( err ) {
1570+ const e = err as Error & { code ?: string } ;
1571+ if ( e && typeof e . message === "string" ) {
1572+ if ( e . message . includes ( "mismatching domain parameters" ) ) {
1573+ e . code = "ERR_OSSL_MISMATCHING_DOMAIN_PARAMETERS" ;
1574+ } else if ( e . message . includes ( "failed during derivation" ) ) {
1575+ e . code = "ERR_OSSL_FAILED_DURING_DERIVATION" ;
1576+ }
1577+ }
1578+ throw e ;
1579+ }
1580+ }
1581+
15421582export function diffieHellman (
15431583 options : {
15441584 privateKey : KeyObject ;
@@ -1563,23 +1603,15 @@ export function diffieHellman(
15631603
15641604 if ( callback ) {
15651605 try {
1566- const privateKey = getKeyObjectHandle (
1567- options . privateKey ,
1568- kConsumePrivate ,
1569- ) ;
1570- const publicKey = getKeyObjectHandle ( options . publicKey , kConsumePublic ) ;
1571- const bytes = op_node_diffie_hellman ( privateKey , publicKey ) ;
1572- callback ( null , Buffer . from ( bytes ) ) ;
1606+ const secret = statelessDH ( options . privateKey , options . publicKey ) ;
1607+ callback ( null , secret ) ;
15731608 } catch ( err ) {
15741609 callback ( err as Error ) ;
15751610 }
15761611 return ;
15771612 }
15781613
1579- const privateKey = getKeyObjectHandle ( options . privateKey , kConsumePrivate ) ;
1580- const publicKey = getKeyObjectHandle ( options . publicKey , kConsumePublic ) ;
1581- const bytes = op_node_diffie_hellman ( privateKey , publicKey ) ;
1582- return Buffer . from ( bytes ) ;
1614+ return statelessDH ( options . privateKey , options . publicKey ) ;
15831615}
15841616
15851617export default {
0 commit comments