Convert a hex string to a byte array and vice versa
note: implementation from crypto-js, though now out of date and slightly altered
// Convert a hex string to a byte array
function hexToBytes(hex) {
let bytes = [];
for (let c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
// Convert a byte array to a hex string
function bytesToHex(bytes) {
let hex = [];
for (let i = 0; i < bytes.length; i++) {
let current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];
hex.push((current >>> 4).toString(16));
hex.push((current & 0xF).toString(16));
}
return hex.join("");
}
Answer from Quark on Stack Overflowjavascript - How to convert hex string into a bytes array, and a bytes array in the hex string? - Stack Overflow
Byte array to Hex string conversion in javascript - Stack Overflow
node.js - How to convert a hex string to a byte and a byte to a hex string in Javascript? - Stack Overflow
javascript - How to convert an array of bytes into string with Node.js? - Stack Overflow
Convert a hex string to a byte array and vice versa
note: implementation from crypto-js, though now out of date and slightly altered
// Convert a hex string to a byte array
function hexToBytes(hex) {
let bytes = [];
for (let c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
// Convert a byte array to a hex string
function bytesToHex(bytes) {
let hex = [];
for (let i = 0; i < bytes.length; i++) {
let current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];
hex.push((current >>> 4).toString(16));
hex.push((current & 0xF).toString(16));
}
return hex.join("");
}
Update: Scroll down for solution... Live Demo
The issue: you are using a lossy conversion to hex, which cannot be reversed.
var p = parseHexString(createHexString(rsa_privk[0]));
This will never be same as rsa_privk[0].
Because, createHexString() only uses the last 2 bytes from each array element.
Example:
rsa_privk[0] : [123676133, 198914513, 129998601, 245147334, 11918451, 206998232, 96766191, 75984899, 177840095, 106709334, 10180427, 208237547, 119814814, 127003446, 189062377, 84099480, 220452154, 250519075, 267883908, 115471915, 165124106, 238628722, 169382478, 42320122, 95982405, 80725759, 89608310, 85166267, 200925925, 254033325, 86971506, 191278317, 127411298, 180195794, 142776693, 188738169, 39016]
createHexString(rsa_privk[0]) : e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed62d2757968
parseHexString(createHexString(rsa_privk[0])) : [229, 209, 9, 198, 115, 216, 239, 3, 223, 86, 75, 235, 158, 54, 233, 152, 58, 35, 132, 43, 10, 114, 78, 250, 69, 255, 118, 187, 229, 173, 114, 237, 98, 210, 117, 121, 104]
Update : Working Solution...
The two functions... the hex always contains 8 byte blocks, each for each element in the array...
function parseHexString(str) {
var result = [];
while (str.length >= 8) {
result.push(parseInt(str.substring(0, 8), 16));
str = str.substring(8, str.length);
}
return result;
}
function createHexString(arr) {
var result = "";
var z;
for (var i = 0; i < arr.length; i++) {
var str = arr[i].toString(16);
z = 8 - str.length + 1;
str = Array(z).join("0") + str;
result += str;
}
return result;
}
Test code...
function test() {
a = [123676133, 198914513, 129998601, 245147334, 11918451, 206998232, 96766191, 75984899, 177840095, 106709334, 10180427, 208237547, 119814814, 127003446, 189062377, 84099480, 220452154, 250519075, 267883908, 115471915, 165124106, 238628722, 169382478, 42320122, 95982405, 80725759, 89608310, 85166267, 200925925, 254033325, 86971506, 191278317, 127411298, 180195794, 142776693, 188738169, 39016];
console.log("Input");
console.log(a);
b = createHexString(a);
console.log("Hex");
console.log(b);
c = parseHexString(b);
console.log("Output");
console.log(c);
if(checkIfEqual(a, c)) {
alert("Same");
}
}
function checkIfEqual(arr1, arr2) {
if (arr1.length != arr2.length) {
return false;
}
//sort them first, then join them and just compare the strings
return arr1.sort().join() == arr2.sort().join();
}
You are missing the padding in the hex conversion. You'll want to use
function toHexString(byteArray) {
return Array.from(byteArray, function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('')
}
so that each byte transforms to exactly two hex digits. Your expected output would be 04812d7e3a9829e5d51bdd64ceb35df060699bc1309731bd6e6f1a5443a7f9ce0af4382fcfd6f5f8a08bb2619709c2d49fb771601770f2c267985af2754e1f8cf9
Using map() won't work if the input is of a type like Uint8Array: the result of map() is also Uint8Array which can't hold the results of string conversion.
function toHexString(byteArray) {
var s = '0x';
byteArray.forEach(function(byte) {
s += ('0' + (byte & 0xFF).toString(16)).slice(-2);
});
return s;
}
Here's a node.js specific approach, taking advantage of the the Buffer class provided by the node standard lib.
https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
To get the byte (0-255) value:
Buffer.from('80', 'hex')[0];
// outputs 128
And to convert back:
Buffer.from([128]).toString('hex');
// outputs '80'
To convert to utf8:
Buffer.from('80', 'hex').toString('utf8');
You can make use of Number.prototype.toString and parseInt.
The key is to make use of the radix parameters to do the conversions for you.
var bytestring = Number('0x' + hexstring).toString(10); // '128'
parseInt(bytestring, 2).toString(16); // '80'
Try this:
new Buffer(bytes).toString('ascii');
More details here: http://nodejs.org/api/buffer.html
You can just use crypto that comes with node:
var Promise = require("bluebird");
var crypto = Promise.promisifyAll(require("crypto"));
crypto.randomBytesAsync(20).then(function(bytes){
console.log('random byte string:', bytes.toString("hex"));
});
Logs:
random byte string: 39efc98a75c87fd8d5172bbb1f291de1c6064849