39

The following code procedure bytes = parseHexString (createHexString (bytes)) leads to updated of bytes, what I would like to avoid. And as a result calculations are not correct.

<html>
<head>
<SCRIPT SRC="http://eu.static.mega.co.nz/sjcl_1.js"></SCRIPT>
<SCRIPT SRC="http://eu.static.mega.co.nz/crypto_1.js"></SCRIPT>
<SCRIPT SRC="http://eu.static.mega.co.nz/rsa_1.js"></SCRIPT>
<SCRIPT SRC="http://eu.static.mega.co.nz/hex_1.js"></SCRIPT>
<SCRIPT>
function parseHexString(str) { 
    var result = [];
    while (str.length >= 2) { 
        result.push(parseInt(str.substring(0, 2), 16));
        str = str.substring(2, str.length);
    }

    return result;
}

function createHexString(arr) {
    var result = "";
    for (i in arr) {
        var str = arr[i].toString(16);
        str = str.length == 0 ? "00" :
              str.length == 1 ? "0" + str : 
              str.length == 2 ? str :
              str.substring(str.length-2, str.length);
        result += str;
    }
    return result;
}

function t()
{
    var json_k     = 'aOrP5yLtNQT53WMQfufSlA';
    var json_csid  = 'CABD6JUMldvI_eqP0537xl9P8x7kgk2OjOq99Fy7kosphj6AFUtlbwRRDpg4EIifXRLO6FNpdD22WwtUlJ_1Mgye2Y87trEqLCbhahuEFJVQNMDtNbIem7xY2ER9uF-cdgBXZWuzp7XIBybSh7W8MSUlv_eGS6LcLGJ81Q49dSzVhcswHTJ_IJl04p3c0axR6ZIJ8dH5bJ_vXvgQsypUVVtdfMacKhB9cXdEtRZ6iWLKCKqscXdo6CNXlbIdzRhro0gxfmhfB_miysFAiSQrbtuYnIgYBU3i9p3jRlPD4ti3CUcnj0SomV61w1aEYNvo56HPMUZlVkVHA7BFzvHGHo0J';
    var json_privk = 'K7LDtk2M2QhjJx_v_Hqf0LKUBaZx76U_vBDjQty9HpFDy2MntF5HxxuyHQ9-1HmXeYzbL1pZnAxsZ7LRUbDnkR6qtJVaGdWuQhrytkuq0l5zBp-O--gZxoQPRGTsVgVRdAvpsRTkQI_q8fxADLCe0womFxtvvnD_FJgjaMsm7vkYchXkoq33WWyHijb3JMkymjl0_GtiSamT0qEL6sm_l5Z1lehqBGUEHfYAa0ub8IDx_yqy2R9Nh8Lwzmz4s24sShVxjaNsMBlSE-sEvTziOsnNWK1Zl_XUYadlENkweuIoxYx_lt8XIV71TzjEFuVTd-pXhzVlqePmIu3SM3bO1Kzq_DnGfB62RmzlmbtHU4iyw4Hd1wQFRhTeSRrvMjsMPFKN-SIIQU7CRNaMuaDxZbNZcOKhMg_h9mApM0rRS3VZaGZzFTL9rSaDMYHw4pL3aOkSFPMY3w785Tss7Zqwuo9HFUWUVbnYAb97JkgCohlMotORrMMtual1dQ4sG1sIYXyWTckAGGL0ZAGurhtSKiyz1m8Lb39pXPacqFh_nCHqqb2_RdrKTj0PdGZESKkU8YedeqC1I9nR4v38DuQc-pBBR5DOwgNjJMvzvsUehs_PxIL8THjgIcr7ONc4hWV9o2v_l81Vo2cCW2I99Iz84IFN2fV1dTqHIG_tnLzz8ljBVygETUqrFdZ0JlQJkurZ7RBku5krm-k9CZmDezCIzPPil-RcYzVIk00gNYAxfiZE48Or4WEiGjgKLnHCYVtSlvlMF4bPGB4SVCZ-68j49EjfSWaMK0OoMkpGhqf7KchgxYBZq6o3AhLgp4t0BClvsdee6VTz1SFqc3m2A-TMG6fNdbCT_Q9nYCYdZIROdOc';

    var aes = new sjcl.cipher.aes( prepare_key_pw("oEyoo9cQcw") );
    k = decrypt_key(aes, base64_to_a32(json_k) );

    aes = new sjcl.cipher.aes(k);

    var t = mpi2b(base64urldecode(json_csid));

    var privk = a32_to_str(decrypt_key(aes,base64_to_a32(json_privk)));

    var rsa_privk = Array(4);
    for (var i = 0; i < 4; i++)
    {
        var l = ((privk.charCodeAt(0)*256+privk.charCodeAt(1)+7)>>3)+2;

        rsa_privk[i] = mpi2b(privk.substr(0,l));
        if (typeof rsa_privk[i] == 'number') break;
        privk = privk.substr(l);    
    }

    var p = parseHexString(createHexString(rsa_privk[0]));  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    var q = parseHexString(createHexString(rsa_privk[1]));  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    var d = parseHexString(createHexString(rsa_privk[2]));  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    var u = parseHexString(createHexString(rsa_privk[3]));  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    sid = base64urlencode(b2s(RSAdecrypt(t,d,p,q,u)).substr(0,43));
    if (sid!=='tajetAbW0qTQGFlwp8iD5lQ0TFV1QUZJZFVvjRX7Xx-bPzYBoau7qog09w')
        console.log("ERROR");

    p = rsa_privk[0];
    q = rsa_privk[1];
    d = rsa_privk[2];
    u = rsa_privk[3];
    sid = base64urlencode(b2s(RSAdecrypt(t,d,p,q,u)).substr(0,43));
    if (sid=='tajetAbW0qTQGFlwp8iD5lQ0TFV1QUZJZFVvjRX7Xx-bPzYBoau7qog09w')
        console.log("OK");
}
</script>

