is there any builtin javascript string hash function in newest browsers? - javascript

Everytime a new versions of browsers show up I hear about new stuff being added, like say webGL and other technologies that no one really knows if they catch up.
But I wonder if someone ever thought about such basic stuff in JS like hashing functions (MD5,SHA1 and the like).
By newest browsers I mean today's development versions too like Opera 12, Chrome 17 or Firefox 10.
Looking now for solution I found this comment on another thread here: https://stackoverflow.com/questions/7204097/short-hashing-function-for-javascript (Do you know that javascript objects already are hashtables ?). So what are these 'hashtables' ? Does it mean that I can make any string into a hash, but not an established one like md5 or sha1 but some JS build in specific ?
basically what I need to do is:
var txt="Hello world!";
var hash = txt.toSha1();

For anybody still looking for this information. There is a WebCrypto API which appears to have been finalised at the beginning of 2017.
To use it in a browser, you can find it at window.crypto.subtle which contains methods for encryption, digests etc. Documentation on the available functions here.

Paul Johnston has implemented the following algorithms in javascript
MD5, RIPEMD-160, SHA-1, SHA-256 and sha-512
You can find the source code and some examples here:
http://pajhome.org.uk/crypt/md5/
I hope this is what you were looking for.

async function sha256(source) {
const sourceBytes = new TextEncoder().encode(source);
const digest = await crypto.subtle.digest("SHA-256", sourceBytes);
const resultBytes = [...new Uint8Array(digest)];
return resultBytes.map(x => x.toString(16).padStart(2, '0')).join("");
}

Note: This answer was written in 2014 when the Web Cryptography API was not available. Do not use this in the context where cryptographic security is needed. This may be useful when you need a simple reversible encryption with "builtin" support.
When I need simple client side hashing without external libraries I use the browsers' built in atob() and btoa() functions.
window.btoa() creates a base-64 encoded ASCII string from a "string" of binary data.
function utf8_to_b64( str ) {
return window.btoa(encodeURIComponent( escape( str )));
}
The window.atob() function decodes a string of data which has been encoded using base-64 encoding.
function b64_to_utf8( str ) {
return unescape(decodeURIComponent(window.atob( str )));
}
http://caniuse.com/#search=btoa and http://caniuse.com/#search=atob shows it is hugely supported by the modern browsers
Example taken from https://developer.mozilla.org/en-US/docs/Web/API/window.btoa

Related

Decompressing bzip2 data in Javascript

I ultimately have to consume some data from a Javascript file that looks as follows:
Note: The base64 is illustrative only.
function GetTripsDataCompressed() { return 'QlpoOTFBWSZTWdXoWuEDCAgfgBAHf/.....=='; }
GetTripsDataCompressed() returns a base64 string that is derived as an array of objects converted to JSON using JSON.NET and the resulting string then compressed to bzip2 using SharpCompress with the resulting memory stream Base64 encoded.
This is what I have and cannot change it.
I am struggling to find a bzip2 JavaScript implementation that will take the result of:
var rawBzip2Data = atob(GetTripsDataCompressed());
and convert rawBzip2Data back into the string that is the JSON array. I cannot use something like compressjs as I need to support IE 10 and as it uses typed arrays that means IE10 support is out.
So it appears that my best option is https://github.com/antimatter15/bzip2.js however because I have not created an archive and only bzip2 a string it raises an error of Uncaught No magic number found after doing:
var c = GetTripsDataCompressed();
c = atob(c);
var arr = new Uint8Array(c);
var bitstream = bzip2.array(arr);
bzip2.simple(bitstream);
So can anyone help me here to decompress a BZip2, Base64 encoded string from JavaScript using script that is IE 10 compliant? Ultimately I don't care whether it uses https://github.com/antimatter15/bzip2.js or some other native JavaScript implementation.
It seems to me the answer is in the readme:
decompress(bitstream, size[, len]) does the main decompression of a single block. It'll return -1 if it detects that it's the final block, otherwise it returns a string with the decompressed data. If you want to cap the output to a certain number of bytes, set the len argument.
Also, keep in mind the repository doesn't have a license attached. You'll need to reach out to the author if you want to use the code. That might be tricky given that the repository is eight years old.
On the other hand, the Bzip2 algorithm itself is open-source (BSD-like license), so you can just reimplement it yourself in Javascript. It's just a few hundred lines of relatively straight-forward code.

