yubikey icon indicating copy to clipboard operation
yubikey copied to clipboard

Add a function to get the public key

Open exaunique opened this issue 10 years ago • 6 comments

Currently missing inside of this implementation of the Yubikey, is a function that parses out the public key. Commonly used within "two factor authentication".

The first 12 characters of the string according to the Yubico documentation and also known as "prefix" within the data array of Yubico's own php implementation.

With that, dont forget the password. So parsing out the first 12 characters, wont work in every situation.

exaunique avatar Jul 16 '15 14:07 exaunique

Isn't the prefix always the same length? I'm not sure what you mean by "password" in this case.

enygma avatar Jul 16 '15 18:07 enygma

Perfectly understandable, the technical documentation available at Yubico is really sloppy. But the strings are defined as followed within the documentation @ https://www.yubico.com/wp-content/uploads/2012/10/YubiKey-Authentication-Module-Design-Guideline-v1.0.pdf:

3.1 YubiKey One - Factor and Two Factor Authentication

The YubiKey emits a 44 character One Time Password (OTP) of which the first 12 characters is a unique public identifier of the YubiKey itself and the characters that follows is the dynamic part of the OTP. A sample output from a YubiKey where the button has been pressed three times may look like this:

Public ID - OTP fifjgjgkhchbirdrfdnlnghhfgrtnnlgedjlftrbdeut fifjgjgkhchbgefdkbbditfjrlniggevfhenublfnrev fifjgjgkhchblechfkfhiiuunbtnvgihdfiktncvlhck

This fact that the YubiKey emits both a static identifier part and a dynamic ever changing part of the OTP makes it possible to develop combinations of two factor authentication and one factor authentication system.

There is also "Advanced Encryption Standard" option available which is described within 3.3> Then within the git repo of Yubico @ https://github.com/Yubico/yubico-php-client/blob/master/YubiCloud.php, the following parsing script is used:

function parsePasswordOTP($str, $delim = '[:]')
  {
    if (!preg_match("/^((.*)" . $delim . ")?" .
            "(([cbdefghijklnrtuv]{0,16})" .
            "([cbdefghijklnrtuv]{32}))$/i",
            $str, $matches)) {
      /* Dvorak? */
      if (!preg_match("/^((.*)" . $delim . ")?" .
              "(([jxe\.uidchtnbpygk]{0,16})" .
              "([jxe\.uidchtnbpygk]{32}))$/i",
              $str, $matches)) {
    return false;
      } else {
    $ret['otp'] = strtr($matches[3], "jxe.uidchtnbpygk", "cbdefghijklnrtuv");
      }
    } else {
      $ret['otp'] = $matches[3];
    }
    $ret['password'] = $matches[2];
    $ret['prefix'] = $matches[4];
    $ret['ciphertext'] = $matches[5];
    return $ret;
  }

Seeing the coding style it doesnt hint on perfection.... But it should give you the full scope.

exaunique avatar Jul 16 '15 20:07 exaunique

Without knowing any identifier of the used key the usage of OTP does not make any sense. Anybody with any valid yubico key could auhtorize to a system that should be secured by a second authentication factor.

Not comparing the used OTP public ID with the account data stored by your application opens the door for any account to anybody using any OTP public ID. The result is not having a proper second factor.

There has to be the possibility to not only get an info about the success of the validation operation but the used OTP or better the used public ID. As long as this issue is not solved using the API provided by this repo is dangerous! Especially for devs not really knowing what goes under the hood.

Bonscho avatar Apr 11 '16 12:04 Bonscho

I created a pull request that adds a simple parsing function to extract the ID

https://github.com/enygma/yubikey/pull/22

DKhalil avatar Dec 12 '16 12:12 DKhalil

Actually, it doesn't need to be part of the library, the library consumer can (easily) do this by extracting the 'identifier' part of the OTP provided by the YubiKey, it is a helpful little feature to have though :)

ghost avatar Dec 30 '16 14:12 ghost

Perfectly true. I suspect that the API in the actual state combined with the imperfect documentation misleads devs to not use it properly. On the other hand an API should provide methods and functionality that mirrors the common use cases. Getting the public ID from the result is definitively a common case if using the mechanism properly.

Bonscho avatar Jan 02 '17 09:01 Bonscho