Hash code which contains more than 16 characters? - javascript

I would like to apply a hash code solution on my webpage which is more compact than MD5 and SHA-1, because I want to use them as keys in a JSON hash table.
Or equivalently: how can I convert a hexadecimal MD5 hash to a higher base number system? The higher the better, till the words can be used as keys in a JSON hash. For example instead of:
"684591beaa2c8e2438be48524f555141" hexadecimal MD5 hash I would prefer "668e15r60463kya64xq7umloh" which is a base 36 number and the values are equal.
I made the calculation in Ruby:
"684591beaa2c8e2438be48524f555141".to_i(16).to_s(36)
=> 668e15r60463kya64xq7umloh
Because it handles the big decimal value of the hexadecimal MD5 hash (138600936100279876740703998180777611585)
Unlike JavaScript, in JavaScript I get a float value, which is rounded. So I get the same 36-base value for different MD5 hashes.

Ruby
You could return base64digest directly :
require 'digest'
Digest::MD5.hexdigest 'your_page'
#=> "a6b580481008e60df9350de170b7e728"
p Digest::MD5.base64digest 'your_page'
#=> "prWASBAI5g35NQ3hcLfnKA=="
Javascript
If you already have a hex string, a comment from this previous answer seems to work fine :
btoa("a6b580481008e60df9350de170b7e728".match(/\w{2}/g).map(function(a){return String.fromCharCode(parseInt(a, 16));} ).join(""))
#=> "prWASBAI5g35NQ3hcLfnKA=="

Related

Maintain decimal points with 0 in JSON object [duplicate]

