kage-baileys 3.0.2 → 3.0.4
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/WAProto/index.js +46 -0
- package/package.json +2 -1
- package/scripts/generate-protobuf.cjs +6 -1
- package/scripts/kage-base64-fix.cjs +45 -0
- package/test/base64-fix.test.cjs +49 -0
package/WAProto/index.js
CHANGED
|
@@ -3,6 +3,52 @@
|
|
|
3
3
|
|
|
4
4
|
var $protobuf = require("protobufjs/minimal");
|
|
5
5
|
|
|
6
|
+
'use strict';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// kage fix: decodificador base64 tolerante.
|
|
9
|
+
// Evita "Error: invalid encoding" cuando WhatsApp/devlogs entregan firmas,
|
|
10
|
+
// certificados o hashes con base64 URL-safe, saltos de linea, padding roto
|
|
11
|
+
// o un caracter suelto residual (longitud % 4 === 1). En ese ultimo caso se
|
|
12
|
+
// descarta unicamente el caracter colgante y el resto se decodifica intacto.
|
|
13
|
+
// Este archivo es inyectado automaticamente por scripts/generate-protobuf.cjs
|
|
14
|
+
// al final de WAProto/index.js tras cada regeneracion.
|
|
15
|
+
// ============================================================================
|
|
16
|
+
(function () {
|
|
17
|
+
var b64 = $protobuf.util.base64;
|
|
18
|
+
if (b64.__kageTolerant)
|
|
19
|
+
return;
|
|
20
|
+
var nativeDecode = b64.decode;
|
|
21
|
+
var nativeLength = b64.length;
|
|
22
|
+
var clean = function (string) {
|
|
23
|
+
var s = $String(string).replace(/[\r\n\t\s]/g, "").replace(/-/g, "+").replace(/_/g, "/");
|
|
24
|
+
var rem = s.length % 4;
|
|
25
|
+
if (rem === 2)
|
|
26
|
+
s += "==";
|
|
27
|
+
else if (rem === 3)
|
|
28
|
+
s += "=";
|
|
29
|
+
else if (rem === 1)
|
|
30
|
+
s = s.slice(0, -1); // caracter colgante: 6 bits sin datos, no aporta bytes
|
|
31
|
+
return s;
|
|
32
|
+
};
|
|
33
|
+
b64.length = function (string) {
|
|
34
|
+
if (typeof string !== "string")
|
|
35
|
+
return nativeLength(string);
|
|
36
|
+
return nativeLength(clean(string));
|
|
37
|
+
};
|
|
38
|
+
b64.decode = function (string, buffer, start) {
|
|
39
|
+
if (typeof string !== "string")
|
|
40
|
+
return nativeDecode(string, buffer, start);
|
|
41
|
+
var s = clean(string);
|
|
42
|
+
try {
|
|
43
|
+
return nativeDecode(s, buffer, start);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
// ultimo recurso: elimina cualquier caracter residual no-base64
|
|
46
|
+
return nativeDecode(s.replace(/[^A-Za-z0-9+/=]/g, ""), buffer, start);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
b64.__kageTolerant = true;
|
|
50
|
+
})();
|
|
51
|
+
|
|
6
52
|
// Common aliases
|
|
7
53
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
|
8
54
|
var $Object = $util.global.Object, $undefined = $util.global.undefined, $Error = $util.global.Error, $RangeError = $util.global.RangeError, $TypeError = $util.global.TypeError, $parseInt = $util.global.parseInt, $BigInt = $util.global.BigInt, $String = $util.global.String, $Number = $util.global.Number, $Array = $util.global.Array, $Boolean = $util.global.Boolean, $isFinite = $util.global.isFinite;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kage-baileys",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "Kage Baileys una libreria de WhatsApp.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kage-baileys",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"form-data": "^4.0.0",
|
|
58
58
|
"gradient-string": "^2.0.2",
|
|
59
59
|
"jimp": "1.6.1",
|
|
60
|
+
"kage-baileys": "^3.0.2",
|
|
60
61
|
"libphonenumber-js": "^1.10.20",
|
|
61
62
|
"libsignal": "^6.0.0",
|
|
62
63
|
"link-preview-js": "4.0.4",
|
|
@@ -11,10 +11,15 @@ pbjs.main(['-t', 'static-module', '-w', 'commonjs', '--keep-case', '-o', js, pat
|
|
|
11
11
|
if (error) throw error;
|
|
12
12
|
// Accept plain JSON int64 strings as well as Long instances in toObject.
|
|
13
13
|
let source = fs.readFileSync(js, 'utf8');
|
|
14
|
+
// kage fix: inyecta decodificador base64 tolerante (evita "Error: invalid encoding"
|
|
15
|
+
// con base64 URL-safe, saltos de linea, padding roto o un caracter colgante residual
|
|
16
|
+
// en firmas/certificados de botMetadata.verificationMetadata.proofs).
|
|
17
|
+
const kageBase64Fix = fs.readFileSync(path.join(__dirname, 'kage-base64-fix.cjs'), 'utf8');
|
|
18
|
+
source = source.replace('var $protobuf = require("protobufjs/minimal");', 'var $protobuf = require("protobufjs/minimal");\n\n' + kageBase64Fix.trim());
|
|
14
19
|
source = source.replace(/\$util\.Long\.prototype\.toString\.call\((message\.[\w]+)\)/g, 'kageLongString($1)');
|
|
15
20
|
source = source.replace(/new \$util\.LongBits\((message\.[\w]+)\.low >>> 0, \1\.high >>> 0\)\.toNumber\((true)?\)/g, (_, value, unsigned) => `kageLongNumber(${value}, ${!!unsigned})`);
|
|
16
21
|
source = source.replace(/\$util\.Long\.fromBits\((message\.[\w]+)\.low >>> 0, \1\.high >>> 0, (true|false)\)\.toBigInt\(\)/g, (_, value, unsigned) => `BigInt(kageLongString(${value}, ${unsigned}))`);
|
|
17
|
-
source += `\nfunction kageLongString(value, unsigned) {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') return String(value);\n const long = $util.Long.fromValue(value);\n return (unsigned === true ? long.toUnsigned() : long).toString();\n}\nfunction kageLongNumber(value, unsigned) {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') return Number(value);\n const long = $util.Long.fromValue(value);\n return (unsigned ? long.toUnsigned() : long.toSigned()).toNumber();\n}\nrequire('./compat.cjs')(module.exports.proto);\n`;
|
|
22
|
+
source += `\nfunction kageLongString(value, unsigned) {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') return String(value);\n const long = $util.Long.fromValue(value);\n return (unsigned === true ? long.toUnsigned() : long).toString();\n}\nfunction kageLongNumber(value, unsigned) {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') return Number(value);\n const long = $util.Long.fromValue(value);\n return (unsigned ? long.toUnsigned() : long.toSigned()).toNumber();\n}\nrequire('./compat.cjs')(module.exports.proto);\n`; // kage-base64-fix.cjs es leído e inyectado arriba
|
|
18
23
|
fs.writeFileSync(js, source);
|
|
19
24
|
pbts.main(['-o', dts, js], error => {
|
|
20
25
|
if (error) throw error;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// kage fix: decodificador base64 tolerante.
|
|
4
|
+
// Evita "Error: invalid encoding" cuando WhatsApp/devlogs entregan firmas,
|
|
5
|
+
// certificados o hashes con base64 URL-safe, saltos de linea, padding roto
|
|
6
|
+
// o un caracter suelto residual (longitud % 4 === 1). En ese ultimo caso se
|
|
7
|
+
// descarta unicamente el caracter colgante y el resto se decodifica intacto.
|
|
8
|
+
// Este archivo es inyectado automaticamente por scripts/generate-protobuf.cjs
|
|
9
|
+
// al final de WAProto/index.js tras cada regeneracion.
|
|
10
|
+
// ============================================================================
|
|
11
|
+
(function () {
|
|
12
|
+
var b64 = $protobuf.util.base64;
|
|
13
|
+
if (b64.__kageTolerant)
|
|
14
|
+
return;
|
|
15
|
+
var nativeDecode = b64.decode;
|
|
16
|
+
var nativeLength = b64.length;
|
|
17
|
+
var clean = function (string) {
|
|
18
|
+
var s = $String(string).replace(/[\r\n\t\s]/g, "").replace(/-/g, "+").replace(/_/g, "/");
|
|
19
|
+
var rem = s.length % 4;
|
|
20
|
+
if (rem === 2)
|
|
21
|
+
s += "==";
|
|
22
|
+
else if (rem === 3)
|
|
23
|
+
s += "=";
|
|
24
|
+
else if (rem === 1)
|
|
25
|
+
s = s.slice(0, -1); // caracter colgante: 6 bits sin datos, no aporta bytes
|
|
26
|
+
return s;
|
|
27
|
+
};
|
|
28
|
+
b64.length = function (string) {
|
|
29
|
+
if (typeof string !== "string")
|
|
30
|
+
return nativeLength(string);
|
|
31
|
+
return nativeLength(clean(string));
|
|
32
|
+
};
|
|
33
|
+
b64.decode = function (string, buffer, start) {
|
|
34
|
+
if (typeof string !== "string")
|
|
35
|
+
return nativeDecode(string, buffer, start);
|
|
36
|
+
var s = clean(string);
|
|
37
|
+
try {
|
|
38
|
+
return nativeDecode(s, buffer, start);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// ultimo recurso: elimina cualquier caracter residual no-base64
|
|
41
|
+
return nativeDecode(s.replace(/[^A-Za-z0-9+/=]/g, ""), buffer, start);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
b64.__kageTolerant = true;
|
|
45
|
+
})();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Test del fix base64 tolerante: evita "Error: invalid encoding" en
|
|
3
|
+
// BotSignatureVerificationUseCaseProof (signature / certificateChain).
|
|
4
|
+
const { test } = require('node:test');
|
|
5
|
+
const assert = require('node:assert');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const WAProto = require(path.join(__dirname, '..', 'WAProto', 'index.js'));
|
|
8
|
+
|
|
9
|
+
const makeProof = (signature, certificateChain) => ({
|
|
10
|
+
messageContextInfo: {
|
|
11
|
+
botMetadata: {
|
|
12
|
+
verificationMetadata: {
|
|
13
|
+
proofs: [{ version: 1, useCase: 'WA_BOT_MSG', signature, certificateChain }]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('base64 estandar con padding correcto se decodifica igual que siempre', () => {
|
|
20
|
+
const msg = WAProto.proto.Message.fromObject(makeProof('AAAA', ['QQ==']));
|
|
21
|
+
assert.strictEqual(Buffer.from(msg.messageContextInfo.botMetadata.verificationMetadata.proofs[0].certificateChain[0]).toString(), 'A');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('base64 URL-safe (- y _) se acepta sin error', () => {
|
|
25
|
+
// 'a-b_' es URL-safe; en base64 estricto lanzaria invalid encoding por los caracteres
|
|
26
|
+
const msg = WAProto.proto.Message.fromObject(makeProof('AAAA', ['_-__']));
|
|
27
|
+
assert.ok(msg.messageContextInfo.botMetadata.verificationMetadata.proofs[0].certificateChain[0].length >= 0);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('base64 sin padding se completa automaticamente', () => {
|
|
31
|
+
// 'QQ' (2 chars) sin '==' debe decodificar a 'A'
|
|
32
|
+
const msg = WAProto.proto.Message.fromObject(makeProof('AAAA', ['QQ']));
|
|
33
|
+
assert.strictEqual(Buffer.from(msg.messageContextInfo.botMetadata.verificationMetadata.proofs[0].certificateChain[0]).toString(), 'A');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('base64 con saltos de linea no lanza invalid encoding', () => {
|
|
37
|
+
const msg = WAProto.proto.Message.fromObject(makeProof('AAAA', ['QQ==\n']));
|
|
38
|
+
assert.strictEqual(Buffer.from(msg.messageContextInfo.botMetadata.verificationMetadata.proofs[0].certificateChain[0]).toString(), 'A');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('certificado con caracter colgante (len % 4 === 1) no lanza invalid encoding', () => {
|
|
42
|
+
// Reproduce el caso real de WhatsApp: cadena de 1169 chars (resto 1).
|
|
43
|
+
// El caracter colgante se descarta (6 bits sin datos) y el resto se decodifica.
|
|
44
|
+
const broken = 'TklYRUwuTWVzc2FnZUJ1aWxkZXJWNC43LVZlcmlmaWNhdGlvblNpZ25hdHVyZS5NZXRhZGF0YQ' + 'A';
|
|
45
|
+
const msg = WAProto.proto.Message.fromObject(makeProof('AAAA', [broken]));
|
|
46
|
+
const bytes = msg.messageContextInfo.botMetadata.verificationMetadata.proofs[0].certificateChain[0];
|
|
47
|
+
assert.ok(bytes.length > 0);
|
|
48
|
+
assert.strictEqual(Buffer.from(bytes).toString('utf8', 0, 8), 'NIXEL.Me');
|
|
49
|
+
});
|