2

As I said in the title I need to reproduce this PHP function (in JavaScript):

hash("sha512", "string", true);

The tricky part if for the true at the end which means:

When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.

This can be important too if I need to create something by myself and if I should take care of the endian:

The tiger algorithm now uses big-endian byte ordering.

Reference: php.net - hash()

EDIT: After some tests and research here is the function I need to reproduce in JavaScript:

hex2bin("string");

Actually witch CryptoJS I'm able to obtain the result in hexa. I don't know exactly how to obtain it in row binary data (hex2bin equivalent).

I found that with NodeJS and the library crypto we can do that easily but I don't use NodeJS. I need to obtain the same result in classic JavaScript (or jQuery or any other lib which will work).

My goal is to send to a Symfony's WSSE protocol a password that will match the one in database (passwordDigest).

Here is the PHP code I need to reproduce:

public function encodePassword($raw, $salt)
    {

        // ... Some check code for data

        $salted = $this->mergePasswordAndSalt($raw, $salt); // Just do $raw."{".$salt."}";
        $digest = hash($this->algorithm, $salted, true);

        // "stretch" hash
        for ($i = 1; $i < $this->iterations; $i++) {
            $digest = hash($this->algorithm, $digest.$salted, true);
        }

        return $this->encodeHashAsBase64 ? base64_encode($digest) :
bin2hex($digest);
    }

And here is the code in JavaScript I actually have:

WSSE.encodePassword = function(password, salt) {
    try {
        var salted = WSSE.mergePasswordAndSalt(password, salt);
        var digest = CryptoJS.SHA512(salted).toString();

        for (i = 1; i < 5000; i++) {
            digest = CryptoJS.SHA512(digest + salted).toString();
        }

        return WSSE.base64_encode(digest);
    } catch(err) {
        Log.e("WSSE", err.message);
        return null;
    }
};

The problem with this code is that the digest variable always contains data in hexa, not in raw binary data.

An idea, code, or lib everyone?

7
  • 1
    It's better to keep the hex and convert it to binary on your server, since binary data is pretty complicated to deal with in javascript, especially if you're sending requests to a server with it. Take a look at this question about binary data: stackoverflow.com/questions/2803145/… Commented Oct 28, 2014 at 18:53
  • I would like to do it but as there is a loop of 5000 iteration in which the binary raw output is concatenate with the salted I don't think it will work. Commented Oct 28, 2014 at 18:57
  • So you need digest to be binary? Javascript treats all number-systems as base10 numbers, for example: console.log(0xff) -> 255, check the question I linked Commented Oct 28, 2014 at 18:59
  • Yes I need it to be raw binary. I think there is a difference between binary and raw binary. When I print the result in PHP I obtain funny ASCII characters, I want to have the same and not stuffs like 00100100 00110101 ... But your first idea could work. I try to see if I can obtain binary raw output from the result of the first sha512() Commented Oct 28, 2014 at 19:07
  • 1
    Yeah I saw that thank to your link ! I always try to figure out how to reproduce hex2bin(); PHP function but if I can't it's not a big deal, I can do that in the PHP part. Commented Oct 28, 2014 at 19:36

2 Answers 2

4

I found a solution for it, based on a WSSE Implementation for EmberJS : https://github.com/Gerfaut/ember-simple-wsse-auth

Precisly in https://github.com/Gerfaut/ember-simple-wsse-auth/blob/master/packages/ember-simple-wsse-auth/lib/core.js

Ember.SimpleWsseAuth.EncodePassword = function(password, salt) {
    var salted = password + '{' + salt + '}';
    var passwordEncoded = CryptoJS.SHA512(salted);
    for(var i = 1; i < this.passwordEncodingIterations; i++) { //TODO use webworker
        passwordEncoded = CryptoJS.SHA512(passwordEncoded.concat(CryptoJS.enc.Utf8.parse(salted)));
    }
    return this.passwordEncodingAsBase64 ? passwordEncoded.toString(CryptoJS.enc.Base64) : passwordEncoded;
};

Your encodePassword function become

WSSE.encodePassword = function(password, salt) {
    try {
        var salted = WSSE.mergePasswordAndSalt(password, salt);
        var digest = CryptoJS.SHA512(salted);

        for (i = 1; i < 5000; i++) {
            digest = CryptoJS.SHA512(digest.concat(CryptoJS.enc.Utf8.parse(salted)));
        }    

        return WSSE.base64_encode(digest);
    } catch(err) {
        Log.e("WSSE", err.message);
        return null;
    }
};
Sign up to request clarification or add additional context in comments.

Comments

0

using http://movable-type.co.uk/scripts/sha512.html you obtain the same output as using the function

hash('sha512', 'puma');

That is an excellent solution from Chris Veness

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.