@open-charging-cloud/chargy-core 0.11.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ import { ed448ph, ed448 } from '@noble/curves/ed448.js';
5
5
  import { p521, p384, p256 } from '@noble/curves/nist.js';
6
6
  import { secp256k1 } from '@noble/curves/secp256k1.js';
7
7
  import { ml_dsa87, ml_dsa65, ml_dsa44 } from '@noble/post-quantum/ml-dsa.js';
8
+ import { sha256 as sha256$1 } from '@noble/hashes/sha2.js';
8
9
  import { Buffer as Buffer$1 } from 'buffer';
9
10
  import { fileTypeFromBuffer } from 'file-type';
10
11
  import isURL from 'is-url-superb';
@@ -54,7 +55,7 @@ var IECCurves = /* @__PURE__ */ ((IECCurves2) => {
54
55
  IECCurves2["secp256k1"] = "secp256k1";
55
56
  IECCurves2["secp256r1"] = "secp256r1";
56
57
  IECCurves2["secp384r1"] = "secp384r1";
57
- IECCurves2["secp512r1"] = "secp512r1";
58
+ IECCurves2["secp521r1"] = "secp521r1";
58
59
  return IECCurves2;
59
60
  })(IECCurves || {});
60
61
  var IEncoding = /* @__PURE__ */ ((IEncoding2) => {
@@ -515,12 +516,45 @@ function SetHex(dv, hex, offset, reverse) {
515
516
  }
516
517
  return buf2hex(buffer);
517
518
  }
519
+ var meterTimeZone = "Europe/Berlin";
520
+ var statesItsOwnUTCOffset = /[+-]\d{2}:?\d{2}$/;
521
+ function timeZoneOffsetMinutes(instant, timeZone = meterTimeZone) {
522
+ const parts = new Intl.DateTimeFormat("en-US", {
523
+ timeZone,
524
+ hour12: false,
525
+ year: "numeric",
526
+ month: "2-digit",
527
+ day: "2-digit",
528
+ hour: "2-digit",
529
+ minute: "2-digit",
530
+ second: "2-digit"
531
+ }).formatToParts(instant);
532
+ const field = (type) => Number(parts.find((part) => part.type === type)?.value ?? "0");
533
+ const asUTC = Date.UTC(
534
+ field("year"),
535
+ field("month") - 1,
536
+ field("day"),
537
+ field("hour") % 24,
538
+ // Intl may report midnight as hour 24
539
+ field("minute"),
540
+ field("second")
541
+ );
542
+ return (asUTC - Math.floor(instant.getTime() / 1e3) * 1e3) / 6e4;
543
+ }
544
+ function meterLocalTime(timestamp) {
545
+ if (typeof timestamp !== "string")
546
+ return { moment: timestamp, offsetMinutes: timestamp.utcOffset() };
547
+ const parsed = moment.parseZone(timestamp);
548
+ return {
549
+ moment: parsed,
550
+ offsetMinutes: statesItsOwnUTCOffset.test(timestamp.trim()) ? parsed.utcOffset() : timeZoneOffsetMinutes(new Date(parsed.valueOf()))
551
+ };
552
+ }
518
553
  function SetTimestamp(dv, timestamp, offset, addLocalOffset = true) {
519
554
  if (timestamp == void 0)
520
555
  throw new Error("Timestamp is missing!");
521
- if (typeof timestamp === "string")
522
- timestamp = parseUTC(timestamp);
523
- const unixtime = timestamp.unix() + (addLocalOffset ? 60 * timestamp.utcOffset() : 0);
556
+ const meterTime = meterLocalTime(timestamp);
557
+ const unixtime = meterTime.moment.unix() + (addLocalOffset ? 60 * meterTime.offsetMinutes : 0);
524
558
  const bytes = getInt64Bytes(unixtime);
525
559
  const buffer = new ArrayBuffer(8);
526
560
  const tv = new DataView(buffer);
@@ -533,9 +567,8 @@ function SetTimestamp(dv, timestamp, offset, addLocalOffset = true) {
533
567
  function SetTimestamp32(dv, timestamp, offset, addLocalOffset = true) {
534
568
  if (timestamp == void 0)
535
569
  throw new Error("Timestamp is missing!");
536
- if (typeof timestamp === "string")
537
- timestamp = parseUTC(timestamp);
538
- const unixtime = timestamp.unix() + (addLocalOffset ? 60 * timestamp.utcOffset() : 0);
570
+ const meterTime = meterLocalTime(timestamp);
571
+ const unixtime = meterTime.moment.unix() + (addLocalOffset ? 60 * meterTime.offsetMinutes : 0);
539
572
  const bytes = getInt64Bytes(unixtime);
540
573
  const buffer = new ArrayBuffer(4);
541
574
  const tv = new DataView(buffer);
@@ -945,7 +978,10 @@ var secp224k1 = class {
945
978
  N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
946
979
  // Number of points in the field
947
980
  Acurve = BigInt(0);
948
- // Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
981
+ // Defined on the elliptic curve. y^2 = x^3 + Acurve * x + Bcurve
982
+ Bcurve = BigInt(5);
983
+ // secp224k1 has a = 0 and b = 5, and a cofactor of 1, so every
984
+ // point on the curve except infinity has order N.
949
985
  Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
950
986
  Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
951
987
  GPoint = [this.Gx, this.Gy];
@@ -959,16 +995,42 @@ var secp224k1 = class {
959
995
  }
960
996
  return null;
961
997
  }
998
+ // Returns true only for a signature that verifies against a public key which
999
+ // is a valid point on the curve. Every other outcome is false, including a
1000
+ // point off the curve and any failure while computing, so that a caller
1001
+ // trying several candidate keys is never interrupted by an exception.
962
1002
  validate(hash, signatureR, signatureS, PublicKey) {
963
- if (signatureR == this.Zero || signatureR >= this.N)
1003
+ if (signatureR <= this.Zero || signatureR >= this.N)
964
1004
  throw new Error("Invalid R");
965
- if (signatureS == this.Zero || signatureS >= this.N)
1005
+ if (signatureS <= this.Zero || signatureS >= this.N)
966
1006
  throw new Error("Invalid S");
967
- const w = this.modInv(signatureS, this.N);
968
- const u1 = this.ECmultiply(this.GPoint, this.modulo(w * hash, this.N));
969
- const u2 = this.ECmultiply(PublicKey, this.modulo(w * signatureR, this.N));
970
- const validation = this.ECadd(u1, u2);
971
- return validation[0] == signatureR;
1007
+ if (!this.isOnCurve(PublicKey))
1008
+ return false;
1009
+ try {
1010
+ const w = this.modInv(signatureS, this.N);
1011
+ const u1 = this.ECmultiply(this.GPoint, this.modulo(w * hash, this.N));
1012
+ const u2 = this.ECmultiply(PublicKey, this.modulo(w * signatureR, this.N));
1013
+ const validation = this.ECadd(u1, u2);
1014
+ const x = validation[0];
1015
+ if (x === void 0)
1016
+ return false;
1017
+ return this.modulo(x, this.N) === signatureR;
1018
+ } catch {
1019
+ return false;
1020
+ }
1021
+ }
1022
+ // y^2 == x^3 + Acurve * x + Bcurve (mod Pcurve), with both coordinates
1023
+ // reduced. The point at infinity has no [x, y] representation here and is
1024
+ // therefore rejected along with everything else that is malformed.
1025
+ isOnCurve(point) {
1026
+ const x = point[0];
1027
+ const y = point[1];
1028
+ if (x === void 0 || y === void 0)
1029
+ return false;
1030
+ if (x < this.Zero || x >= this.Pcurve || y < this.Zero || y >= this.Pcurve) {
1031
+ return false;
1032
+ }
1033
+ return this.modulo(y * y, this.Pcurve) === this.modulo(x * x * x + this.Acurve * x + this.Bcurve, this.Pcurve);
972
1034
  }
973
1035
  modulo(n, m) {
974
1036
  return (n % m + m) % m;
@@ -981,6 +1043,8 @@ var secp224k1 = class {
981
1043
  }
982
1044
  modInv(a, n = this.Pcurve) {
983
1045
  let lm = BigInt(1), hm = BigInt(0), high = n, low = this.modulo(a, n);
1046
+ if (low === this.Zero)
1047
+ throw new Error("Value is not invertible!");
984
1048
  while (low > 1) {
985
1049
  const ratio = high / low, nm = hm - ratio * lm, newm = high - ratio * low;
986
1050
  hm = lm;
@@ -992,6 +1056,12 @@ var secp224k1 = class {
992
1056
  }
993
1057
  ECadd(a, b) {
994
1058
  if (a[0] != void 0 && b[0] != void 0 && a[1] != void 0 && b[1] != void 0) {
1059
+ if (this.modulo(a[0] - b[0], this.Pcurve) === this.Zero) {
1060
+ if (this.modulo(a[1] - b[1], this.Pcurve) === this.Zero && this.modulo(a[1], this.Pcurve) !== this.Zero) {
1061
+ return this.ECdouble(a);
1062
+ }
1063
+ throw new Error("EC point addition results in the point at infinity!");
1064
+ }
995
1065
  const LamAdd = this.modulo((b[1] - a[1]) * this.modInv(b[0] - a[0]), this.Pcurve);
996
1066
  const x = this.modulo(LamAdd * LamAdd - a[0] - b[0], this.Pcurve);
997
1067
  const y = this.modulo(LamAdd * (a[0] - x) - a[1], this.Pcurve);
@@ -4032,6 +4102,7 @@ async function signJSONMessage(JSONMessage, KeyPairs, options) {
4032
4102
  return false;
4033
4103
  if (JSONMessage.signatures != null && !Array.isArray(JSONMessage.signatures))
4034
4104
  return false;
4105
+ let signaturesCreated = 0;
4035
4106
  for (const KeyPair of KeyPairs) {
4036
4107
  if (KeyPair == null || !isNobleSignatureKeyPair(KeyPair))
4037
4108
  continue;
@@ -4063,8 +4134,6 @@ async function signJSONMessage(JSONMessage, KeyPairs, options) {
4063
4134
  signatureJSON.context = bytesToBase64(options.context);
4064
4135
  signatureJSON.contextHEX = bytesToHex(options.context);
4065
4136
  }
4066
- JSONMessage.signatures ??= [];
4067
- JSONMessage.signatures.push(signatureJSON);
4068
4137
  const signatureIsValid = suite.verify(
4069
4138
  plainText,
4070
4139
  signatureBytes,
@@ -4073,8 +4142,11 @@ async function signJSONMessage(JSONMessage, KeyPairs, options) {
4073
4142
  );
4074
4143
  if (!signatureIsValid)
4075
4144
  return false;
4145
+ JSONMessage.signatures ??= [];
4146
+ JSONMessage.signatures.push(signatureJSON);
4147
+ signaturesCreated++;
4076
4148
  }
4077
- return true;
4149
+ return signaturesCreated > 0;
4078
4150
  }
4079
4151
  async function verifyJSONSignature(JSONMessage, signature, options) {
4080
4152
  return isVerificationTrue(await verifyJSONSignatureResult(JSONMessage, signature, options));
@@ -5497,6 +5569,33 @@ function decodeRawOCMFBytes(value, encoding) {
5497
5569
  return new Uint8Array(Buffer.from(value, "base64"));
5498
5570
  throw new TypeError(`Unsupported raw key encoding '${encoding ?? ""}'.`);
5499
5571
  }
5572
+ function getOCMFSignatureDisplay(signature, signatureBytes, signatureRS) {
5573
+ const encodedSignature = signatureBytes !== void 0 && signatureBytes.length > 0 ? signatureBytes : decodeRawOCMFBytes(signature.SD, signature.SE);
5574
+ const rawHex = buf2hex(encodedSignature).toUpperCase();
5575
+ if (signature.SA === "EdDSA-Ed25519" || signature.SA === "EdDSA-Ed448") {
5576
+ const componentHexLength = signature.SA === "EdDSA-Ed25519" ? 64 : 114;
5577
+ if (rawHex.length !== componentHexLength * 2)
5578
+ return { format: "RS, hex", valueLabel: "raw", value: rawHex };
5579
+ return {
5580
+ format: "RS, hex",
5581
+ valueLabel: "raw",
5582
+ value: rawHex,
5583
+ r: rawHex.substring(0, componentHexLength),
5584
+ s: rawHex.substring(componentHexLength)
5585
+ };
5586
+ }
5587
+ if (signature.SA === "ML-DSA-44" || signature.SA === "ML-DSA-65" || signature.SA === "ML-DSA-87")
5588
+ return { format: "raw, hex", valueLabel: "raw", value: rawHex };
5589
+ return {
5590
+ format: "rs, hex",
5591
+ valueLabel: "der",
5592
+ value: rawHex,
5593
+ ...signatureRS === void 0 ? {} : {
5594
+ r: signatureRS.r.toLowerCase().padStart(56, "0"),
5595
+ s: signatureRS.s.toLowerCase().padStart(56, "0")
5596
+ }
5597
+ };
5598
+ }
5500
5599
  var OCMFv1_x = class extends ACrypt {
5501
5600
  curve;
5502
5601
  constructor(chargy) {
@@ -5728,10 +5827,15 @@ var OCMFv1_x = class extends ACrypt {
5728
5827
  }
5729
5828
  }
5730
5829
  if (measurementValue.ocmfDocument.signature.SD) {
5830
+ const signatureDisplay = getOCMFSignatureDisplay(
5831
+ measurementValue.ocmfDocument.signature,
5832
+ measurementValue.ocmfDocument.signatureBytes,
5833
+ measurementValue.ocmfDocument.signatureRS
5834
+ );
5731
5835
  if (SignatureExpectedDiv.parentElement) {
5732
- getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
5836
+ getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (" + signatureDisplay.format + ")";
5733
5837
  }
5734
- SignatureExpectedDiv.innerHTML = "der: " + (measurementValue.ocmfDocument.signature.SD.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br /><br />r:&nbsp;&nbsp; " + (measurementValue.ocmfDocument.signatureRS?.r.toLowerCase().padStart(56, "0").match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />s:&nbsp;&nbsp; " + (measurementValue.ocmfDocument.signatureRS?.s.toLowerCase().padStart(56, "0").match(/.{1,8}/g)?.join(" ") ?? "-");
5838
+ SignatureExpectedDiv.innerHTML = signatureDisplay.valueLabel + ": " + (signatureDisplay.value.match(/.{1,8}/g)?.join(" ") ?? "-") + (signatureDisplay.r === void 0 || signatureDisplay.s === void 0 ? "" : "<br /><br />R:&nbsp;&nbsp; " + (signatureDisplay.r.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />S:&nbsp;&nbsp; " + (signatureDisplay.s.match(/.{1,8}/g)?.join(" ") ?? "-"));
5735
5839
  }
5736
5840
  if (measurementValue.measurement.chargingSession.verificationResult) {
5737
5841
  switch (measurementValue.measurement.chargingSession.verificationResult.status) {
@@ -5860,8 +5964,20 @@ var OCMF = class {
5860
5964
  message: this.chargy.GetMultilanguageText("Each OCMF data set must have at least one meter reading!"),
5861
5965
  certainty: 0
5862
5966
  };
5967
+ const sessionId = "OCMF-" + bytesToHex(
5968
+ sha256$1(
5969
+ new TextEncoder().encode(
5970
+ OCMFJSONDocuments.map(
5971
+ (ocmfJSONDocument) => canonicalJSONStringify({
5972
+ payload: ocmfJSONDocument.payload,
5973
+ signature: ocmfJSONDocument.signature
5974
+ })
5975
+ ).join("\n")
5976
+ )
5977
+ )
5978
+ );
5863
5979
  const CTR = {
5864
- "@id": "?",
5980
+ "@id": sessionId,
5865
5981
  "@context": "https://open.charging.cloud/contexts/CTR+json",
5866
5982
  //"@context": [ "https://open.charging.cloud/contexts/CTR+json", "https://open.charging.cloud/contexts/CTR_OCMF+json" ],
5867
5983
  "begin": "?",
@@ -5951,7 +6067,7 @@ var OCMF = class {
5951
6067
  // }]
5952
6068
  // }],
5953
6069
  "chargingSessions": [{
5954
- "@id": "1554181214441:-1965658344385548683:2",
6070
+ "@id": sessionId,
5955
6071
  "@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/OCMFv1.0+json",
5956
6072
  "begin": "?",
5957
6073
  "end": "?",
@@ -5997,8 +6113,26 @@ var OCMF = class {
5997
6113
  if (containerEVSE !== void 0 && CTR.chargingSessions?.[0] !== void 0) {
5998
6114
  const chargingSession = CTR.chargingSessions[0];
5999
6115
  chargingSession.EVSEId ??= containerEVSE["@id"];
6000
- if (chargingSession.EVSEId === containerEVSE["@id"])
6001
- chargingSession.EVSE = containerEVSE;
6116
+ if (chargingSession.EVSEId === containerEVSE["@id"]) {
6117
+ const containerEnergyMeter = containerEVSE.energyMeters?.[0];
6118
+ const resolvedEnergyMeter = containerEnergyMeter !== void 0 || meterSerial !== void 0 ? {
6119
+ ...containerEnergyMeter,
6120
+ "@id": meterSerial ?? containerEnergyMeter?.["@id"] ?? "",
6121
+ manufacturer: {
6122
+ ...containerEnergyMeter?.manufacturer,
6123
+ name: meterVendor ?? containerEnergyMeter?.manufacturer?.name
6124
+ },
6125
+ model: {
6126
+ ...containerEnergyMeter?.model,
6127
+ name: meterModel ?? containerEnergyMeter?.model?.name
6128
+ },
6129
+ firmware: {
6130
+ ...containerEnergyMeter?.firmware,
6131
+ version: meterFirmware ?? containerEnergyMeter?.firmware?.version
6132
+ }
6133
+ } : void 0;
6134
+ chargingSession.EVSE = resolvedEnergyMeter !== void 0 ? { ...containerEVSE, energyMeters: [resolvedEnergyMeter] } : containerEVSE;
6135
+ }
6002
6136
  }
6003
6137
  const resolvedConnectorId = signedConnectorId ?? containerConnector?.["@id"];
6004
6138
  if ((resolvedConnectorId !== void 0 || signedCable !== void 0) && CTR.chargingSessions?.[0] !== void 0) {
@@ -6157,8 +6291,16 @@ var OCMF = class {
6157
6291
  CTR.warnings = (CTR.warnings ?? []).concat(ContainerInfos.warnings);
6158
6292
  CTR.status = OCMFJSONDocuments.every((ocmfJSONDocument) => ocmfJSONDocument.validationStatus === "ValidSignature" /* ValidSignature */) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
6159
6293
  if (CTR.chargingSessions != null && CTR.chargingSessions.length > 0 && CTR.chargingSessions[0]) {
6160
- CTR.begin = CTR.chargingSessions[0].begin;
6161
- CTR.end = CTR.chargingSessions[0].end;
6294
+ const firstChargingSession = CTR.chargingSessions[0];
6295
+ const measurementTimestamps = firstChargingSession.measurements.flatMap((measurement) => measurement.values).map((value) => value.timestamp).filter((timestamp) => isMandatoryString(timestamp) && !Number.isNaN(Date.parse(timestamp))).sort((left, right) => Date.parse(left) - Date.parse(right));
6296
+ const firstTimestamp = measurementTimestamps[0];
6297
+ const lastTimestamp = measurementTimestamps[measurementTimestamps.length - 1];
6298
+ if (firstTimestamp !== void 0 && lastTimestamp !== void 0) {
6299
+ firstChargingSession.begin = firstTimestamp;
6300
+ firstChargingSession.end = lastTimestamp;
6301
+ }
6302
+ CTR.begin = firstChargingSession.begin;
6303
+ CTR.end = firstChargingSession.end;
6162
6304
  return CTR;
6163
6305
  }
6164
6306
  }
@@ -6822,8 +6964,29 @@ var OCPI = class {
6822
6964
  const address = asJSONObject(placeInfo?.["address"]);
6823
6965
  const geoLat = asNumber(geoLocation?.["lat"]);
6824
6966
  const geoLon = asNumber(geoLocation?.["lon"]);
6967
+ const meterInfo = asJSONObject(SomeJSON["meterInfo"]);
6968
+ const containerEnergyMeter = meterInfo !== void 0 ? {
6969
+ "@id": asString(meterInfo["meterId"]) ?? "",
6970
+ manufacturer: {
6971
+ name: asString(meterInfo["manufacturer"]),
6972
+ url: asString(meterInfo["manufacturerURL"])
6973
+ },
6974
+ model: {
6975
+ name: asString(meterInfo["model"]),
6976
+ url: asString(meterInfo["modelURL"])
6977
+ },
6978
+ hardware: {
6979
+ revision: asString(meterInfo["hardwareVersion"])
6980
+ },
6981
+ firmware: {
6982
+ version: asString(meterInfo["firmwareVersion"])
6983
+ }
6984
+ } : void 0;
6825
6985
  const containerInfos = {
6826
- EVSEIds: [evseId],
6986
+ EVSEs: evseId !== void 0 ? [{
6987
+ "@id": evseId,
6988
+ energyMeters: containerEnergyMeter !== void 0 ? [containerEnergyMeter] : void 0
6989
+ }] : void 0,
6827
6990
  chargingStations: [{
6828
6991
  "@id": evseIdStr.substring(0, evseIdStr.lastIndexOf("*")),
6829
6992
  geoLocation: geoLat !== void 0 && geoLon !== void 0 ? { lat: geoLat, lng: geoLon } : void 0,
@@ -6834,7 +6997,6 @@ var OCPI = class {
6834
6997
  country: asString(address["country"]) ?? ""
6835
6998
  } : void 0
6836
6999
  }]
6837
- //energyMeter: chargyLib.asJSONObject(SomeJSON["meterInfo"])
6838
7000
  };
6839
7001
  return new OCMF(this.chargy).TryToParseOCMFDocument(
6840
7002
  firstSignedData,
@@ -9778,7 +9940,7 @@ var ChargePointCrypt01 = class extends ACrypt {
9778
9940
  if (plainText !== "" && chargingSession.signature != null && chargingSession.signature !== "") {
9779
9941
  let sha225Value = null;
9780
9942
  let sha256Value = null;
9781
- let sha385Value = null;
9943
+ let sha384Value = null;
9782
9944
  let sha512Value = null;
9783
9945
  for (const publicKey of publicKeys) {
9784
9946
  const algorithm = typeof publicKey.algorithm === "object" ? publicKey.algorithm.name : publicKey.algorithm;
@@ -9803,9 +9965,9 @@ var ChargePointCrypt01 = class extends ACrypt {
9803
9965
  ) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
9804
9966
  break;
9805
9967
  case "secp384r1":
9806
- sha385Value = sha385Value ?? await sha384(plainText);
9968
+ sha384Value = sha384Value ?? await sha384(plainText);
9807
9969
  sessionResult = this.curve384r1.keyFromPublic(publicKey.value, "hex").verify(
9808
- sha385Value,
9970
+ sha384Value,
9809
9971
  chargingSession.signature
9810
9972
  ) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
9811
9973
  break;
@@ -9827,12 +9989,13 @@ var ChargePointCrypt01 = class extends ACrypt {
9827
9989
  chargingSession.hashValue = sha256Value ?? "";
9828
9990
  break;
9829
9991
  case "secp384r1":
9830
- chargingSession.hashValue = sha385Value ?? "";
9992
+ chargingSession.hashValue = sha384Value ?? "";
9831
9993
  break;
9832
9994
  case "secp521r1":
9833
9995
  chargingSession.hashValue = sha512Value ?? "";
9834
9996
  break;
9835
9997
  }
9998
+ break;
9836
9999
  }
9837
10000
  }
9838
10001
  }
@@ -9954,7 +10117,7 @@ var ChargePointCrypt01 = class extends ACrypt {
9954
10117
  case "secp384r1":
9955
10118
  hashInfo = "(SHA384, 384 Bits, hex)";
9956
10119
  break;
9957
- case "secp512r1":
10120
+ case "secp521r1":
9958
10121
  hashInfo = "(SHA512, 512 Bits, hex)";
9959
10122
  break;
9960
10123
  }
@@ -10344,8 +10507,14 @@ var validationRules_default = {
10344
10507
  function isPdfAttachment(value) {
10345
10508
  if (!isMandatoryJSONObject(value))
10346
10509
  return false;
10347
- return typeof value["filename"] === "string" && (value["content"] instanceof ArrayBuffer || ArrayBuffer.isView(value["content"]));
10510
+ return typeof value["filename"] === "string";
10348
10511
  }
10512
+ var pdfAttachmentTypes = [
10513
+ { extension: ".chargy", type: "application/chargy", info: "A CHARGY file extracted from a PDF/A-3 or newer attachment" },
10514
+ { extension: ".xml", type: "application/xml", info: "A XML file extracted from a PDF/A-3 or newer attachment" },
10515
+ { extension: ".json", type: "application/json", info: "A JSON file extracted from a PDF/A-3 or newer attachment" },
10516
+ { extension: ".csv", type: "text/csv", info: "A CSV file extracted from a PDF/A-3 or newer attachment" }
10517
+ ];
10349
10518
  var Chargy = class {
10350
10519
  //#region Data
10351
10520
  i18n;
@@ -10444,7 +10613,9 @@ var Chargy = class {
10444
10613
  case "1.3.101.113":
10445
10614
  KeyType = "EdDSA";
10446
10615
  break;
10616
+ case "2.16.840.1.101.3.4.3.17":
10447
10617
  case "2.16.840.1.101.3.4.3.18":
10618
+ case "2.16.840.1.101.3.4.3.19":
10448
10619
  KeyType = "ML-DSA";
10449
10620
  break;
10450
10621
  }
@@ -10457,9 +10628,15 @@ var Chargy = class {
10457
10628
  case "1.3.101.113":
10458
10629
  Algorithm = "Ed448";
10459
10630
  break;
10631
+ case "2.16.840.1.101.3.4.3.17":
10632
+ Algorithm = "ML-DSA-44";
10633
+ break;
10460
10634
  case "2.16.840.1.101.3.4.3.18":
10461
10635
  Algorithm = "ML-DSA-65";
10462
10636
  break;
10637
+ case "2.16.840.1.101.3.4.3.19":
10638
+ Algorithm = "ML-DSA-87";
10639
+ break;
10463
10640
  // Koblitz 224-bit curve
10464
10641
  case "1.3.132.0.32":
10465
10642
  Algorithm = "secp224k1";
@@ -10478,7 +10655,7 @@ var Chargy = class {
10478
10655
  break;
10479
10656
  }
10480
10657
  const publicKeyData = new Uint8Array(publicKeyDER.publicKey.data);
10481
- const expectedLength = Algorithm === "Ed25519" ? 32 : Algorithm === "Ed448" ? 57 : Algorithm === "ML-DSA-65" ? 1952 : void 0;
10658
+ const expectedLength = Algorithm === "Ed25519" ? 32 : Algorithm === "Ed448" ? 57 : Algorithm === "ML-DSA-44" ? 1312 : Algorithm === "ML-DSA-65" ? 1952 : Algorithm === "ML-DSA-87" ? 2592 : void 0;
10482
10659
  if (publicKeyDER.publicKey.unused !== void 0 && publicKeyDER.publicKey.unused !== 0)
10483
10660
  throw new Error("The SubjectPublicKeyInfo public key has unused bits!");
10484
10661
  if (expectedLength !== void 0 && publicKeyData.length !== expectedLength)
@@ -10525,7 +10702,7 @@ var Chargy = class {
10525
10702
  publicKeyDER
10526
10703
  ).publicKeys[0];
10527
10704
  const algorithm = typeof publicKey?.algorithm === "string" ? publicKey.algorithm : publicKey?.algorithm.name;
10528
- return algorithm === "Ed25519" || algorithm === "Ed448" || algorithm === "ML-DSA-65" ? publicKey?.value : buf2hex(publicKeyDER);
10705
+ return algorithm === "Ed25519" || algorithm === "Ed448" || algorithm?.startsWith("ML-DSA-") === true ? publicKey?.value : buf2hex(publicKeyDER);
10529
10706
  } catch {
10530
10707
  return void 0;
10531
10708
  }
@@ -10538,7 +10715,7 @@ var Chargy = class {
10538
10715
  publicKeyDER
10539
10716
  ).publicKeys[0];
10540
10717
  const algorithm = typeof publicKey?.algorithm === "string" ? publicKey.algorithm : publicKey?.algorithm.name;
10541
- return algorithm === "Ed25519" || algorithm === "Ed448" || algorithm === "ML-DSA-65" ? publicKey?.value : buf2hex(publicKeyDER);
10718
+ return algorithm === "Ed25519" || algorithm === "Ed448" || algorithm?.startsWith("ML-DSA-") === true ? publicKey?.value : buf2hex(publicKeyDER);
10542
10719
  } catch {
10543
10720
  return void 0;
10544
10721
  }
@@ -11114,45 +11291,27 @@ var Chargy = class {
11114
11291
  const pdfDocument = fileInfo.data ? await pdfjsLib.getDocument({ data: fileInfo.data }).promise : fileInfo.path != null && fileInfo.path.length > 0 ? await pdfjsLib.getDocument({ url: fileInfo.path }).promise : null;
11115
11292
  if (pdfDocument !== null) {
11116
11293
  try {
11117
- const attachmentsUnknown = await pdfDocument.getAttachments();
11118
- if (isMandatoryJSONObject(attachmentsUnknown))
11119
- Object.values(attachmentsUnknown).forEach((attachmentUnknown) => {
11120
- if (!isPdfAttachment(attachmentUnknown))
11121
- return;
11122
- const attachment = attachmentUnknown;
11123
- if (attachment.filename.endsWith(".chargy"))
11124
- expandedFiles.push({
11125
- name: attachment.filename,
11126
- path: FileInfos[0]?.path,
11127
- type: "application/chargy",
11128
- data: attachment.content,
11129
- info: "A CHARGY file extracted from a PDF/A-3 or newer attachment"
11130
- });
11131
- else if (attachment.filename.endsWith(".xml"))
11132
- expandedFiles.push({
11133
- name: attachment.filename,
11134
- path: FileInfos[0]?.path,
11135
- type: "application/xml",
11136
- data: attachment.content,
11137
- info: "A XML file extracted from a PDF/A-3 or newer attachment"
11138
- });
11139
- else if (attachment.filename.endsWith(".json"))
11140
- expandedFiles.push({
11141
- name: attachment.filename,
11142
- path: FileInfos[0]?.path,
11143
- type: "application/json",
11144
- data: attachment.content,
11145
- info: "A JSON file extracted from a PDF/A-3 or newer attachment"
11146
- });
11147
- else if (attachment.filename.endsWith(".csv"))
11148
- expandedFiles.push({
11149
- name: attachment.filename,
11150
- path: FileInfos[0]?.path,
11151
- type: "text/csv",
11152
- data: attachment.content,
11153
- info: "A CSV file extracted from a PDF/A-3 or newer attachment"
11154
- });
11294
+ const attachments = await pdfDocument.getAttachments();
11295
+ for (const [attachmentId, attachmentUnknown] of attachments ?? []) {
11296
+ if (!isPdfAttachment(attachmentUnknown))
11297
+ continue;
11298
+ const attachment = attachmentUnknown;
11299
+ const attachmentType = pdfAttachmentTypes.find(
11300
+ (candidate) => attachment.filename.endsWith(candidate.extension)
11301
+ );
11302
+ if (attachmentType === void 0)
11303
+ continue;
11304
+ const content = attachment.content ?? await pdfDocument.getAttachmentContent(attachmentId);
11305
+ if (content == null)
11306
+ continue;
11307
+ expandedFiles.push({
11308
+ name: attachment.filename,
11309
+ path: FileInfos[0]?.path,
11310
+ type: attachmentType.type,
11311
+ data: content,
11312
+ info: attachmentType.info
11155
11313
  });
11314
+ }
11156
11315
  } catch (error) {
11157
11316
  console.error(`Error extracting PDF/A-3 attachments: ${String(error)}`);
11158
11317
  }
@@ -11750,6 +11909,6 @@ var Chargy = class {
11750
11909
  }
11751
11910
  };
11752
11911
 
11753
- export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CreateError, CreateWarning, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EDL40, EDL40Crypt01, EDL40ValidationError, EDL40_OBIS, EDL40_SESSION_CONTEXT, EDL40_SIGNATURE_CONTEXT, EMHCrypt01, ErrorLevel, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKey, IsAPublicKeyLookup, IsAPublicKeySignature, IsAPublicKeyXY, IsASessionCryptoResult, IsAURL, IsNullOrEmpty, IsValidURL, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFBonnTariffParseError, OCMFTransactionTypes, OCMF_SIGNATURE_ALGORITHMS, OCMFv1_x, OCPI, OIDInfo, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, PTB, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, IURL_exports as SimpleURL, TimeStatusTypes, URLContext, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WarningLevel, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, base64ToBytes, buf2hex, buildEDL40Signature, buildIsaSignature, buildMennekesSignatureData, bytesToBase64, bytesToHex, canParseEDL40, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createCompatibleCurve, createHexString, createLegacyP192Curve, dateToMennekesLocalEpochSeconds, decodeSmlMessages, extractMennekesChargingProcesses, findEntryByObis, findGetListRes, firstKey, firstValue, generateSignatureKeyPair, getArrayElement, getArrayLikeElement, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getFirstArrayElement, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getLastArrayElement, getSignatureSuite, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isEncodedValue, isGeoLocation, isI18NString, isICryptoResult, isIFileInfo, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalStringArray, isOptionalStringOrOIDInfo, isOptionalURL, isPCDFText, isPublicKeySubject, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, isaListNameContext, jsonPrettyPrinter, measurementName2human, normalizePCDFPublicKeyHex, normalizeXMLText, ocmfBonnTariffToChargingTariff, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseEDL40, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parseOCMFBonnTariffText, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseSmlTime, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, readTLV, secp224k1, setUILocale, sha256, sha256____, sha384, sha384____, sha512, sha512____, signJSONMessage, signMessage, stripPCDFControlCharacters, stripTransport, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, transformEDL40Status, tryParseOCMFBonnTariffText, unquotePCDFText, validatePCDFFields, verifyEDL40Document, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
11912
+ export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CreateError, CreateWarning, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EDL40, EDL40Crypt01, EDL40ValidationError, EDL40_OBIS, EDL40_SESSION_CONTEXT, EDL40_SIGNATURE_CONTEXT, EMHCrypt01, ErrorLevel, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKey, IsAPublicKeyLookup, IsAPublicKeySignature, IsAPublicKeyXY, IsASessionCryptoResult, IsAURL, IsNullOrEmpty, IsValidURL, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFBonnTariffParseError, OCMFTransactionTypes, OCMF_SIGNATURE_ALGORITHMS, OCMFv1_x, OCPI, OIDInfo, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, PTB, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, IURL_exports as SimpleURL, TimeStatusTypes, URLContext, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WarningLevel, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, base64ToBytes, buf2hex, buildEDL40Signature, buildIsaSignature, buildMennekesSignatureData, bytesToBase64, bytesToHex, canParseEDL40, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createCompatibleCurve, createHexString, createLegacyP192Curve, dateToMennekesLocalEpochSeconds, decodeSmlMessages, extractMennekesChargingProcesses, findEntryByObis, findGetListRes, firstKey, firstValue, generateSignatureKeyPair, getArrayElement, getArrayLikeElement, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getFirstArrayElement, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getLastArrayElement, getOCMFSignatureDisplay, getSignatureSuite, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isEncodedValue, isGeoLocation, isI18NString, isICryptoResult, isIFileInfo, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalStringArray, isOptionalStringOrOIDInfo, isOptionalURL, isPCDFText, isPublicKeySubject, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, isaListNameContext, jsonPrettyPrinter, measurementName2human, meterTimeZone, normalizePCDFPublicKeyHex, normalizeXMLText, ocmfBonnTariffToChargingTariff, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseEDL40, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parseOCMFBonnTariffText, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseSmlTime, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, readTLV, secp224k1, setUILocale, sha256, sha256____, sha384, sha384____, sha512, sha512____, signJSONMessage, signMessage, stripPCDFControlCharacters, stripTransport, time2human, timeZoneOffsetMinutes, toArrayBuffer, toSessionVerificationResults, toUint8Array, transformEDL40Status, tryParseOCMFBonnTariffText, unquotePCDFText, validatePCDFFields, verifyEDL40Document, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
11754
11913
  //# sourceMappingURL=index.js.map
11755
11914
  //# sourceMappingURL=index.js.map