PHP一次性密码?

时间:2013-09-30 11:47:46

标签: php android authentication hash one-time-password

我一直在努力学习如何HOTPAndroid Google Authenication的基于计数器的HOTP代码)。 我找到了这个代码,它能够在服务器和客户端(Mobile APP)之间共享密钥。

<?php
function oath_hotp($key,$counter) {

   // Convert to padded binary string
   $data = pack ('C*', $counter);
   $data = str_pad($data,8,chr(0),STR_PAD_LEFT);

   // HMAC
   return hash_hmac('sha1',$data,$key);
}

function oath_truncate($hash, $length = 6) {

   // Convert to dec
   foreach(str_split($hash,2) as $hex) {
      $hmac_result[]=hexdec($hex);
   }

   // Find offset
   $offset = $hmac_result[19] & 0xf;

   // Algorithm from RFC
   return (
         (($hmac_result[$offset+0] & 0x7f) << 24 ) |
         (($hmac_result[$offset+1] & 0xff) << 16 ) |
         (($hmac_result[$offset+2] & 0xff) << 8 ) |
         ($hmac_result[$offset+3] & 0xff)
         ) % pow(10,$length);
}

print "<pre>";
print "Compare results with:";
print " http://tools.ietf.org/html/draft-mraihi-oath-hmac-otp-04\n";
print "Count\tHash\t\t\t\t\t\tPin\n";
for($i=0;$i<10;$i++){
   print $i."\t".($a=oath_hotp("mysecretvalue",$i));
   print "\t".oath_truncate($a)."\n";
}
?>

此输出以下内容 -

Compare results with: http://tools.ietf.org/html/draft-mraihi-oath-hmac-otp-04
Count                   Hash                      Pin
0   f25e6c58cc7a2dfedae7eb48a1bff891aa0c0189    472801
1   b52adf13022511f08740566fb44c0b267d7c2604    983856
2   3c693c66f6e04178943dc9badc0dd41318dbc7f7    981065
3   1225cf508043a59fe2e39e335ff5f3e5795131ba    683381
4   21a9756e8de58df5e10c9292e0147823ba03539b    675192
5   7339c3496cebdaf3a035eaba888f61d8c19d8cf9    575624
6   c7c03ce2174f144a329664d35cc90e70a3686596    406934
7   431a75f26b9950f0206911667f3a2ed7fdfc43c7    172241
8   81e05a2d9e060a25f515b1e53170dce4daad5cc7    818865
9   ff2068918dc53db45a0c338d8de99419cf3cb571    723917

现在我的问题是我无法管理上面的代码在客户端和服务器端都能正常工作。我使用了相同的密钥print $i."\t".($a=oath_hotp("**mysecretvalue**",$i));输出完全不同。请注意,这是基于计数器的,这意味着没有像TOTP那样的时间同步。

我在Android手机和服务器端检查了我的密码。可能有什么不对?请注意我对PHP安全性并不熟悉。因此,如果上述内容无法与Google的身份验证配合使用,请为我提供一个开始的地方。

谢谢

1 个答案:

答案 0 :(得分:1)

Google身份验证器将输入密钥视为RFC 3548 base32(https://code.google.com/p/google-authenticator/),并且您使用的是ASCII密码。

您拥有的PHP代码很好(您可以通过传递“12345678901234567890”的ASCII密码并根据http://www.ietf.org/rfc/rfc4226.txt的附录D进行检查)。

您需要做的是将您输入Google身份验证器的密码从base32转换为ASCII。

您可以使用github https://github.com/devicenull/PHP-Google-Authenticator/blob/master/base32.php中的此实用程序类base32为您进行转换,然后只需添加:

include_once "base32.php";
$keyToTest = "mysecretvalue";

$b = new Base32(Base32::csRFC3548);
$keyToTest = $b->toString($keyToTest);

for($i=0;$i<10;$i++){
   print $i."\t".($a=oath_hotp($keyToTest,$i));
   print "\t".oath_truncate($a)."\n";
}