From: Jérôme Benoit Date: Tue, 7 Apr 2026 20:57:22 +0000 (+0200) Subject: refactor(ocpp): use Node.js crypto for EC curve derivation X-Git-Tag: ocpp-server@v4.4.0~4 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=05820aae196f01dcee2cdf82dbbbcdde69841d4a;p=e-mobility-charging-stations-simulator.git refactor(ocpp): use Node.js crypto for EC curve derivation Replace manual ASN.1 OID hex substring matching with crypto.createPublicKey which parses the DER structure via OpenSSL, validates the EC point, and returns the named curve directly. Map Node.js curve names (e.g. prime256v1) to SigningMethodEnumType. --- diff --git a/src/charging-station/ocpp/OCPPSignedMeterValueUtils.ts b/src/charging-station/ocpp/OCPPSignedMeterValueUtils.ts index 675abcc2..c1760337 100644 --- a/src/charging-station/ocpp/OCPPSignedMeterValueUtils.ts +++ b/src/charging-station/ocpp/OCPPSignedMeterValueUtils.ts @@ -1,3 +1,5 @@ +import { createPublicKey } from 'node:crypto' + import { BaseError } from '../../exception/index.js' import { PublicKeyWithSignedMeterValueEnumType, @@ -24,27 +26,33 @@ export interface SigningConfig { signingMethod?: SigningMethodEnumType } -// EC curve OID hex → SigningMethodEnumType (OCA Application Note Table 12) -const EC_CURVE_OID_MAP = new Map([ - ['06052b8104000a', SigningMethodEnumType.ECDSA_secp256k1_SHA256], - ['06052b8104001f', SigningMethodEnumType.ECDSA_secp192k1_SHA256], - ['06052b81040022', SigningMethodEnumType.ECDSA_secp384r1_SHA256], - ['06082a8648ce3d030101', SigningMethodEnumType.ECDSA_secp192r1_SHA256], - ['06082a8648ce3d030107', SigningMethodEnumType.ECDSA_secp256r1_SHA256], - ['06092b240303020801010b', SigningMethodEnumType.ECDSA_brainpool384r1_SHA256], - ['06092b2403030208010107', SigningMethodEnumType.ECDSA_brainpool256r1_SHA256], +const NODE_CURVE_TO_SIGNING_METHOD = new Map([ + ['brainpoolP256r1', SigningMethodEnumType.ECDSA_brainpool256r1_SHA256], + ['brainpoolP384r1', SigningMethodEnumType.ECDSA_brainpool384r1_SHA256], + ['prime192v1', SigningMethodEnumType.ECDSA_secp192r1_SHA256], + ['prime256v1', SigningMethodEnumType.ECDSA_secp256r1_SHA256], + ['secp192k1', SigningMethodEnumType.ECDSA_secp192k1_SHA256], + ['secp256k1', SigningMethodEnumType.ECDSA_secp256k1_SHA256], + ['secp384r1', SigningMethodEnumType.ECDSA_secp384r1_SHA256], ]) export const deriveSigningMethodFromPublicKeyHex = ( publicKeyHex: string ): SigningMethodEnumType | undefined => { - const hex = publicKeyHex.toLowerCase().replace(/[^0-9a-f]/g, '') - for (const [oid, method] of EC_CURVE_OID_MAP) { - if (hex.includes(oid)) { - return method + try { + const key = createPublicKey({ + format: 'der', + key: Buffer.from(publicKeyHex, 'hex'), + type: 'spki', + }) + if (key.asymmetricKeyType !== 'ec') { + return undefined } + const namedCurve = key.asymmetricKeyDetails?.namedCurve + return namedCurve != null ? NODE_CURVE_TO_SIGNING_METHOD.get(namedCurve) : undefined + } catch { + return undefined } - return undefined } export interface SigningPrerequisiteResult { diff --git a/tests/charging-station/ocpp/OCPPSignedMeterValueUtils.test.ts b/tests/charging-station/ocpp/OCPPSignedMeterValueUtils.test.ts index fd277d4f..2109c6b1 100644 --- a/tests/charging-station/ocpp/OCPPSignedMeterValueUtils.test.ts +++ b/tests/charging-station/ocpp/OCPPSignedMeterValueUtils.test.ts @@ -91,8 +91,9 @@ await describe('SignedMeterValueUtils', async () => { ) }) - await it('should derive secp256r1 from key with OID 06082a8648ce3d030107', () => { - const secp256r1Key = '3059301306072a8648ce3d020106082a8648ce3d03010703420004abcd' + await it('should derive secp256r1 from valid prime256v1 key', () => { + const secp256r1Key = + '3059301306072a8648ce3d020106082a8648ce3d03010703420004effb01ac755dad9574b89873e42e9f2f7a33a3b106f2d1662d0909a16f1e5a5355b022fec98119f1877b958f2240fc9c0e113cb94ee75b44c9ef79c9ed8627e0' assert.strictEqual( deriveSigningMethodFromPublicKeyHex(secp256r1Key), SigningMethodEnumType.ECDSA_secp256r1_SHA256