How to make SJCL and Python hashlib generate identical pdkdf2 output

I have a JavaScript app and a Python app that communicate using a key derived from a password using pbdkf2. The problem is, the generated keys don't match. I've produced a minimal test case for each.
Python
import hashlib, binascii
bytes = hashlib.pbkdf2_hmac('sha256', "password".encode(), b'', 100000)
print(binascii.hexlify(bytes).decode())
Generates: 64a868d4b23af696d3734d0b814d04cdd1ac280128e97653a05f32b49c13a29a
JavaScript
<script src="lib/sjcl.js"></script>
<script>
var hmacSHA256 = function (key) {
var hasher = new sjcl.misc.hmac(key, sjcl.hash.sha256);
this.encrypt = function () {
return hasher.encrypt.apply(hasher, arguments);
};
};
hash = sjcl.misc.pbkdf2("password", [0], 100000, 256, hmacSHA256);
console.log(sjcl.codec.hex.fromBits(hash));
</script>
Generates: 41c04f824d843d5be0ae66b3f621d3f05db7d47e7c46ee0e9171b5cbff7f3631
I'm scratching my head a lot now. I think b'' and [0] are equivalent salts, but I'm not sure. I think they both use utf-8 to encode the password, but I'm not sure. And I'm not convinced the JavaScript hmacSHA256 function exactly matches what Python is doing. Or it could be something else still.
Off the top of my head, have you checked if
hash = sjcl.misc.pbkdf2("password", "", 100000, 256);
gives the correct result?
As far as I can tell from the docs, SJCL's PBKDF2 implementation defaults to HMAC-SHA256 if you don't explicitly give it a PRF. If making that change fixes the bug, then there's probably something wrong with your hmacSHA256 wrapper.
Also, I'm not sure if specifying an empty salt as [0] really works (or is guaranteed to work in future versions, given that the format of SJCL's bitArrays is explicitly subject to change), but "" definitely should work.
This is sharing for the rest based on my recent experience.
My objective:
To generate PBKDF2 password using Python. The client will be Android (Java), and the back end will be on Flask (Python).
Issue:
While testing, I discovered that both versions (Java vs Python) produced different hashing output (all other parameters were equal - SHA256, 1000 iterations, similar SALT)
What I have found out:
Using PBKDF2 generation tools available on the internet, the Android result was an exact match, while the Python was not. So there is a good chance the Python result was somehow skewed .....
Problem solved:
While looking for possible explanation in SO, I discovered that the way I converted String to bytes in Python was somehow not entirely correct:
Original code:
dk = hashlib.pbkdf2_hmac('sha256', b'base64_message', b'salt', 1000)
Working code:
dk = hashlib.pbkdf2_hmac('sha256', base64_message.encode(), salt.encode(), 1000)
This is probably due to my lack of experience in Python. Hope this note will be of use to others, especially those who are new to Python!

JSON Date without eval?

