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.
- package/dist/js/business/BusinessServer.js +3 -3
- package/dist/js/business/utils/CryptoUtils.js +24 -0
- package/dist/types/business/utils/CryptoUtils.d.ts +14 -1
- package/package.json +1 -1
- package/src/main/node/business/BusinessServer.ts +4 -3
- package/src/main/node/business/utils/CryptoUtils.ts +27 -2
|
@@ -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
|
|
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,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
|
-
|
|
136
|
-
|
|
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);
|