If you do this...
var parsed = JSON.parse('{"myNum":0.0}') ;
Then when you look at parsed.myNum, you just get 0. (Fair enough.)
If you do parsed.myNum.toString(), you get "0".
Basically, I'm looking for a way to turn this into the string "0.0".
Obviously, in real life I don't control the JSON input, I get the JSON from a web service... I want to parse the JSON using the browser's JSON parser, and to be able to recognise the difference between the number values 0 and 0.0.
Is there any way to do this, short of manually reading the JSON string? That's not really possible in this case, I need to use the browser's native JSON parser, for speed. (This is for a Chrome extension by the way; no need to worry about it working in other browsers.)
There's no way to get the number of digits from JSON.parse or eval. Even if IBM's decimal proposal had been adopted by the EcmaScript committee, the number is still going to be parsed to an IEEE 754 float.
Take a look a http://code.google.com/p/json-sans-eval/source/browse/trunk/src/json_sans_eval.js for a simple JSON parser that you can modify to keep precision info.
If 0.0 is not enclosed in quotes in your JSON (i.e. it's a number and not a string), then there's no way to distinguish it from 0, unless you write your own JSON parser.
... parsed.myNum.toFixed( 1 ) ...
where 1 is number of decimal places
Edit: parsed.myNum is number, parsed.myNym.toFixed( 1 ) would be string
Edit2: in this case you need to pass value as string {"myNum":'0.0'} and parsed when calculations is needed or detect decimal separator, parsed number, and use decimal separator position when string is needed
It shouldn't matter, 00000.00000 is 0 if you try JSON.parse('{"myNum":0.00001}') you'll see a value of { myNum=0.0001 } If you really need it to hold the decimal you'll need to keep it a string JSON.parse('{"myNum":"0.0"}')

Why I can't use some of HEX-colors that include letters in my embed?

I'm trying to use HEX-color with letters (ex. 2c2f33) and it doesn't work, but If I use something as "3447003" it works. So what should I do to make it work?
message.channel.send({embed: {
color: 2c2f33,
fields: [
{ name: "Gaming Roles:", value: "<:gta:605106790534742057><#&587234726834733056>\n<:r6s:605106790677348372><#&587234959752822824>\n<:Fortnite:605106790580879361><#&587461980172976168>\n󠇰<:pubg:605106790690193428><#&587240268068159497>\n<:arma:605109711703900170><#&587238820890804224>\n<:division:605106790673416202><#&587239012909973517>", inline: true}
]
A color field within an embed object in Discord's Javascript API is of the type integer, meaning that it will only take a number as a value. The Hexadecimal number system is of base 16, meaning that the first 16 numbers are represented using 16 different symbols (0-9, A-F). Because the color field can only take numeric characters and not alphanumeric characters, Hexadecimal doesn't work. Thus, Discord's API team decided to use the vastly more common decimal (base 10) number system, the system we use every day with 10 symbols that are all numeric characters. This way, the input in your code will only be numbers.
You have two options that I can think of:
Convert your colors yourself from Hexadecimal to Decimal, then use the result in your program instead of the hex code. The math needed to do this by hand is off-topic, but I can link you to this website to do it for you. This option can be somewhat tedious (even if you use a website) because of the copying and pasting.
put 0x before your hex code in the code. I'm not 100% sure this would work in JS; What it does is it marks the number as being hexadecimal, then converts it to decimal for you.
Resources:
https://discordapp.com/developers/docs/resources/channel#DOC_CHANNEL/embed-object
https://simple.wikipedia.org/wiki/Hexadecimal_numeral_system
Related Tags:
javascript, hexadecimal, discord.js
Use a string containing your hexadecimal value.
embed: {
color: "2c2f33",
fields: [...]
}
When creating a RichEmbed, the color property can be set to a ColorResolvable, so it can be any of the following:
Hex Literal
Hex String
Number
RGB Array
See hyperlinked documentation page for a list of pre-defined strings.

Reassembling negative Python marshal int's into Javascript numbers

I'm writing a client-side Python bytecode interpreter in Javascript (specifically Typescript) for a class project. Parsing the bytecode was going fine until I tried out a negative number.
In Python, marshal.dumps(2) gives 'i\x02\x00\x00\x00' and marshal.dumps(-2) gives 'i\xfe\xff\xff\xff'. This makes sense as Python represents integers using two's complement with at least 32 bits of precision.
In my Typescript code, I use the equivalent of Node.js's Buffer class (via a library called BrowserFS, instead of ArrayBuffers and etc.) to read the data. When I see the character 'i' (i.e. buffer.readUInt8(offset) == 105, signalling that the next thing is an int), I then call readInt32LE on the next offset to read a little-endian signed long (4 bytes). This works fine for positive numbers but not for negative numbers: for 1 I get '1', but for '-1' I get something like '-272777233'.
I guess that Javascript represents numbers in 64-bit (floating point?). So, it seems like the following should work:
var longval = buffer.readInt32LE(offset); // reads a 4-byte long, gives -272777233
var low32Bits = longval & 0xffff0000; //take the little endian 'most significant' 32 bits
var newval = ~low32Bits + 1; //invert the bits and add 1 to negate the original value
//but now newval = 272826368 instead of -2
I've tried a lot of different things and I've been stuck on this for days. I can't figure out how to recover the original value of the Python integer from the binary marshal string using Javascript/Typescript. Also I think I deeply misunderstand how bits work. Any thoughts would be appreciated here.
Some more specific questions might be:
Why would buffer.readInt32LE work for positive ints but not negative?
Am I using the correct method to get the 'most significant' or 'lowest' 32 bits (i.e. does & 0xffff0000 work how I think it does?)
Separate but related: in an actual 'long' number (i.e. longer than '-2'), I think there is a sign bit and a magnitude, and I think this information is stored in the 'highest' 2 bits of the number (i.e. at number & 0x000000ff?) -- is this the correct way of thinking about this?
The sequence ef bf bd is the UTF-8 sequence for the "Unicode replacement character", which Unicode encoders use to represent invalid encodings.
It sounds like whatever method you're using to download the data is getting accidentally run through a UTF-8 decoder and corrupting the raw datastream. Be sure you're using blob instead of text, or whatever the equivalent is for the way you're downloading the bytecode.
This got messed up only for negative values because positive values are within the normal mapping space of UTF-8 and thus get translated 1:1 from the original byte stream.

Javascript encoding breaking & combining multibyte characters?

I'm planning to use a client-side AES encryption for my web-app.
Right now, I've been looking for ways to break multibyte characters into one byte-'non-characters' ,encrypt (to have the same encrypted text length),
de-crypt them back, convert those one-byte 'non-characters' back to multibyte characters.
I've seen the wiki for UTF-8 (the supposedly-default encoding for JS?) and UTF-16, but I can't figure out how to detect "fragmented" multibyte characters and how I can combine them back.
Thanks : )
JavaScript strings are UTF-16 stored in 16-bit "characters". For Unicode characters ("code points") that require more than 16 bits (some code points require 32 bits in UTF-16), each JavaScript "character" is actually only half of the code point.
So to "break" a JavaScript character into bytes, you just take the character code and split off the high byte and the low byte:
var code = str.charCodeAt(0); // The first character, obviously you'll have a loop
var lowbyte = code & 0xFF;
var highbyte = (code & 0xFF00) >> 8;
(Even though JavaScript's numbers are floating point, the bitwise operators work in terms of 32-bit integers, and of course in our case only 16 of those bits are relevant.)
You'll never have an odd number of bytes, because again this is UTF-16.
You could simply convert to UTF8... For example by using this trick
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
function decode_utf8(s) {
return decodeURIComponent(escape(s));
}
Considering you are using crypto-js, you can use its methods to convert to utf8 and return to string. See here:
var words = CryptoJS.enc.Utf8.parse('𤭢');
var utf8 = CryptoJS.enc.Utf8.stringify(words);
The 𤭢 is probably a botched example of Utf8 character.
By looking at the other examples (see the Latin1 example), I'll say that with parse you convert a string to Utf8 (technically you convert it to Utf8 and put in a special array used by crypto-js of type WordArray) and the result can be passed to the Aes encoding algorithm and with stringify you convert a WordArray (for example obtained by decoding algorithm) to an Utf8.
JsFiddle example: http://jsfiddle.net/UpJRm/

JSON transfer of bigint: 12000000000002539 is converted to 12000000000002540?

I'm transferring raw data like [{id: 12000000000002539, Name: "Some Name"}] and I'm getting the object [{id: 12000000000002540, Name: "Some Name"}] after parsing, for now server side converting id into string seems to help.
But is there a better way to transfer bigint data correctly?
The value is actually not exceeding the maximum numeric value in JavaScript (which is "only" 1.7308 or so).
However, the value is exceeding the range of "integral precision". It is not that the wrong number is sent: rather, it is that the literal 12000000000002539 can only be represented as precisely as 12000000000002540, and thus there was never the correct numeric value in JavaScript. (The range of integrals is about +/- 253.)
This is an interesting phenomena of using a double relative-precision (binary64 in IEEE-754 speak) type to store all numeric values, including integers:
12000000000002539 === 12000000000002540 // true
The maximum significant number of decimal digits that be precisely stored as a numeric value is 15 (15.95, really). In the above, there are 17 significant digits, so some of the least-significant information is silently lost. In this case, as the JavaScript parser/engine reads in the literal value.
The only safe way to handle integral numbers of this magnitude in JavaScript is to use a string literal or to break it down in another fashion (e.g. a custom numeric type or a "bigint library"). However, I recommend just using a string, as it is human readable, relatively compact (only two extra characters in JSON), and doesn't require special serialization. Since the value is just an "id" in this case, I hope that math does not need to be performed upon it :)
Happy coding.

Categories

Resources