Elegant way to split hex string at byte 00? - javascript

I need to split a hex string at every 00 byte. I tried this:
string.split('00');
But that causes splits at 5009, for instance, which is incorrect because it is splitting a byte in half.
In other words, it turns 5009 to [5, 9], which I don't want. But I do want it to turn af0059 to [af, 59].
Is it even possible to split bytes using regex, without cutting any bytes in half?
I could use a loop to seek through the string and only divide the string at even-number indices, but I would much prefer a regex expression.

Because of the byte sizes, you need to first split the string into byte-sizes, then map and finally join.
const string = "af00b9e00f70";
const res = string.split(/([\d\w]{4})/).filter(e => e).map(e => e.replace(/00([\d\w]{2})/, "$1").replace(/([\d\w]{2})00/, "$1")).join("");
console.log(res);

Here's a somewhat "old school' approach, but it demonstrates the principal. I say "old school' because we had to do this all the time back in the days of assembler coding. 'string' contains your long string of hex pairs (bytes). Here I convert it to byte values. Change the 'string' to whatever you want, but be sure it has an even number of hex digits. Call 'translate' to demonstrate it, and format the output into an alert() (or just output to the console)
var values = []; // output array
var string = "000102030405060708090a0b0c0d0e0f1FFFFEFDFCFBFAF9F8F7F6F5F4F3F2F0";
function getHexByteValues( string) {
var hex= "0123456789ABCDEF";
var outIx=0;
for (var i =0; i <= (string.length-2); i +=2) { // skip every other
//get higher and lower nibble
var hexdig1 = string.substring(i, i+1);
var hexdig0 = string.substring(i+1, i+2);
// for simplicity, convert alpha to upper case
hexdig1 = hexdig1.toUpperCase();
hexdig0 = hexdig0.toUpperCase();
// convert hex to decimal value.
// position in lookup string == value
var dec1 = hex.indexOf(hexdig1);
var dec0 = hex.indexOf(hexdig0);
// calc "byte" value, and add to values.
values[outIx++] = dec1 * 16 + dec0;
}
}
function translate(string) {
getHexByteValues(string);
var output="";
for (var i =0; i < values.length; i++) {
output += i + " = " + values[i] + "\r\n";
}
alert (output);
}

Maybe not the most elegant, but it works
const inp = "af00b9e00f70"
const out = inp.match(/.{1,2}/g).map(a=>a=="00"?"_":a).join("").split("_");
console.log(out);

Related

decode numbers in an array and compare to different array

