0

HOTP ( Android Google認証用のカウンターベースの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 の認証で機能しない場合は、開始する場所を教えてください。

ありがとうございました

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 に答える