TOTP(Time Based One Time Password)を作成するJavaScript関数があります。 これでPHPを使用して、同じTOTPをサーバーで作成する必要がありました。 JavaScriptで同じロジックをPHPでコーディングしました。 便宜上、私はJavaScriptのフィドルとPHPフィドルを作成しました。したがって、コードを比較して出力を見ることができます。HMAC Javascript関数がPHPと異なる結果を返しました
Javascriptのバージョン:(フィドル:https://jsfiddle.net/rrfk4ey9/1/)
var TOTP = function() {
var dec2hex = function(s) {
return (s < 15.5 ? "0" : "") + Math.round(s).toString(16);
};
var hex2dec = function(s) {
return parseInt(s, 16);
};
var leftpad = function(s, l, p) {
if(l + 1 >= s.length) {
s = Array(l + 1 - s.length).join(p) + s;
}
return s;
};
this.getOTP = function(secret) {
try {
var epoch = Math.round(new Date().getTime()/1000.0);
// For testing, we take a fixed time. (same as in PHP version).
var time = "0000000002f3e3c9";//leftpad(dec2hex(Math.floor(epoch/30)), 16, "0");
document.getElementById("key").innerHTML = secret;
document.getElementById("time").innerHTML = time;
var hmacObj = new jsSHA(time, "HEX");
var hmac = hmacObj.getHMAC(secret, "TEXT", "SHA-1", "HEX");
document.getElementById("hmac-out").innerHTML = hmac;
var offset = hex2dec(hmac.substring(hmac.length - 1));
var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec("7fffffff")) + "";
otp = (otp).substr(otp.length - 6, 6);
} catch (error) {
\t alert("Error: " + error);
throw error;
}
return otp;
};
};
var totpObj = new TOTP();
document.getElementById("result").innerHTML = totpObj.getOTP("someSecret");
output {
font-family: monospace;
white-space: pre;
}
#result {
color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/1.6.0/sha.js"></script>
<body>
<aside>This snippet uses external library <b>jsSHA</b> version <b>1.6.0</b></aside>
<hr />
<output>
<div>Key: <b id="key"></b></div>
<div>Time: <b id="time"></b></div>
<div>HMAC: <b id="hmac-out"></b></div>
<div>code: <b id="result"></b></div>
</output>
</body>
PHPバージョン:(http://ideone.com/s0Bwqu)
<?php
function leftPad($in, $len, $str) {
return str_pad($in, $len, $str, STR_PAD_LEFT);
}
$key = "someSecret";
$epoch = time();
// For testing, we take a fixed time. (same as in JS version).
$time = "0000000002f3e3c9";//leftPad(dechex(floor($epoch/30)), 16, "0");
echo "Key: " . $key . "\n";
echo "Time: " . $time . "\n";
$hmac = hash_hmac("sha1", $time, $key, false);
echo "HMAC: " . $hmac . "\n";
$offset = hexdec(substr($hmac, strlen($hmac) - 1));
$otp = (hexdec(substr($hmac, $offset * 2, 8)) & hexdec("7fffffff")) . "";
$otp = substr($otp, strlen($otp) - 6, 6);
echo "Code: " . $otp . "\n";
?>
この利回り:
Key: someSecret
Time: 0000000002f3e3c9
HMAC: 5dcab54740bdca71e706c7e38a5c59fec3cb9c1a
Code: 094428
両方のバージョン(JSおよびPHP)でtime
とkey
が同じであることに留意されたいです。 HMAC
が異なるので、ここで私の理解には問題が始まります。 javascriptのバージョンは、最初に作成したもので、正しく動作することが証明されています。
私はかなり問題がjsSHAライブラリの動作によって引き起こされたと確信しています。 は、だから私は視点でいくつかのものを置く:
- jsSHAライブラリは、HEX形式で
time
をとります。また、PHPでは、hash_hmac
関数の中に置かれたとき、時間はHEX形式になります。 secret
(key
)は、jsSHAに入れられたTEXT形式です。 PHPでも。
実際には、ポイントはPHPでjavascriptのjsSHAライブラリと同じ結果になっています。 私は何かが欠けていると確信しています。私はずっとずっと試してきたし、Googleでさえ答えを知らない。
第三者サービスではなく、ご質問に直接コードを投稿してください。 – Narf