JavaScript 在 sha512 中加密并获得原始二进制数据的结果,如 PHP hash()

标签 javascript symfony hash

正如我在标题中所说,我需要重现这个 PHP 函数(在 JavaScript 中):

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

棘手的部分是如果最后的 true 意味着:

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

如果我需要自己创建一些东西并且我应该处理字节序,这也很重要:

The tiger algorithm now uses big-endian byte ordering.

引用:php.net - hash()

编辑:经过一些测试和研究,这里是我需要在 JavaScript 中重现的函数:

hex2bin("string");

实际上,CryptoJS 我能够获得十六进制的结果。我不知道如何在行二进制数据(hex2bin 等效)中获取它。

我发现使用 NodeJS 和 crypto 库我们可以轻松做到这一点,但我不使用 NodeJS。我需要在经典 JavaScript(或 jQuery 或任何其他可以工作的库)中获得相同的结果。

我的目标是向 Symfony 的 WSSE 协议(protocol)发送一个与数据库中的密码 (passwordDigest) 相匹配的密码。

这是我需要重现的 PHP 代码:

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

这是我实际拥有的 JavaScript 代码:

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

此代码的问题在于摘要变量始终包含十六进制数据,而不是原始二进制数据。

每个人都有一个想法、代码或库吗?

最佳答案

我找到了一个解决方案,基于 EmberJS 的 WSSE 实现:https://github.com/Gerfaut/ember-simple-wsse-auth

正是在 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;
};

你的encodePassword函数变成了

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

关于JavaScript 在 sha512 中加密并获得原始二进制数据的结果,如 PHP hash(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26616217/

相关文章:

没有返回 true 的 javascript 代码

doctrine - Symfony 2.7/3 - Doctrine : You have requested a non-existent service "fos_user.doctrine_registry"

php - 在隔离包中注册 Symfony Hydrators

python - 足够安全的 8 字符短唯一随机字符串

Vim、表格和 Ruby 1.9 哈希

ruby - 如何获得 JavaScript 样式的哈希访问?

javascript - 我可以根据特定的 Select 值自动设置 js-GRID 文本字段吗?

javascript - 如何根据在另一个文本框中输入的值更新一个文本框中的值?

javascript - 在不使用 `map` 两次的情况下将对象的属性收集到两个数组中的更简洁的方法?

symfony - 为 Twig 模板定义自定义文件系统路径