0

I've been struggling around about learning how HOTP (counter-based HOTP codes for Android Google Authenication ). I've found this code, which has the ability to share a secret key between the server and client ( 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";
}
?>

This Output the following -

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

Now my problem is that I can not manage for above code to work properly on both Client and Server side. I've used the same Secret key print $i."\t".($a=oath_hotp("**mysecretvalue**",$i)); The output is completely different. Please note this is counter based which means there is no time sync like TOTP.

I've doubled check my secret code on my android phone and server side. What could be wrong? Please note I'm not really familiar with PHP security. So if the above does not work with Google's Authentication please provide me with a place to start with.

Thank You

4

1 回答 1

1

Google Authenticator 将输入密码作为 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";
}
于 2013-11-12T12:35:17.547 回答