]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor(ocpp): use Node.js crypto for EC curve derivation
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 7 Apr 2026 20:57:22 +0000 (22:57 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 7 Apr 2026 20:57:22 +0000 (22:57 +0200)
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.

src/charging-station/ocpp/OCPPSignedMeterValueUtils.ts
tests/charging-station/ocpp/OCPPSignedMeterValueUtils.test.ts

index 675abcc2746ef30524e471edf22f281e0c0c9d88..c17603377b12aa39f638ef85bdc0c995f021619b 100644 (file)
@@ -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<string, SigningMethodEnumType>([
-  ['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<string, SigningMethodEnumType>([
+  ['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 {
index fd277d4f07e3463d796d7b233b6465e2fbf4dc84..2109c6b1fac487b33fe4386924c42c6ed6c6e307 100644 (file)
@@ -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