简体   繁体   中英

how to convert byte array into a signed big integer in javascript?

There are some excellent biginteger.js libraries out there. Currently I am using jsbin.js by Tom Wu to exchange matching SRP proof-of-password hashes between a browse and java on the server.

My problem is that I cannot seem to easily convert a byte array representing a large signed integer into a Javascript BigInteger which matches the Java code below. This is required to be able to hash at the browser in a way which matches two RFC 5054 compliant java cryto libraries (bounceycastle and nimbusds). The two java libraries which do H(A,B) hashing of the SRP protocol as:

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

That does not work with the bsbin.js library as it does not have a constructor which takes a signed byte array. Javascript doesn't have signed bytes. Whats the easy way to do the same H(A|B) conversion to signed data in javascript in a way which works with the two published libraries which use the byte array constructor of java.math.BigInteger ?

Something like the following would work to convert the signed byte array into a large decimal string:

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

I am also willing to try a different javascript BigInteger library which has all the math logic of the bsbin.js library but which has a signed byte array style constructor.

NB RFC2945 points out that converting a sequence of bytes into a big number is one key implementation issue worth specifying for interoperable SRP negotiation and specifies:

An n-byte string S can be converted to an integer as follows:

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

The problem as stated above is that the Java code uses the byte array constructor of BigInteger which is not platform portable rather than the documented conversion given in RFC2945.

( Edit Please note I have successfully edited the opensource Java cryptography libraries in question to do H(A|B) hashing as trivial string concat and got everything all working fine exchanging SRP password proofs with a browser. Yet I don't want to use nor publish my own edited versions of java cryptography libraries. I want to write javascript which is compatible with original and unedited java SRP crypto logic).

( Edit Please note one 'fix' is the change the java to hex encode the byte array returned by the hash then use the constructor new BigInteger(hexstring,16) which is more platform portable. That would give an entirely different number to the number given from new BigInteger(hashbytes) but is repeatable in Javascript and works when I tried that. Once again I don't want to publish edited java crypo libraries so this is not a solution).

Update I actually got around this problem by using a new extension point in one of the java libraries to plug in a hash -> hex string -> BigInteger approach. The problem still stands for people wanted to make Javascript run like java which uses the byte array constructor of BigInteger.

You could convert your byte array to a hex string:

// 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('');

and then load this hex string into a bignumber library like bignumber.js :

var num = new BigNumber(hexStr, 16);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM