It has been some years since this was posted. I had made my own just now and I thought I would share it here than make a whole new thread:
#include <Crypt.au3>
Global $otp, $APIid = 00000000, $error, $CustSalt = '7F34E3F39F7967B38A9CEB3C3EE55F17BF9552F8F7A5B74', $AuthorisedHashedPubID = '0x6F25B171D3563C000F75455EAFFA1AA967EAB605'
; Get your API ID ($APIid) by registering for an API key: https://upgrade.yubico.com/getapikey/
; Use your own custom salt value above so that all the hashes will be entirely unique to your implementation.
$otp = InputBox('Yubikey OTP Request', 'Press the OTP Button on your Yubikey', Default, '*') ; Obtain the OTP from the user, by them pressing the button on their Yubikey that is inserted.
$nousedonce = StringTrimLeft(HashThis(StringReplace(Random(), '.', '') & @MSEC & StringReplace(Random(), '.', '') & StringReplace(Random(), '.', '') & @SEC & @MSEC), 2) ; This is the "number, used once" which actually is random data, not a number.
;;;;; Prep area, uncomment to generate a working hash to check the person's Yubikey "Public Identity" prefix to generate a salted hash you can check in the future to authenticate their Yubikey
;~ ClipPut(HashThis('ccccccjlgpht')) ; Paste the first 12 characters of a genuine Yubikey OTR that you wish to authorise to access this program and copy the resulting salted hash
;~ Exit
;;;;;
$url = 'https://api.yubico.com/wsapi/2.0/verify?otp=' & $otp & '&id=' & $APIid & '&nonce=' & $nousedonce & '×tamp=1' ; Constructing the URL needed to check with the remote server about a Yubikey's OTP output.
$results = InetRead($url, 1) ; Sending the request to the API server.
If Not @error Then
$results = BinaryToString($results)
$split = StringSplit($results, @CRLF, 3) ; Breaking the resulting feedback from the API server up into lines (array rows) so parameters can be ensured they start from the beginning of each line.
If StringInStr($results, 'otp=' & $otp) And StringInStr($results, 'nonce=' & $nousedonce) And StringInStr($results, 'status=OK') Then ; If OTP and nonce that were sent to server are the same ones returned & status is OK, continue validation.
For $a In $split
If StringInStr($a, 'otp=', 1) Then ; If this row of the array contains the otp parameter (it starts at the beginning of the string) then...
$a = StringReplace($a, 'otp=', '') ; Strip away the parameter prefix of "otp="
If HashThis(StringMid($a, 1, 12)) = $AuthorisedHashedPubID Then ; If the newly salted & hashed Yubikey's Public ID matches the existing salted hash of the authorised user, then do the immediately following thing...
MsgBox(0, 'SUCCESS', 'Successfully authenticated the authorised user''s Yubikey')
Else ; If we got here, the OTP that was generated was valid but the particular Yubikey was not one authorised for use with this program, so instead, do the following thing.
MsgBox(0, 'Error', 'While the Yubico OTP was validated as genuine,' & @CRLF & 'this Yubikey is not authorised for access.')
EndIf
EndIf
Next
ElseIf Not StringInStr($results, 'status=OK') Then ; If the status is anything other than "OK" there is a problem with the OTP that was generated, perhaps it was an old used one? etc.
For $a In $split
If StringInStr($a, 'status=', 1) Then $error = StringReplace($a, 'status=', '') ; set the error code supplied by the API server in the $error variable.
Next
MsgBox(0, 'Error', 'Yubico authentication error: ' & $error) ; Display the error to the user.
EndIf
Else
MsgBox(0, 'Error', 'Error accessing Yubico API address.') ; There was a problem accessing the API server, perhaps an internet problem or SSL problem.
EndIf
Func HashThis($_input) ; Simply does the salted hashing and provides the result
$_hash = StringTrimLeft(_Crypt_HashData($CustSalt & $_input, $CALG_SHA1), 0)
Return $_hash
EndFunc ;==>HashThis
My goal was to not have the required public ID stored in the source of the program, yet be able to check when it is the correct one.