ismx-nexo-node-app 0.4.193 → 0.4.196

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.
@@ -37,7 +37,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
38
  const Service_1 = require("../api/Service");
39
39
  const Business_1 = __importDefault(require("./Business"));
40
- const node_http_1 = require("node:http");
41
40
  class BusinessServer extends Business_1.default {
42
41
  constructor() {
43
42
  super();
@@ -162,11 +161,12 @@ class BusinessServer extends Business_1.default {
162
161
  Object.entries((_h = response.headers) !== null && _h !== void 0 ? _h : {}).forEach(([header, value]) => {
163
162
  socket.set(header, value);
164
163
  });
165
- if (response.pipe)
166
- if (response.pipe instanceof node_http_1.IncomingMessage)
164
+ if (response.pipe) { // @ts-ignore
165
+ if (response.pipe.pipe)
167
166
  response.pipe.pipe(socket);
168
167
  else
169
168
  this.readable.fromWeb(response.pipe).pipe(socket);
169
+ }
170
170
  else
171
171
  socket.send(response === null || response === void 0 ? void 0 : response.content);
172
172
  try {
@@ -87,6 +87,30 @@ class CryptoUtils {
87
87
  return decrypted.toString('utf8');
88
88
  });
89
89
  }
90
+ /**
91
+ * Genera un desafío (challenge) aleatorio y seguro.
92
+ * Se recomienda un tamaño de 32 bytes para asegurar suficiente entropía.
93
+ */
94
+ challenge() {
95
+ return (0, node_crypto_1.randomBytes)(32).toString('hex');
96
+ }
97
+ /**
98
+ * Verifica si el desafío firmado criptográficamente coincide con la clave generadora.
99
+ * @param challenge El desafío original que el servidor generó.
100
+ * @param signature La firma generada por el dispositivo (usualmente en base64 o hex).
101
+ * @param key La clave pública que guardamos en setupBiometry() para este dispositivo.
102
+ * @param format
103
+ */
104
+ verify(challenge, signature, key, format = 'base64') {
105
+ try {
106
+ const verifier = (0, node_crypto_1.createVerify)('sha256');
107
+ verifier.update(challenge);
108
+ return verifier.verify(key, signature, format);
109
+ }
110
+ catch (error) {
111
+ return false;
112
+ }
113
+ }
90
114
  static sha256Sign(merchantKey, orderId, encodedOrder) {
91
115
  return __awaiter(this, void 0, void 0, function* () {
92
116
  var _a;
@@ -1,4 +1,4 @@
1
- import { KeyLike, RsaPrivateKey } from "crypto";
1
+ import { BinaryToTextEncoding, KeyLike, RsaPrivateKey } from "crypto";
2
2
  export default abstract class CryptoUtils {
3
3
  private static crypto;
4
4
  private static zeroPad;
@@ -8,5 +8,18 @@ export default abstract class CryptoUtils {
8
8
  static asymEncrypt(value: string, publicKey: RsaPrivateKey | KeyLike): Promise<string>;
9
9
  /** Asymmetric decryption (RSA) */
10
10
  static asymDecrypt(hash: string, privateKey: RsaPrivateKey | KeyLike): Promise<string>;
11
+ /**
12
+ * Genera un desafío (challenge) aleatorio y seguro.
13
+ * Se recomienda un tamaño de 32 bytes para asegurar suficiente entropía.
14
+ */
15
+ challenge(): string;
16
+ /**
17
+ * Verifica si el desafío firmado criptográficamente coincide con la clave generadora.
18
+ * @param challenge El desafío original que el servidor generó.
19
+ * @param signature La firma generada por el dispositivo (usualmente en base64 o hex).
20
+ * @param key La clave pública que guardamos en setupBiometry() para este dispositivo.
21
+ * @param format
22
+ */
23
+ verify(challenge: string, signature: string, key: string, format?: BinaryToTextEncoding): boolean;
11
24
  private static sha256Sign;
12
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ismx-nexo-node-app",
3
- "version": "0.4.193",
3
+ "version": "0.4.196",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build": "rm -rf ./dist && npx tsc",
@@ -1,6 +1,5 @@
1
1
  import Service, {HttpRequest, HttpResponse} from "../api/Service";
2
2
  import Business from "./Business";
3
- import {IncomingMessage} from "node:http";
4
3
 
5
4
  export default class BusinessServer extends Business
6
5
  {
@@ -132,8 +131,10 @@ export default class BusinessServer extends Business
132
131
  socket.set(header, value);
133
132
  });
134
133
  if (response.pipe)
135
- if (response.pipe instanceof IncomingMessage) response.pipe.pipe(socket);
136
- else this.readable.fromWeb(response.pipe).pipe(socket);
134
+ { // @ts-ignore
135
+ if (response.pipe.pipe) response.pipe.pipe(socket);
136
+ else this.readable.fromWeb(response.pipe).pipe(socket);
137
+ }
137
138
  else socket.send(response?.content);
138
139
 
139
140
  try { this.onEnd?.(request, response); } catch(e) { }
@@ -1,5 +1,5 @@
1
- import {privateDecrypt, publicEncrypt} from "node:crypto";
2
- import {KeyLike, RsaPrivateKey} from "crypto";
1
+ import {createVerify, privateDecrypt, publicEncrypt, randomBytes} from "node:crypto";
2
+ import {BinaryToTextEncoding, KeyLike, RsaPrivateKey} from "crypto";
3
3
 
4
4
  export default abstract class CryptoUtils {
5
5
 
@@ -62,6 +62,31 @@ export default abstract class CryptoUtils {
62
62
  return decrypted.toString('utf8');
63
63
  }
64
64
 
65
+ /**
66
+ * Genera un desafío (challenge) aleatorio y seguro.
67
+ * Se recomienda un tamaño de 32 bytes para asegurar suficiente entropía.
68
+ */
69
+ public challenge() {
70
+ return randomBytes(32).toString('hex');
71
+ }
72
+
73
+ /**
74
+ * Verifica si el desafío firmado criptográficamente coincide con la clave generadora.
75
+ * @param challenge El desafío original que el servidor generó.
76
+ * @param signature La firma generada por el dispositivo (usualmente en base64 o hex).
77
+ * @param key La clave pública que guardamos en setupBiometry() para este dispositivo.
78
+ * @param format
79
+ */
80
+ public verify(challenge: string, signature: string, key: string, format: BinaryToTextEncoding = 'base64'): boolean
81
+ {
82
+ try {
83
+ const verifier = createVerify('sha256');
84
+ verifier.update(challenge);
85
+ return verifier.verify(key, signature, format);
86
+
87
+ } catch (error) { return false; }
88
+ }
89
+
65
90
  private static async sha256Sign(merchantKey: string, orderId: string, encodedOrder: string) {
66
91
  let crypto = this.crypto ?? (await import("crypto")).default;
67
92
  const orderKeyBuf = await CryptoUtils.symEncrypt(merchantKey, orderId);