正如我在标题中所说,我需要重现这个 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.
编辑:经过一些测试和研究,这里是我需要在 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
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/