如何在javascript中将字节数组转换为有符号大整数?

问题描述 投票:0回答:3

有一些优秀的 biginteger.js 库。目前,我正在使用 Tom Wu 的 jsbin.js 在服务器上的浏览器和 java 之间交换匹配的 SRP 密码证明哈希值。

我的问题是,我似乎无法轻松地将表示大有符号整数的字节数组转换为与下面的 Java 代码匹配的 Javascript BigInteger。这是为了能够在浏览器上以匹配两个

RFC 5054
兼容的 java crypto 库(bounceycastle 和 nimbusds)的方式进行哈希处理。对 SRP 协议进行
H(A,B)
哈希处理的两个 Java 库如下:

byte[] output = digest.digest(); // sha256 digest gives byte array
return new BigInteger(1, output); // 1 indicates positive number

这不适用于 bsbin.js 库,因为它没有采用带符号字节数组的构造函数。 JavaScript 没有带符号的字节。在 javascript 中,以与使用

H(A|B)
的字节数组构造函数的两个已发布库一起使用的方式对签名数据进行相同的
java.math.BigInteger
转换的简单方法是什么?

类似以下内容可以将带符号的字节数组转换为大的十进制字符串:

var output = moduleSHA256.hashToBinaryArray(message); // sha256 digest gives byte array
var signedNumberString = someConversion(output); // ???
return new BigInteger(signedNumberString); // this value toString(16) must match Java code

我也愿意尝试不同的 javascript BigInteger 库,它具有 bsbin.js 库的所有数学逻辑,但具有带符号的字节数组样式构造函数。

注意RFC2945 指出将字节序列转换为大数是值得为可互操作的 SRP 协商指定的一个关键实现问题,并指定:

n 字节字符串 S 可以如下转换为整数:

i = S[n-1] + 256 * S[n-2] + 256^2 * S[n-3] + ... + 256^(n-1) * S[0]

上述问题是Java代码使用了BigInteger的字节数组构造函数,它不是平台可移植的,而不是RFC2945中给出的记录转换。

编辑请注意,我已经成功编辑了相关的开源Java加密库,将

H(A|B)
哈希作为简单的字符串连接,并让一切工作正常,与浏览器交换SRP密码证明。但我不想使用也不发布我自己编辑的 java 加密库版本。我想编写与原始且未经编辑的 java SRP 加密逻辑兼容的 javascript。

编辑请注意,一个“修复”是将java更改为对散列返回的字节数组进行十六进制编码,然后使用更平台可移植的构造函数

new BigInteger(hexstring,16)
。这将给出与给定数字完全不同的数字来自
new BigInteger(hashbytes)
但在 Javascript 中是可重复的,并且在我尝试时可以工作。我再次不想发布编辑后的 java crypto 库,所以这不是一个解决方案)。

更新 实际上,我通过在其中一个 java 库中使用新的扩展点来插入

hash -> hex string -> BigInteger
方法来解决这个问题。这个问题仍然代表着人们想让 Javascript 像 java 一样运行,它使用 BigInteger 的字节数组构造函数。

javascript math biginteger
3个回答
1
投票

您可以将字节数组转换为十六进制字符串:

// convert a byte (0-255) to a hex string with two characters 'XX'
function dec2hex(value) {
  return (i + 0x100).toString(16).substr(-2).toUpperCase();
}

var hexStr = byteArray.map(dec2hex).join('');

然后将此十六进制字符串加载到一个大数字库中,例如 bignumber.js:

var num = new BigNumber(hexStr, 16);

0
投票

如果您想将不超过 64 位(8 字节)的 TypedArray 转换为 BigInt,那么我认为最快的方法是在底层数组缓冲区上使用 DataView:

let arr = new UInt8Array(8); // this is the input array
let bigint = new DataView(arr.buffer).getBigInt64(); // you can pass offset in the array and endianness here

您可以扩展该解决方案以将任意长度的数据转换为单个 BigInt。


0
投票

我遇到了同样的问题,我正在寻找 java Big Intege.toByteArray() 并将其转换回 JavaScript 中。

我使用了https://www.npmjs.com/package/big-integer 并使用以下代码

BigInteger(bn).toArray(256).value
为我工作。

© www.soinside.com 2019 - 2024. All rights reserved.