</head>
<body onload="t();"></body>
</html>

I am not javascript developer, and not one found in google code did not work on this data.

Update 1

console.log(createHexString(rsa_privk[0])); = e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed62d2757968 

But if do

parseHexString('e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed‌​62d2757968'); 

then code if (sid!== ... make error

Update 2

console.log(rsa_privk[0].toString(16));

output: 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

Update 3

console.log(parseHexString(createHexString(rsa_privk[0])));
console.log(rsa_privk[0]);

output:

[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]

[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]
7
  • What data are you expecting and what data are you getting? Commented Jan 30, 2013 at 11:47
  • I expect that the transformation data = parseHexString (createHexString (data)) not change the data Commented Jan 30, 2013 at 11:51
  • Copy paste your input to createHexString(rsa_privk[0]), ie console.log(rsa_privk[0]);. Commented Jan 30, 2013 at 11:59
  • console.log(createHexString(rsa_privk[0])); = e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed62d2757968 But if do parseHexString('e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed62d2757968'); then code if (sid!== ... make error Commented Jan 30, 2013 at 12:10
  • See my updated answer, just add the console.log line and copy paste the whole output in your question. Commented Jan 30, 2013 at 12:25

7 Answers 7

86

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("");
}
Sign up to request clarification or add additional context in comments.

8 Comments

THIS works. Nothing else worked for me. Thank you SO much.
Just a reminder, crypto-js api has changed to CryptoJS.enc.Hex.parse(), there is no hexToBytes
The code has changed a little from the original. Here is the link to the latest bytesToHex (stringify) and hexToBytes (parse) methods: crypto-js/core.js#L390
bytesToHex calculates strange on some circumtances. e.g. [159,15] is been calculated as '9f0f' it should be '9ff'. [25,255] does work again. Is this an endianess thing? The issues are beginning with 9th bit of the first array element. Function createHexString from the accepted answer works for me.
@TefoD I cannot reproduce your issue. the code works good to me
|
14

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();
}

10 Comments

What is your input and output?
The data is in binary form in the code above. The question is how to display them in hex ​​format. But I'm sure not getting the correct result, because with inverse transformation data is not correctly.
What is your data like? Copy paste the data here.
data is binary, I can not insert here the binary data!!! they are calculated in the above code. And I do not know how to properly convert them to hex and back to binary
arr[i] gives back a character. what you want is the byte number from the character which you can get with .charCodeAt( ... )
|
9

I just wanted to chime in that there is a library at https://github.com/dcodeIO/bytebuffer.js to easily help with conversions like this, and thus you don't need to write your own functions (which could possibly not be the most optimal, or be more optimal if your solution was reviewed through the open source community on GitHub).

var ByteBuffer = require("bytebuffer");

var bb = ByteBuffer.fromHex(yourHexString);

// need to convert it to base 64?
// bb.toBase64();

See https://github.com/dcodeIO/bytebuffer.js/wiki/API#bytebufferfromhexstr-littleendian-noassert for the API documention and more insight on the methods I used above.

Comments

3

Just to clarify, if you simply want to hex decode a simple string such as 48656C6C6F20576F726C6421 (Hello World!) you can use the OP function but instead of using a length of 8 you should use a length of 2.

Code:

var DecodeHexStringToByteArray = function (hexString) {
   var result = [];
   while (hexString.length >= 2) { 
       result.push(parseInt(hexString.substring(0, 2), 16));
       hexString = hexString.substring(2, hexString.length);
   }
   return result;
}

Output will be [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

I know that this code is already in the OP question, but it's not in the accepted answer. My intent here is only to give a straight answer to the first part of the question being asked (How to convert a hex string into a bytes array).

Comments

3

I found solution over here enter link description here

function hexStringToByteArray(hexString) {
    if (hexString.length % 2 !== 0) {
        throw "Must have an even number of hex digits to convert to bytes";
    }
    var numBytes = hexString.length / 2;
    var byteArray = new Uint8Array(numBytes);
    for (var i=0; i<numBytes; i++) {
        byteArray[i] = parseInt(hexString.substr(i*2, 2), 16);
    }
    return byteArray;
}

once again thank you http://www.java2s.com

Comments

0

Here is a live sample for this test.

http://jsfiddle.net/vincentwang2020/eks1z4g2/

function testcreateHexString()
{
    alert('test function createHexString');
    var key = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
    var result = createHexString(key);
    alert ('Hex value:' + result);

    alert('test function parseHexString');

    var key2 = parseHexString(result);

    if (key.sort().join() == key2.sort().join())
        alert ('Matched');

}

Comments

0

Here's some potentially inefficient one-liners if that's your deal:

const h2b = /** @param {string} s */ s => new Uint8Array([...s.matchAll(/../g)].map(m => parseInt(m[0], 16)));
const b2h = /** @param {Uint8Array} b */ b => [...b].map(n => n.toString(16)).join("");

and some test code

import { expect, test } from "vitest";

test("h2b", () => {
    const h = "deadB33F";
    const b = new Uint8Array([0xde, 0xad, 0xb3, 0x3f]);

    expect(h2b(h), "h2b").toEqual(b);
    expect(b2h(b), "b2h").toEqual(h.toLowerCase());
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.