Sh4*_*dow 3 javascript qr-code zlib certificate cbor
你好,我正在尝试读取我的绿通证书,我知道当你扫描二维码时,它会出现类似 HC1:NHFDFGDF...... 的内容,我也知道这是编码为 base45 的,所以我做了一个小小的 javascript 解码器,这是我的代码:
\nconst base45 = require(\'base45\');\n\n//of course my personal HC1: isnt here\nconst encodedData = \'C0C9BQF2LVU.TMBX4KDL*XD/GPWBILC9GGBYPLR-SAG1CSQ6U7SSQY%SJWLK34JWLG56H0API0TUL:12>\'\n\nconst decodedData = base45.decode(encodedData).toString(\'utf-8\');\n\nconsole.log(decodedData);\nRun Code Online (Sandbox Code Playgroud)\n这是回应:
\nx\xda\xbb\xef\xbf\xbd\xe2\xbb\x88Q\xef\xbf\xbd\xef\xbf\xbdC#?\xef\xbf\xbd\xef\xbf\xbd-E\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdK\xef\xbf\xbdBX\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xd6\xb3I%|\xef\xbf\xbdzl\xef\xbf\xbd\xc8\xbc\xef\xbf\xbdqIbY\xe3\xaa\xa4\xef\xbf\xbd\xef\xbf\xbd\n\xef\xbf\xbd\xd2\xa2<\xef\xbf\xbd\xd2\xb2\xef\xbf\xbdL\xef\xbf\xbd\xef\xbf\xbd ?\xef\xbf\xbd\xef\xbf\xbd0gO+C\xef\xbf\xbd\xef\xbf\xbd+\xef\xbf\xbd`\xef\xbf\xbd\xef\xbf\xbd`\xd7\x800\xef\xbf\xbdH\'W\xef\xbf\xbdP\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdWwe\xcf\xa4\xef\xbf\xbd|\xef\xbf\xbd\xef\xbf\xbdI)yLI)%YFF\xef\xbf\xbd\xef\xbf\xbdf\xef\xbf\xbdFfI\xef\xbf\xbd\xc5\xa5\xef\xbf\xbd\xef\xbf\xbdy\xef\xbf\xbd\xef\xbf\xbd%\xef\xbf\xbdWe\xef\xbf\xbd+\xef\xbf\xbd$*\'\xde\x95\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdkh\xef\xbf\xbdf\xef\xbf\xbd\xef\xbf\xbdI\xef\xbf\xbd9\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdF\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdF\xef\xbf\xbdI\xef\xbf\xbd)LI%\xef\xbf\xbd&\xef\xbf\xbd\xc6\x96fIeY\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd)\xef\xbf\xbdIY\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdF {\n \xef\xbf\xbdsVp\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd*8\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdz\xef\xbf\xbd8*\xef\xbf\xbd\xef\xbf\xbd:;\'\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\n pMN\xef\xbf\xbd+*\xef\xbf\xbd\xef\xbf\xbd*\xef\xbf\xbd+JN\xef\xbf\xbd+\xef\xbf\xbd\xef\xbf\xbd \xef\xbf\xbd\n \xef\xbf\xbd\xef\xbf\xbd**K-J5\xef\xbf\xbd3\xef\xbf\xbd3\xef\xbf\xbdp8\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdyM]\xef\xbf\xbdo\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdE\xef\xbf\xbd_\xef\xbf\xbd\xef\xbf\xbdO.\xef\xbf\xbd\xcf\xa9\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\n\xef\xbf\xbdg\xef\xbf\xbd\xcb\xbd\xef\xbf\xbd\xef\xbf\xbd\\\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd="\xef\xbf\xbd\xef\xbf\xbd]\xdb\xb7\n\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd{\xef\xbf\xbd\xef\xbf\xbdKq \xef\xbf\xbd\xef\xbf\xbd\nRun Code Online (Sandbox Code Playgroud)\n我读到的是,它的 base45 解码将导致 zlib 压缩文件,其中解压将导致 CBOR Web 令牌,但我卡住了,你能帮助我吗?这个结果正常吗?我还在学习
\n我仅使用浏览器资源(没有node.js)解决了问题;我还找到了一些解释、测试数据、现场解码的官方来源(见答案末尾):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title></title>
</head>
<body>
<textarea id="encoded" name="encoded" cols=100 rows=10></textarea><br>
<textarea id="decoded" name="decoded" cols=100 rows=10 value = "prova">hello</textarea><br>
<span id="plain1" name="plain1">-</span> -->
<span id ="cod" name="cod">-</span> -->
<span id="plain2" name="plain2">-</span><br>
<button onclick="test()">Test</button><br>
<button onclick="vai()">Vai</button><br>
<script src="pako.min.js"></script>
<script src="my_base45_2.js"></script>
<script src="cbor.js" type="text/javascript"></script>
<script>
// https://dev.to/lmillucci/javascript-how-to-decode-the-greenpass-qr-code-3dh0
function convert(decoded) {
text="";
for (var i = 0; i < decoded.length; i++) {
text += String.fromCharCode(decoded[i]);
}
console.log("Text=",text);
values = text.split(",");
console.log("values: " ,values);
final = "";
for (var i=0; i<values.length; i++) {
final += String.fromCharCode(values[i])
}
return final;
}
function test() {
source = document.getElementById("decoded").value;
console.log("source=",source);
document.getElementById("plain1").innerHTML = source;
var enc = new TextEncoder();
buff= enc.encode(source);
console.log("buff:" , buff);
encoded2 = encode(buff);
console.log("encoded2:" , encoded2);
document.getElementById("cod").innerHTML = encoded2;
source = encoded2;
console.log("Encoded source=",source);
decoded = decode(source).enc;
converted = convert(decoded);
console.log("Decoded=", decoded);
console.log("converted=", converted);
document.getElementById("plain2").innerHTML = converted;
}
function buf2hex(buffer) {
// /sf/ask/2401699191/
var u = new Uint8Array(buffer),
a = new Array(u.length),
i = u.length;
while (i--) // map to hex
a[i] = (u[i] < 16 ? '0' : '') + u[i].toString(16);
u = null; // free memory
return a.join('');
};
function typedArrayToBuffer(array) {
// /sf/ask/2605979981/
return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset)
}
function vai() {
source = document.getElementById("encoded").value;
console.log("Encoded source=",source);
// Decode BASE45:
decoded = decode(source).enc;
// Unzip the decoded:
COSEbin = pako.inflate(decode(source).raw);
COSE = buf2hex(COSEbin);
var typedArray = new Uint8Array(COSE.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
})) // /sf/ask/3019186971/
var unzipped = typedArray.buffer;
[headers1, headers2, cbor_data, signature] = CBOR.decode(unzipped);
cbor_dataArr = typedArrayToBuffer(cbor_data);
greenpassData = CBOR.decode(cbor_dataArr);
console.log(greenpassData);
}
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
关键是“双CBOR解码”:一次是不够的:
CBOR解码:
[headers1, headers2, cbor_data, signature] = CBOR.decode(unzipped);
Run Code Online (Sandbox Code Playgroud)
转换为数组:
cbor_dataArr = typedArrayToBuffer(cbor_data);
Run Code Online (Sandbox Code Playgroud)
进一步的 CBOR 转换:
greenpassData = CBOR.decode(cbor_dataArr);
Run Code Online (Sandbox Code Playgroud)
我的base45解码器版本(“my_base45_2.js”),改编自node.js版本:
function encode(uint8array) {
var output = [];
for (var i = 0, length = uint8array.length; i < length; i+=2) {
if (uint8array.length -i > 1) {
var x = (uint8array[i]<<8)+ uint8array[i+1]
var [ e, x ] = divmod(x, 45*45)
var [ d, c ] = divmod(x, 45)
output.push(fromCharCode(c) + fromCharCode(d) + fromCharCode(e))
} else {
var x = uint8array[i]
var [ d, c ] = divmod(x, 45)
output.push(fromCharCode(c) + fromCharCode(d))
}
}
return output.join('')
};
var divmod = function divmod(a,b) {
var remainder = a
var quotient = 0
if (a >= b) {
remainder = a % b
quotient = (a - remainder) / b
}
return [ quotient, remainder ]
}
const BASE45_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
var fromCharCode = function fromCharCode(c) {
return BASE45_CHARSET.charAt(c);
};
function decode(str) {
var output = []
var buf = []
for(var i = 0, length=str.length; i < length; i++) {
//console.log(i);
var j = BASE45_CHARSET.indexOf(str[i])
if (j < 0)
console.log('Base45 decode: unknown character n.', i, j);
//throw new Error('Base45 decode: unknown character');
buf.push(j)
}
for(var i = 0, length=buf.length; i < length; i+=3) {
var x = buf[i] + buf[i + 1] * 45
if (length - i >= 3) {
var [d, c] = divmod(x + buf[i + 2] * 45 * 45,256)
output.push(d)
output.push(c)
} else {
output.push(x)
}
}
console.log("output",output);
var enc = new TextEncoder();
return {"enc" : enc.encode(output), "raw" : output};
//return Buffer.from(output);
};
Run Code Online (Sandbox Code Playgroud)
这些是解码步骤:
QR 码 --> QR DECODER --> RAW QR 解码字符串 --> BASE45 解码器--> zlib 压缩字符串 --> pako 库 --> COSE 字符串 --> CBOR 解码器 --> CBOR 字符串 --> CBOR解码器--> 最终 JSON 文件
我的绿色通行证解码参考指南:
https://dev.to/lmillucci/javascript-how-to-decode-the-greenpass-qr-code-3dh0
| 归档时间: |
|
| 查看次数: |
10715 次 |
| 最近记录: |