]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
fix(ocpp): conform signingMethod to OCA spec and fix template curve mismatch
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 7 Apr 2026 19:30:56 +0000 (21:30 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 7 Apr 2026 19:30:56 +0000 (21:30 +0200)
- Set signingMethod to empty string when using OCMF encoding per OCA
  Application Note Table 11: SA field already in signedMeterData
- Add FiscalMetering.SigningMethod=ECDSA-secp256k1-SHA256 to
  keba-ocpp2-signed template to match the secp256k1 public key from
  OCA spec §5.3 example
- Update tests to expect empty signingMethod for OCMF payloads
- Remove unused SigningMethodEnumType imports from test files

src/assets/station-templates/keba-ocpp2-signed.station-template.json
src/charging-station/ocpp/OCPPSignedMeterDataGenerator.ts
tests/charging-station/ocpp/1.6/OCPP16ServiceUtils-SignedMeterValues.test.ts
tests/charging-station/ocpp/2.0/OCPP20RequestBuilders-SignedMeterValues.test.ts
tests/charging-station/ocpp/OCPPSignedMeterDataGenerator.test.ts

index 7d078a5846ef9ecb0ec73ffa097b5c397c428f87..51fb5319f5c2ed629bf247591b75cafcf4e73da0 100644 (file)
         "key": "FiscalMetering.PublicKey",
         "readonly": true,
         "value": "3056301006072a8648ce3d020106052b8104000a03420004460a02ba2766d9c44f023ecc0e4e58644a87add1aadd6317e5fe4dccdb29b163a01d8a6297c84bc530f86431e92f8d46ab37830247c05cbd92fac252929e7f61"
+      },
+      {
+        "key": "FiscalMetering.SigningMethod",
+        "readonly": true,
+        "value": "ECDSA-secp256k1-SHA256"
       }
     ]
   },
index bb09b3dfea95d4d87ef520e6843446e644f814b9..cd49afa6945ec47980a9e036f595440a8aed9092 100644 (file)
@@ -13,7 +13,7 @@ export interface SignedMeterData extends JsonObject {
   encodingMethod: EncodingMethodEnumType
   publicKey: string
   signedMeterData: string
-  signingMethod: SigningMethodEnumType
+  signingMethod: '' | SigningMethodEnumType
 }
 
 export interface SignedMeterDataParams {
@@ -76,12 +76,15 @@ export const generateSignedMeterData = (
 
   const simulatedSignature = createHash('sha256').update(JSON.stringify(ocmfPayload)).digest('hex')
 
+  // OCMF includes the signing algorithm in the SA field of signedMeterData.
+  // Per OCA Application Note Table 11: "If it is already included in the
+  // signedMeterData, then this SHALL be an empty string."
   const ocmfString = `OCMF|${JSON.stringify(ocmfPayload)}|{"SA":"${resolvedSigningMethod}","SD":"${simulatedSignature}"}`
 
   return {
     encodingMethod: DEFAULT_ENCODING_METHOD,
     publicKey: publicKeyHex != null ? buildPublicKeyValue(publicKeyHex) : '',
     signedMeterData: Buffer.from(ocmfString).toString('base64'),
-    signingMethod: resolvedSigningMethod,
+    signingMethod: '',
   }
 }
index 22620b3291adc041713d720ab5567d9a03a5bebf..37011e1f8b7c57b6a9a33aed7988ab3f732bf8c7 100644 (file)
@@ -24,7 +24,6 @@ import {
   type OCPP16SignedMeterValue,
   OCPP16VendorParametersKey,
   OCPPVersion,
-  SigningMethodEnumType,
 } from '../../../../src/types/index.js'
 import { standardCleanup, withMockTimers } from '../../../helpers/TestLifecycleHelpers.js'
 import { createMockChargingStation } from '../../ChargingStationTestUtils.js'
@@ -298,7 +297,7 @@ await describe('OCPP 1.6 — Signed MeterValues', async () => {
       assert.strictEqual(typeof parsed.signedMeterData, 'string')
       assert.strictEqual(typeof parsed.publicKey, 'string')
       assert.strictEqual(parsed.encodingMethod, EncodingMethodEnumType.OCMF)
-      assert.strictEqual(parsed.signingMethod, SigningMethodEnumType.ECDSA_secp256r1_SHA256)
+      assert.strictEqual(parsed.signingMethod, '')
     })
   })
 
index 08ceddd4eccda8cc32c8ea7c06a837eb2defd388..404dcf1c4cbb6fd9d6e700d2b5cc7307e54eadce 100644 (file)
@@ -22,7 +22,6 @@ import {
   OCPPVersion,
   PublicKeyWithSignedMeterValueEnumType,
   type SampledValueTemplate,
-  SigningMethodEnumType,
 } from '../../../../src/types/index.js'
 import { Constants } from '../../../../src/utils/index.js'
 import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
@@ -65,10 +64,7 @@ await describe('OCPP 2.0 Signed Meter Values', async () => {
       )
 
       assert.ok(sampledValue.signedMeterValue != null)
-      assert.strictEqual(
-        sampledValue.signedMeterValue.signingMethod,
-        SigningMethodEnumType.ECDSA_secp256r1_SHA256
-      )
+      assert.strictEqual(sampledValue.signedMeterValue.signingMethod, '')
       assert.strictEqual(sampledValue.signedMeterValue.encodingMethod, EncodingMethodEnumType.OCMF)
     })
 
@@ -243,10 +239,7 @@ await describe('OCPP 2.0 Signed Meter Values', async () => {
       ) as OCPP20SampledValue | undefined
       assert.notStrictEqual(energySampledValue, undefined)
       assert.ok(energySampledValue?.signedMeterValue != null)
-      assert.strictEqual(
-        energySampledValue.signedMeterValue.signingMethod,
-        SigningMethodEnumType.ECDSA_secp256r1_SHA256
-      )
+      assert.strictEqual(energySampledValue.signedMeterValue.signingMethod, '')
       assert.strictEqual(
         energySampledValue.signedMeterValue.encodingMethod,
         EncodingMethodEnumType.OCMF
index ad0309d3e82ad3345dd7aef8d893881fda605098..d724701ed2115ad559c2f61caf36e2e0be275c32 100644 (file)
@@ -23,7 +23,6 @@ import {
   EncodingMethodEnumType,
   MeterValueContext,
   MeterValueUnit,
-  SigningMethodEnumType,
 } from '../../../src/types/index.js'
 
 const DEFAULT_PARAMS: SignedMeterDataParams = {
@@ -60,10 +59,10 @@ await describe('SignedMeterDataGenerator', async () => {
     assert.ok(decoded.startsWith('OCMF|'))
   })
 
-  await it('should set signingMethod to ECDSA-secp256r1-SHA256', () => {
+  await it('should set signingMethod to empty string per OCA spec when using OCMF', () => {
     const result = generateSignedMeterData(DEFAULT_PARAMS)
 
-    assert.strictEqual(result.signingMethod, SigningMethodEnumType.ECDSA_secp256r1_SHA256)
+    assert.strictEqual(result.signingMethod, '')
   })
 
   await it('should set encodingMethod to OCMF', () => {