index.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <?php
  2. session_start(); // using it as storage temporary
  3. require_once __DIR__ . '/../vendor/autoload.php';
  4. use Otp\Otp;
  5. use Otp\GoogleAuthenticator;
  6. use ParagonIE\ConstantTime\Encoding;
  7. // Getting a secret, either by generating or from storage
  8. // DON'T use sessions as storage for this in production!!!
  9. $secret = 0;
  10. if (isset($_SESSION['otpsecret'])) {
  11. $secret = $_SESSION['otpsecret'];
  12. }
  13. if (strlen($secret) != 16) {
  14. $secret = GoogleAuthenticator::generateRandom();
  15. $_SESSION['otpsecret'] = $secret;
  16. }
  17. // The secret is now an easy stored Base32 string.
  18. // To use it in totp though we need to decode it into the original
  19. $otp = new Otp();
  20. $currentTotp = $otp->totp(Encoding::base32DecodeUpper($secret));
  21. $qrCode = GoogleAuthenticator::getQrCodeUrl('totp', 'otpsample@cr', $secret);
  22. $keyUri = GoogleAuthenticator::getKeyUri('totp', 'otpsample@cr', $secret);
  23. ?><html>
  24. <head>
  25. <title>One Time Passwords Example</title>
  26. </head>
  27. <body>
  28. <h1>One Time Passwords Example</h1>
  29. Secret is <?php echo $secret; ?>. This is saved with the users credentials.
  30. <br />
  31. <br />
  32. <hr />
  33. QR Code for totp:<br />
  34. <img src="<?php echo $qrCode; ?>" />
  35. <br />
  36. This QR Code contains the Key URI: <?php echo $keyUri; ?>
  37. <br />
  38. <hr />
  39. Current totp would be <?php echo $currentTotp; ?><br />
  40. <br />
  41. <hr />
  42. Because of timedrift, you could technically enter a code before or after it
  43. would actually be used. This form uses the checkTotp function. To test this,
  44. open this page, wait until the key changes once or twice (not more) on your
  45. Google Authenticator, then hit submit. Even though the key is "wrong" because of
  46. small time differences, you can still use it.
  47. <form action="" method="post">
  48. <input type="text" name="otpkey" value="<?php echo $currentTotp; ?>" /><br />
  49. <input type="submit">
  50. </form>
  51. <br />
  52. Output:<br />
  53. <br />
  54. <?php
  55. if (isset($_POST['otpkey'])) {
  56. // Sanitizing, this should take care of it
  57. $key = preg_replace('/[^0-9]/', '', $_POST['otpkey']);
  58. // Standard is 6 for keys, but can be changed with setDigits on $otp
  59. if (strlen($key) == 6) {
  60. // Remember that the secret is a base32 string that needs decoding
  61. // to use it here!
  62. if ($otp->checkTotp(Encoding::base32DecodeUpper($secret), $key)) {
  63. echo 'Key correct!';
  64. // Add here something that makes note of this key and will not allow
  65. // the use of it, for this user for the next 2 minutes. This way you
  66. // prevent a replay attack. Otherwise your OTP is missing one of the
  67. // key features it can bring in security to your application!
  68. } else {
  69. echo 'Wrong key!';
  70. }
  71. } else {
  72. echo 'Key not the correct size';
  73. }
  74. }
  75. ?>
  76. </body>
  77. </html>