I have 2 arrays, one containing numbers and another one containing encoded numbers.
I need to match the encoded numbers to the normal numbers to find a match. The trick is that I need to decode the numbers to find a match.
let encoded = ['310254#3543129', '03254#03715P5'];
let numbers = ['3102540003543129', '0325400003715445', ...]
I have tried using a for loop with recursion for when there are multiple special characters in the string, but I am not getting the results correctly.
for (let i = 0; i < encrypted.length; i++) {
for (let j = 0; j < numbers.length; j++) {
function removeSpecialChars(referenceNumber) {
if(!/^\d*$/.test(referenceNumber)){
for (let x = 0, invalidChar = ''; invalidChar = referenceNumber.charAt(x); x++) {
let newString = '';
// which char is invalid
if (!/^\d*$/.test(invalidChar)) {
for(let y = 0; i < numbers[j].split('').length; y++){
if(numbers[j].split('')[x] === numbers[j].split('')[x + y]){
newString += numbers[j].split('')[x];
} else break;
}
return removeSpecialChars(referenceNumber.replace(invalidChar, newString));
}
}
}
return referenceNumber;
} // end function
if (removeSpecialChars(encrypted[i]) === numbers[j]) {
count++;
}
}
}
I am not sure if I am approaching this in the wrong way entirely or if I am just missing something.
Here is a fiddle to reproduce my results.
https://jsfiddle.net/6ezuwhdb/1/
it seems that there are at least 2 rules at play here (I haven't looked at the fiddle in any detail but what there is here can be easily extended):
000 is encoded with a #, and
44 is encoded with a P
I would first get a complete list of these rules together and then use regular expressions to replace all instances of the special characters with their numeric equivalents.
The regular expressions use the g modifier so that all instances of the encoded value get replaced within the string.
const encoded = ['310254#3543129', '03254#03715P5'];
const decoded = encoded.map(en => {
// replace the special characters using multiple regular expressions
let result = en;
// swap all #'s for
result = result.replace(/#/g, '000');
// swap all P's for 44
result = result.replace(/P/g, '44');
// add more rules here ...
return result;
});
console.log('Decoded numbers: ', decoded);
To then check whether the normal numbers can be found within the decoded set of numbers is fairly straight forward.
// From previous step ;o)
const decoded = [
"3102540003543129",
"0325400003715445"
];
const numbers = ['3102540003543129', '0325400003715445'];
const matchedNumbers = numbers.filter(number => {
return decoded.indexOf(number) >= 0;
});
console.log(matchedNumbers);

Converting from utf8 to hex and back with Javascript

I'm trying to encrypt text using WebCrypto. I convert the result to a utf8 string, then convert that to hex. The encryption/decryption works. However, I want to convert the data to hex. When I try to convert to hex and back, the result is different.
Here's the fiddle (use Chrome): https://jsfiddle.net/yxp01v5g/
The test code is here:
var text = "hello world";
var key = App.crypto.generateKey(16);
App.crypto.encrypt(text, key, function(encryptedText, iv){
console.log("encrypted text:", encryptedText, "iv", iv);
var encryptedTextHex = convertUtf8StringToHex(encryptedText);
console.log("encrypted text hex", encryptedTextHex);
var backToUtf8 = convertHexToUtf8(encryptedTextHex);
console.log("Back to utf8", backToUtf8);
console.assert(encryptedText == backToUtf8);
})
As you can see, I'm taking the result, converting it to hex, then converting it back to utf8, hoping for it to be equal to the original result. However, it's not.
Can anyone tell me what on earth I'm doing wrong?
I didn't dig too deep into the call-chain used in the fiddle to do the conversion, but it appears to try converting UTF-16/UCS-2 to byte size instead of an actually hex representation of the buffer content itself.
Here is one approach to convert the byte buffer content to hex string representation, and from hex string back to binary data.
It takes each byte in the buffer and produced a two-digit hex representation of its value, and concatenates it to a string.
The reverse takes two chars from the string representation and converts it back to a byte value representation.
// some bytes as Uint8Array
var random = crypto.getRandomValues(new Uint8Array(16)), i, str = "", allOK = true;
// convert to HEX string representation
for(i = 0; i < random.length; i++) str += pad2(random[i].toString(16));
console.log(str);
// convert back to byte buffer
var buffer = new Uint8Array(random.length);
for(i = 0; i < buffer.length; i++) buffer[i] = parseInt(str.substr(i<<1, 2), 16);
// check if same content
for(i = 0; i < buffer.length; i++) if (buffer[i] !== random[i]) allOK = false;
console.log("All OK?", allOK)
function pad2(s) {return s.length < 2 ? "0" + s : s}; // helper: pad to 2 digits

How to make a single string into a multitude of strings?

I have a string called e3 which holds the string 1,2,4,5,3,6. I want to add up all of those numbers up to make the number 21 I was considering doing a for loop for this however I do not know how to turn part of a string into its own value.
I anyone has any better idea of what to do please comment, or answer.
You could use String#split for the string and use Array#reduce for summing.
var e3 = '1,2,4,5,3,6',
sum = e3.split(',').reduce(function (a, b) {
return a + +b; // +b forces b to number
}, 0);
console.log(sum);
If you are sure that it is always a comma separated list of numbers, you could split it on the comma into an array and then use array.reduce() to sum them
var asString = '1,2,4,5,3,6';
var asArray = asString.split(',');
var total = asArray.reduce(function(prev, current){
return prev + parseInt(current, 10);
}, 0);
console.log(total) // outputs 21;
You can do it like this:
var e3 = "1,2,4,5,3,6";
// Split by separator ','
var stringsArr = e3.split(',');
var sum = 0;
// Loop through array of string numbers
stringsArr.forEach(function(str) {
// get Int from a string
var strVal = parseInt(str, 10);
sum += strVal;
});
here's the fiddle
Here is working code to do what you need: https://plnkr.co/edit/8LSkZi0oC8msbHI0qOrz?p=preview
At first you use the split method - this separates a string into an array of strings, based on some separator value. In our case, the separator is a comma, but it could be a blank space or something else:
var testString = '1,2,4,5,3,6';
var separator = ',';
function splitStringOnCommasAndGetArray(string, separator){
var arrayOfStrings = string.split(separator);
return arrayOfStrings;
}
After that, we loop through the array and turn each value into a number. We add the numbers, like so:
function addUpArray(arrayOfStrings){
var totalNumber = 0;
for(var i = 0; i < arrayOfStrings.length; i++){
var currentNum = parseInt(arrayOfStrings[i]);
console.log(currentNum);
totalNumber += currentNum;
}
return totalNumber;
}

How to build a binary-array from hex strings

I'm new to the concept of working with data on the binary level and am hoping someone can give me a hand here...
I'd like to build a binary buffer out of a series of hex numbers that are represented as strings.
For example,
suppose I have "xFCx40xFF" and I want to turn this into an array that looks like: 111111000100000011111111.
What's the best way to do this?
My best attempt seems to not be working:
var raw = "xFCx40xFF"
var end = raw.length-2;
var i = 1;
var j = 0;
var myArray = new Uint8Array(raw.len);
while (i < end) {
var s = raw.substr(i,2);
var num = parseInt(s,16);
i += 3;
myArray[j] = num;
j += 8;
}
Each 3 characters in string will represent 1 number in Uint8Array. Each number in Uint8Array will represent 8 bits. Your code was creating Uint8Array larger than needed and then placing values are wrong locations.
I have simplified the code to use a singe index i which represents the location in the Uint8Array. Corresponding location in string can be easily computed from i.
var raw = "xFCx40xFF"
var myArray = new Uint8Array(raw.length / 3);
for (var i = 0; i < raw.length / 3; i++) {
var str = raw.substr(3 * i + 1, 2);
var num = parseInt(str, 16);
myArray[i] = num;
}
Remove the 'x' character of your hex string and call parseInt() with the radix 16 and toString() with the radix 2 to get the binary string.
var raw = "xFCx40xFF";
var bin = parseInt(raw.split('x').join(''), 16).toString(2);
document.body.textContent = bin;
and if you need an array, just add .split('') at the end.
parseInt(raw.split('x').join(''), 16).toString(2).split('');
or iterate through each character.

Splitting a number into an array

Alright so I'm trying to completely split a number into an Array. So for example:
var num = 55534;
var arr = []; <- I would want the Array to look like this [5,5,5,3,4]
Basically i want to to completely split the number apart and place each Number into its own element of the array. Usually in the past i would just convert the number into a string then use the .split() function. This is how i use to do it:
num += "";
var arr = num.split("");
But this time i actually need to use these numbers, so they can not be strings. What would you guys say be the way of doing this?
Update, after the edit for some reason my code is crashing every run:
function DashInsert(num) {
num += "";
var arr = num.split("").map(Number); // [9,9,9,4,6]
for(var i = 0; i < arr.length; i++){
if(arr[i] % 2 === 1){
arr.splice(i,0,"-");
}// odd
}
return arr.join("");
}
String(55534).split("").map(Number)
...will handily do your trick.
You can do what you already did, and map a number back:
55534..toString().split('').map(Number)
//^ [5,5,5,3,4]
I'll do it like bellow
var num = 55534;
var arr = num.toString().split(''); //convert string to number & split by ''
var digits = arr.map(function(el){return +el}) //convert each digit to numbers
console.log(digits); //prints [5, 5, 5, 3, 4]
Basically I'm converting each string into numbers, you can just pass Number function into map also.

Categories

Resources