]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor(tests): harmonize crypto test data and improve test quality
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 7 Apr 2026 22:52:42 +0000 (00:52 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 7 Apr 2026 22:52:42 +0000 (00:52 +0200)
- Reorganize OCPP20CertificateTestData: move CA/leaf certificates into
  Real X.509 section, simplify JSDoc to consistent one-line format
- Add round-trip tests (derLength → readDerLength) replacing duplicate
  raw byte assertions
- Add semantic test for extractDerIssuer (DER hash vs string DN hash)
- Replace eslint-disable || workaround with assert.match regex
- Update Asn1DerUtils @description to cover parsing functions

tests/charging-station/ocpp/2.0/Asn1DerUtils.test.ts
tests/charging-station/ocpp/2.0/OCPP20CertificateManager.test.ts
tests/charging-station/ocpp/2.0/OCPP20CertificateTestData.ts

index cdb6ab7a232e3d4a10f018fcf2fa7131db99785b..2523137908699af8508ebfbd5ad62eea5201bf7a 100644 (file)
@@ -1,10 +1,10 @@
 /**
  * @file Tests for Asn1DerUtils
- * @description Unit tests for ASN.1 DER encoding primitives and PKCS#10 CSR generation
+ * @description Unit tests for ASN.1 DER encoding, parsing, and PKCS#10 CSR generation
  */
 
 import assert from 'node:assert/strict'
-import { X509Certificate } from 'node:crypto'
+import { hash, X509Certificate } from 'node:crypto'
 import { afterEach, describe, it } from 'node:test'
 
 import {
@@ -118,25 +118,25 @@ await describe('ASN.1 DER encoding utilities', async () => {
   })
 
   await describe('readDerLength', async () => {
-    await it('should parse short form length', () => {
-      const buf = Buffer.from([42])
-      const result = readDerLength(buf, 0)
+    await it('should round-trip with derLength for short form', () => {
+      const encoded = derLength(42)
+      const result = readDerLength(encoded, 0)
       assert.strictEqual(result.length, 42)
-      assert.strictEqual(result.end, 1)
+      assert.strictEqual(result.end, encoded.length)
     })
 
-    await it('should parse single-byte long form (0x81)', () => {
-      const buf = Buffer.from([0x81, 200])
-      const result = readDerLength(buf, 0)
+    await it('should round-trip with derLength for single-byte long form', () => {
+      const encoded = derLength(200)
+      const result = readDerLength(encoded, 0)
       assert.strictEqual(result.length, 200)
-      assert.strictEqual(result.end, 2)
+      assert.strictEqual(result.end, encoded.length)
     })
 
-    await it('should parse two-byte long form (0x82)', () => {
-      const buf = Buffer.from([0x82, 0x01, 0x2c])
-      const result = readDerLength(buf, 0)
+    await it('should round-trip with derLength for two-byte long form', () => {
+      const encoded = derLength(300)
+      const result = readDerLength(encoded, 0)
       assert.strictEqual(result.length, 300)
-      assert.strictEqual(result.end, 3)
+      assert.strictEqual(result.end, encoded.length)
     })
 
     await it('should throw RangeError for empty buffer', () => {
@@ -177,6 +177,14 @@ await describe('ASN.1 DER encoding utilities', async () => {
       assert.strictEqual(issuerDer[0], 0x30)
     })
 
+    await it('should extract issuer that differs from hashing the string DN', () => {
+      const x509 = new X509Certificate(VALID_X509_PEM_CERTIFICATE)
+      const issuerDer = extractDerIssuer(x509.raw)
+      const derHash = hash('sha256', issuerDer, 'hex')
+      const stringHash = hash('sha256', x509.issuer, 'hex')
+      assert.notStrictEqual(derHash, stringHash)
+    })
+
     await it('should produce consistent output for the same certificate', () => {
       const x509 = new X509Certificate(VALID_X509_PEM_CERTIFICATE)
       const first = extractDerIssuer(x509.raw)
index c29251c8f89872cb8154238f1661bca9d6c21a38..b6a0aad913eaf58af713515c83ef42a6df1b6626 100644 (file)
@@ -490,11 +490,7 @@ await describe('I02-I04 - ISO15118 Certificate Management', async () => {
       const result = manager.validateCertificateX509(brokenChain)
 
       assert.strictEqual(result.valid, false)
-      assert.ok(
-        // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
-        result.reason?.includes('issuer mismatch') ||
-          result.reason?.includes('signature verification failed')
-      )
+      assert.match(result.reason ?? '', /issuer mismatch|signature verification failed/)
     })
 
     await it('should return invalid when chain has expired intermediate', () => {
index 2164717a961d7c83521fbfece578bfc86a227a55..a833226f850e9618c427d4f4f9705bc666bae817 100644 (file)
@@ -97,39 +97,12 @@ SIb3DQEBCwUAA0EAexpired==
  */
 export const EMPTY_PEM_CERTIFICATE = ''
 
-/**
- * Real EC P-256 CA certificate (CN=TestRootCA, valid 2026-2036).
- * Used as issuer for VALID_X509_LEAF_CERTIFICATE.
- */
-export const VALID_X509_CA_CERTIFICATE = `-----BEGIN CERTIFICATE-----
-MIIBGDCBwAIJAMY5KBDzNkHGMAoGCCqGSM49BAMCMBUxEzARBgNVBAMMClRlc3RS
-b290Q0EwHhcNMjYwNDA3MjIxMjU1WhcNMzYwNDA0MjIxMjU1WjAVMRMwEQYDVQQD
-DApUZXN0Um9vdENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhOoqHSLrnwVr
-0Nu78E9rGDQmhGK1qvr2W7ye7yXMHgfFGYMuVr7ejCj6TXk2YPSS8ADRwCRj8R6S
-JFomGI2soDAKBggqhkjOPQQDAgNHADBEAiBDCuKOo0v3y/ZTGSf20GQyTtmfibV5
-5t1yXJkVTudOMgIgWqQXoyjI/k2s+T9U38X4S9yTeMkjeNb3FEYVq5kaA5w=
------END CERTIFICATE-----`
-
-/**
- * Real EC P-256 leaf certificate (CN=TestLeaf, valid 2026-2036).
- * Signed by VALID_X509_CA_CERTIFICATE.
- */
-export const VALID_X509_LEAF_CERTIFICATE = `-----BEGIN CERTIFICATE-----
-MIIBGDCBvgIJAJn8LXzPXkayMAoGCCqGSM49BAMCMBUxEzARBgNVBAMMClRlc3RS
-b290Q0EwHhcNMjYwNDA3MjIxMjU1WhcNMzYwNDA0MjIxMjU1WjATMREwDwYDVQQD
-DAhUZXN0TGVhZjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDMWqNhqXlWIksJi
-fYrEQLdPlWG4zAfvc/1q7npD5d+OJu4uwbseA2uXf8/wHgQYrpD3jkXT4b/amhyv
-W1dCq+0wCgYIKoZIzj0EAwIDSQAwRgIhAPnXKKIs+8sE+W+3AH9zE3Z51I1ndCks
-wD0Gud+kCORgAiEArgyP/lVR0Vh9NWe8iTNVXOyc4s8Jn0J+CF9UsUIGuFA=
------END CERTIFICATE-----`
-
 // ============================================================================
 // Real X.509 Certificates (parseable by node:crypto X509Certificate)
 // ============================================================================
 
 /**
- * Valid self-signed X.509 certificate (EC P-256, CN=TestCA, valid 2026-2036).
- * Parseable by node:crypto X509Certificate for X.509 structural validation tests.
+ * Self-signed X.509 certificate (EC P-256, CN=TestCA, valid 2026-2036).
  */
 export const VALID_X509_PEM_CERTIFICATE = `-----BEGIN CERTIFICATE-----
 MIICBjCCAawCCQDuW/VTwcEHDTAKBggqhkjOPQQDAjARMQ8wDQYDVQQDDAZUZXN0
@@ -147,7 +120,6 @@ IHCV6XLaqZACIHEFQs2oVgHqMTxx22E7ZffFpA5hNP021SFwJ9ujSYQj
 
 /**
  * Expired self-signed X.509 certificate (EC P-256, CN=ExpiredTestCA, valid 2020-2021).
- * Parseable by node:crypto X509Certificate; triggers expiration check.
  */
 export const EXPIRED_X509_PEM_CERTIFICATE = `-----BEGIN CERTIFICATE-----
 MIIBLjCB1qADAgECAhRHkkXuRncB5xOMPnTt0pqA/uWOsTAKBggqhkjOPQQDAjAY
@@ -158,3 +130,29 @@ nR2Dm+OL4pHpa31dWSPRPeAZYUlsz8zER/rARNUwCgYIKoZIzj0EAwIDRwAwRAIg
 XvHyZ5eCRgOTBCMBDXvxxZXGaWFsrhq066F0MKd6D1ICICrQl8LxyYh72Bc0gWBG
 2LQtv+sPK1CmsMqp8G8DiFqY
 -----END CERTIFICATE-----`
+
+/**
+ * CA certificate (EC P-256, CN=TestRootCA, valid 2026-2036).
+ * Issuer for VALID_X509_LEAF_CERTIFICATE.
+ */
+export const VALID_X509_CA_CERTIFICATE = `-----BEGIN CERTIFICATE-----
+MIIBGDCBwAIJAMY5KBDzNkHGMAoGCCqGSM49BAMCMBUxEzARBgNVBAMMClRlc3RS
+b290Q0EwHhcNMjYwNDA3MjIxMjU1WhcNMzYwNDA0MjIxMjU1WjAVMRMwEQYDVQQD
+DApUZXN0Um9vdENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhOoqHSLrnwVr
+0Nu78E9rGDQmhGK1qvr2W7ye7yXMHgfFGYMuVr7ejCj6TXk2YPSS8ADRwCRj8R6S
+JFomGI2soDAKBggqhkjOPQQDAgNHADBEAiBDCuKOo0v3y/ZTGSf20GQyTtmfibV5
+5t1yXJkVTudOMgIgWqQXoyjI/k2s+T9U38X4S9yTeMkjeNb3FEYVq5kaA5w=
+-----END CERTIFICATE-----`
+
+/**
+ * Leaf certificate (EC P-256, CN=TestLeaf, valid 2026-2036).
+ * Signed by VALID_X509_CA_CERTIFICATE.
+ */
+export const VALID_X509_LEAF_CERTIFICATE = `-----BEGIN CERTIFICATE-----
+MIIBGDCBvgIJAJn8LXzPXkayMAoGCCqGSM49BAMCMBUxEzARBgNVBAMMClRlc3RS
+b290Q0EwHhcNMjYwNDA3MjIxMjU1WhcNMzYwNDA0MjIxMjU1WjATMREwDwYDVQQD
+DAhUZXN0TGVhZjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDMWqNhqXlWIksJi
+fYrEQLdPlWG4zAfvc/1q7npD5d+OJu4uwbseA2uXf8/wHgQYrpD3jkXT4b/amhyv
+W1dCq+0wCgYIKoZIzj0EAwIDSQAwRgIhAPnXKKIs+8sE+W+3AH9zE3Z51I1ndCks
+wD0Gud+kCORgAiEArgyP/lVR0Vh9NWe8iTNVXOyc4s8Jn0J+CF9UsUIGuFA=
+-----END CERTIFICATE-----`