Short description:
Is there a javascript JSON-converter out there that is able to preserve Dates and does not use eval?
Example:
var obj1 = { someInt: 1, someDate: new Date(1388361600000) };
var obj2 = parseJSON(toJSON(obj1));
//obj2.someDate should now be of type Date and not String
//(like in ordinary json-parsers).
Long description:
I think most people working with JSON already had the problem of how to transmit a Date:
var obj = { someInt: 1, someDate: new Date(1388361600000) }
When converting this to JSON and back, the date suddenly became a String:
JSON.parse(JSON.stringify(obj))
== { someInt: 1, someDate: "2013-12-30T00:00:00.000Z" }
This is a huge disadvantage since you cannot easily submit a Date using JSON. There is always some post-processing necessary (and you need to know where to look for the dates).
Then Microsoft found a loophole in the specification of JSON and - by convention - encodes a date as follows:
{"someInt":1,"someDate":"\/Date(1388361600000)\/"}
The brilliance in this is that there is a now a definitive way to tell a String from a Date inside a valid JSON-string: An encoded String will never contain the substring #"/" (a backslash followed by a slash, not to be confused with an escaped slash). Thus a parser that knows this convention can now safely create the Date-object.
If a parser does not know this convention, the date will just be parsed to the harmless and readable String "/Date(1388361600000)/".
The huge drawback is that there seems to be no parser that can read this without using eval. Microsoft proposes the following way to read this:
var obj = eval("(" + s.replace(/\"\\\/Date\((\d+)\)\\\/\"/g, function (match, time) { return "new Date(" + time + ")"; }) + ")");
This works like a charm: You never have to care about Dates in JSON anymore. But it uses the very unsafe eval-method.
Do you know any ready-to-use-parser that achieves the same result without using eval?
EDIT
There was some confusion in the comments about the advantages of the tweaked encoding.
I set up a jsFiddle that should make the intentions clear: http://jsfiddle.net/AJheH/
I disagree with adeno's comment that JSON is a notation for strings and cannot represent objects. Json is a notation for compound data types which must be in the form of a serialized objects, albeit that the primitive types can only be integer, float, string or bool. (update: if you've ever had deal with spaghetti coded XML, then you'll appreciate that maybe this is a good thing too!)
Presumably hungarian notation has lost favour with Microsoft if they now think that creating a non-standard notation incorporating the data type to describe a type is better idea.
Of itself 'eval' is not evil - it makes solving some problems a lot easier - but it's very difficult to implement good security while using it. Indeed it's disabled by default with a Content Security Policy.
IMHO it boils down to storing the date as 1388361600000 or "2013-12-30T00:00:00.000Z". IMHO the latter has significantly more semantic value - taken out of context it is clearly a date+time while the latter could be just about anything. Both can be parsed by the ECMAscript Date object without resorting to using eval. Yes this does require code to process the data - but what can you do with an sort of data without parsing it? he only time I can see this as being an advanage is with a schemaless database - but in fairness this is a BIG problem.
The issue is the following line of code, here is an example function and take a look at parseWithDate function, add the script to the page and change the following line to this it will work.
http://www.asp.net/ajaxlibrary/jquery_webforms_serialize_dates_to_json.ashx
var parsed1 = JSON.parse(s1); // changed to below
var parsed1 = JSON.parseWithDate(s1);
Updated jsFiddle that works http://jsfiddle.net/GLb67/1/

Are there any one-way hashing functions available in native JavaScript?

I'd like to be able to create unique tokens* for users based on a hashed string. I know I could, for example, use a md5() library but as the purpose is not cryptographic I was wondering if there was anything I could use "out of the box." Are there any one-way hashing functions available in native JavaScript?
*I realize these won't be strictly unique. I'm ok with a small chance of hashing collision.
In 2020, there is a native API:
SubtleCrypto.digest()
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
example:
crypto.subtle
.digest("SHA-256", new TextEncoder().encode("hello"))
.then(console.log);
hex string conversion:
const digest = async ({ algorithm = "SHA-256", message }) =>
Array.prototype.map
.call(
new Uint8Array(
await crypto.subtle.digest(algorithm, new TextEncoder().encode(message))
),
(x) => ("0" + x.toString(16)).slice(-2)
)
.join("");
digest({message: "hello"}).then(console.log)
JavaScript does not have native hashing, but there are many libraries.
I recommend crypto-js: https://code.google.com/p/crypto-js/
For example, to use SHA1, you simply:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/sha1.js"></script>
<script>
var hash = CryptoJS.SHA1("Message");
</script>
Nothing is available in native JavaScript. You could use something like Murmurhash. There's a JavaScript implementation here: https://github.com/garycourt/murmurhash-js. I haven't used it though so can't vouch for it.
Update: now there are multiple Murmurhash3 implementations available in JavaScript. However, many of them have problems encoding strings to bytes and can produce different results compared to the reference C++ implementation. You can read an analysis on this here, the murmurhash3js-revisited library implements all three variants of the function and conforms to the reference.
Over the horizon, this may be possible with the currently experimental Web Crypto API
https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
Granted, at the time of this writing it is unrealistic to use in a production environment and will likely be a moving target. However, come 5 years who knows?

What JavaScript library should I use for parsing URL parameters?

How do I parse URL parameters in JavaScript? (These are the parameters I would ordinarily call GET parameters or CGI parameters, but in this case the page is basically submitting to itself, not a server, so there is no GET request and definitely no CGI program.)
I've seen a number of routines on the net that I can copy, but I have no idea how robust any of them are. I'm used to other languages like Perl and Java where I can rely on an extremely well-tested and robust library that I know will handle millions of little edge-cases in the standard. I would like the same here, rather than just cutting and pasting an example.
jQuery URL Utils or jQuery URL Parser.
Here's are two simple functions that do the job : http://adamv.com/dev/javascript/querystring
Here is a sample of the API Reference :
var qs = new Querystring();
// Parse a given querystring
var qs2 = new Querystring("name1=value1&name2=value2");
var v1 = qs2.get("name1");
var v3 = qs2.get("name3", "default value");
If it's "submitting to itself," do you need to do GET parameters?
But if you do, most browsers now have the decodeURIComponent function which will handle individual parameters; your job is to split them on & (String#split will do that nicely). If you want a library, jQuery and Prototype are both well-used and tested.
The best way I have found is to simply do it yourself and funnel the params into a global key/value object.
Getting quer params is simple...
just take a couple of .split()'s
var myquery = thewholeurl.split("?")[1]; //will get the whole querystring with the ?
then you can do a
myparams = myquery.split("&")
then you can do
for each param in myparams
{
temp = param.split("=");
mykeys.push(temp[0]);
myvalues.push(temp[1]);
OR
myObject[temp[0]] = temp[1];
}
It's just a matter of style.
This is not perfect code, just psuedo stuff to give you the idea.
I use the parseUri library available here:
http://stevenlevithan.com/demo/parseuri/js/
It allows you to do exactly what you are asking for:
var uri = 'http://google.com/?q=stackoverflow';
var q = uri.queryKey['q'];
// q = 'stackoverflow'
I've been using it for a while so far and haven't had any problems.
I found this useful for simple url parsing, modifying url (like adding new query params): https://github.com/derek-watson/jsUri
I think this library would work quite well, it is independent so you can use it with JQuery or with YAHOO or Dojo, another advantage is that it is pretty well documented.
http://www.openjsan.org/doc/t/th/theory/HTTP/Query/0.03/lib/HTTP/Query.html
You can use HTTP.Query to do all of the work for you in this case. It is only like 1.2 KB compressed so you could even include it in a bigger library if you wanted.
I recommend query-string library
Installing:
npm install query-string
Usage:
import queryString from 'query-string';
console.log(location.search);
//=> '?foo=bar'
const parsed = queryString.parse(location.search);
console.log(parsed);
//=> {foo: 'bar'}
parsed.foo = 'unicorn';
parsed.ilike = 'pizza';
const stringified = queryString.stringify(parsed);
//=> 'foo=unicorn&ilike=pizza'
location.search = stringified;
// note that `location.search` automatically prepends a question mark
console.log(location.search);
//=> '?foo=unicorn&ilike=pizza'
https://www.npmjs.com/package/query-string
Javascript has no built in support for URL parameters.
Anyway, the location.search property returns the portion of current page URL starting from the question mark ('?').
From this, you can write your own parameter parser or you can make use of one of those available in most common Javascript frameworks, such as JQuery and similar.

Categories