Voici un code qui fonctionne et que j'utilise.
GenerateOTP.pb (code que j'ai fait à l'aide d'info trouvé sur le net)
Code : Tout sélectionner
XIncludeFile "include\hmac2.pb"
XIncludeFile "include\inc.base32.pbi"
ImportC "":time(*tloc = #Null):EndImport ;unix timestamp crossplattform
Procedure.l Reverse(*ptr,length=8) ;pack Quad
Define *mem=AllocateMemory(length)
CopyMemory(*ptr+3,*mem+4,1)
CopyMemory(*ptr+2,*mem+5,1)
CopyMemory(*ptr+1,*mem+6,1)
CopyMemory(*ptr+0,*mem+7,1)
ProcedureReturn *mem
EndProcedure
Procedure.s GenerateOTP(secrect$,digits=6,interval=30,nextkey=0)
Protected OTP=0, modNumber=0, offset=0, FullOtp=0
Protected Dim HashByteArray.a (0)
Protected secretbase32Hex$=base32Encode(secrect$,"hex") ;create base32 Hex String
Protected SecretLen=Len(secretbase32Hex$)/2 ;size byte array
Protected Dim Secret.a (0)
ReDim Secret(SecretLen)
Hex2Dec(Secret(), secretbase32Hex$) ;create byte array from string
;ShowMemoryViewer(@Secret(),SecretLen)
Protected timestamp=((time()+(nextkey * interval))/interval)
;Debug time()
Protected *timestamp=Reverse(@timestamp)
Protected signature$ = hmac_sha1binMod(@Secret(),SecretLen, *timestamp,8)
;ShowMemoryViewer(*timestamp,8)
FreeMemory(*timestamp)
;Debug "signature$: " + signature$
Protected len=Len(signature$)/2
ReDim HashByteArray(len)
Hex2Dec(HashByteArray(), signature$)
offset= HashByteArray(ArraySize(HashByteArray())-1) & $F
FullOtp=(HashByteArray(offset) & $7f) * Pow(2, 24)
FullOtp = FullOtp + (HashByteArray(offset + 1) & $ff) * Pow(2, 16)
FullOtp = FullOtp + (HashByteArray(offset + 2) & $ff) * Pow(2, 8)
FullOtp = FullOtp + (HashByteArray(offset + 3) & $ff)
modNumber = Pow(10, digits)
OTP= FullOtp % modNumber
ProcedureReturn RSet(Str(OTP), digits,"0")
EndProcedure
; Clé privé fournie par l'application securisé
Define key.s = "JBSWY3DPEHPK3PXP"
key = ReplaceString(key, "-", "")
key = UCase(key)
CodeLen = 6
interval = 30
nb = 5
For i = 0 To nb
timestamp = (time()+(i * interval))
sec.s = Right(FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", timestamp ),2)
If Val(sec) >= 30
timestamp = timestamp - Val(sec) + 30
sec = "30"
Else
timestamp = timestamp - Val(sec)
sec = "00"
EndIf
time.s = Left(FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", timestamp ),17) + sec
;timestamp = (time()+(i * interval))
Debug GenerateOTP(key,CodeLen,interval,i) +" => " + time +" => " + timestamp
Next
;Debug GenerateOTP(key,6,30,1)
;Debug GenerateOTP(key,6,30,2)
hmac2.pb (qui n'est pas de moi, je remercie son créateur dont j'ignore le nom)
Code : Tout sélectionner
;EnableExplicit
; HMAC function implementation
; 2016 (c) Luna Sole
UseMD5Fingerprint() : UseSHA1Fingerprint() : UseSHA2Fingerprint() ; currently only verified with these algorithms
; convert hex string into raw bytes
; Out() unsigned char array to receive result
; Hex$ string with hex data
; RETURN: decimal value is placed to Out() array
Procedure Hex2Dec (Array Out.a (1), Hex$)
Protected i2, max = Len(Hex$)
ReDim Out((max + 1) / 2)
For i2 = 1 To max Step 2
Out(i2 / 2) = Val("$" + Mid(Hex$, i2, 2))
Next i2
EndProcedure
; generates HMAC signature for specified message and key
; NOTE: This function forces strings conversion to ASCII, both for key and message
; I'm not sure how right to do that, but let it be for now (I don't want to do a painful debug of unicode version also ^^)
; PB_Cipher what hashing to use (MD5, SHA1, SHA256 and some others)
; Message$ data to hash
; Key$ a very secret key
; RETURN: string, representing HMAC hash
Procedure$ StringHMAC (PB_Cipher, Message$, Key$)
#HMAC_BLOCKSIZE = 64 ; blocksize is 64 (bytes) when using one of the following hash functions: SHA-1, MD5, RIPEMD-128/160.
; First of all, convert key from string to binary
; If key is longer than block size, replace it with hash(key)
Protected Dim key_bdata.a (#HMAC_BLOCKSIZE)
If (StringByteLength(Key$, #PB_Ascii) > #HMAC_BLOCKSIZE)
PokeS(@key_bdata(0), StringFingerprint(Key$, PB_Cipher), -1, #PB_Ascii | #PB_String_NoZero)
Else
PokeS(@key_bdata(0), Key$, -1, #PB_Ascii | #PB_String_NoZero)
EndIf
; Now introduce o_key_pad/i_key_pad and XOR them with some magic numbers
Protected Dim i_key_pad.a (0)
Protected Dim o_key_pad.a (0)
Protected Tmp
CopyArray(key_bdata(), i_key_pad())
CopyArray(key_bdata(), o_key_pad())
For Tmp = 0 To #HMAC_BLOCKSIZE
i_key_pad(Tmp) ! $36
o_key_pad(Tmp) ! $5c
Next Tmp
; At last, start hashing
Protected Hash_i$, Hash_o$ ; there are two steps, those variables storing result for step 1 and 2
Protected hHash ; handle to initiated hash routine
Protected Dim TempRaw.a (0) ; a temporary buffer for data transfer
; First, hash using i_key_pad() and data
ReDim TempRaw(StringByteLength(Message$, #PB_Ascii))
PokeS(@TempRaw(0), Message$, -1, #PB_Ascii | #PB_String_NoZero)
hHash = StartFingerprint (#PB_Any, PB_Cipher)
AddFingerprintBuffer (hHash, @i_key_pad(0), #HMAC_BLOCKSIZE)
If ArraySize(TempRaw())
AddFingerprintBuffer (hHash, @TempRaw(0), ArraySize(TempRaw()))
EndIf
Hash_i$ = FinishFingerprint(hHash)
; Finally, hash once more using o_key_pad() + result of previous hashing
Hex2Dec(TempRaw(), Hash_i$)
hHash = StartFingerprint (#PB_Any, PB_Cipher)
AddFingerprintBuffer (hHash, @o_key_pad(0), #HMAC_BLOCKSIZE)
AddFingerprintBuffer (hHash, @TempRaw(0), ArraySize(TempRaw()))
Hash_o$ = FinishFingerprint(hHash)
ProcedureReturn Hash_o$
EndProcedure
;Mod to handle binary data
Procedure.s hmac_sha1binMod(*SecretByteArray, SecretLen,*msg,msglen, blocksize.i=64, opad.a=$5C, ipad.a=$36)
Protected.i KeyLength, x
Protected Result$, i_key$
Protected *key, *o_key_pad, *i_key_pad, *i, *o
KeyLength = SecretLen
;Debug "KeyLength: " + KeyLength
If KeyLength > blocksize
*key = AllocateMemory(KeyLength)
ElseIf KeyLength < blocksize
*key = AllocateMemory(blocksize)
EndIf
If *key
CopyMemory(*SecretByteArray,*key,KeyLength)
;ShowMemoryViewer(*key,blocksize)
*o_key_pad = AllocateMemory(blocksize, #PB_Memory_NoClear)
If *o_key_pad
For x = 0 To blocksize - 1
PokeA(*o_key_pad + x, PeekA(*key + x) ! opad)
Next x
*i_key_pad = AllocateMemory(blocksize, #PB_Memory_NoClear)
If *i_key_pad
For x = 0 To blocksize - 1
PokeA(*i_key_pad + x, PeekA(*key + x) ! ipad)
Next x
*i = AllocateMemory(blocksize + msglen)
If *i
CopyMemory(*i_key_pad, *i, blocksize)
;this work with bytes
CopyMemory(*msg,*i + blocksize, msglen)
;ShowMemoryViewer(*msg,msglen)
i_key$ = Fingerprint(*i, MemorySize(*i),#PB_Cipher_SHA1)
FreeMemory(*i)
*o = AllocateMemory(blocksize + 20)
If *o
CopyMemory(*o_key_pad, *o, blocksize)
For x = 0 To 19
PokeA(*o + blocksize + x, Val("$" + Mid(i_key$, x * 2 + 1, 2)))
Next x
Result$ = Fingerprint(*o, MemorySize(*o),#PB_Cipher_SHA1)
FreeMemory(*o)
EndIf
EndIf
FreeMemory(*i_key_pad)
EndIf
FreeMemory(*o_key_pad)
EndIf
FreeMemory(*key)
EndIf
ProcedureReturn Result$
EndProcedure
Procedure.s hmac_sha1(key$, msg$, blocksize.i=64, opad.a=$5C, ipad.a=$36)
Protected.i KeyLength, x
Protected Result$, i_key$
Protected *key, *o_key_pad, *i_key_pad, *i, *o
KeyLength = StringByteLength(key$, #PB_UTF8)
If KeyLength > blocksize
*key = AllocateMemory(KeyLength)
If *key
PokeS(*key, key$, -1, #PB_UTF8|#PB_String_NoZero)
key$ = Fingerprint(*key, MemorySize(*key),#PB_Cipher_SHA1)
FreeMemory(*key)
KeyLength = StringByteLength(key$, #PB_UTF8)
*key = AllocateMemory(KeyLength)
EndIf
ElseIf KeyLength < blocksize
*key = AllocateMemory(blocksize)
EndIf
If *key
PokeS(*key, key$, -1, #PB_UTF8|#PB_String_NoZero)
*o_key_pad = AllocateMemory(blocksize, #PB_Memory_NoClear)
If *o_key_pad
For x = 0 To blocksize - 1
PokeA(*o_key_pad + x, PeekA(*key + x) ! opad)
Next x
*i_key_pad = AllocateMemory(blocksize, #PB_Memory_NoClear)
If *i_key_pad
For x = 0 To blocksize - 1
PokeA(*i_key_pad + x, PeekA(*key + x) ! ipad)
Next x
*i = AllocateMemory(blocksize + StringByteLength(msg$, #PB_UTF8))
If *i
CopyMemory(*i_key_pad, *i, blocksize)
PokeS(*i + blocksize, msg$, -1, #PB_UTF8|#PB_String_NoZero)
i_key$ = Fingerprint(*i, MemorySize(*i),#PB_Cipher_SHA1)
FreeMemory(*i)
*o = AllocateMemory(blocksize + 20)
If *o
CopyMemory(*o_key_pad, *o, blocksize)
For x = 0 To 19
PokeA(*o + blocksize + x, Val("$" + Mid(i_key$, x * 2 + 1, 2)))
Next x
Result$ = Fingerprint(*o, MemorySize(*o),#PB_Cipher_SHA1)
FreeMemory(*o)
EndIf
EndIf
FreeMemory(*i_key_pad)
EndIf
FreeMemory(*o_key_pad)
EndIf
FreeMemory(*key)
EndIf
ProcedureReturn Result$
EndProcedure
Procedure.s hmac_md5(key$, msg$, blocksize.i=64, opad.a=$5C, ipad.a=$36)
Protected.i KeyLength, x
Protected Result$, i_key$
Protected *key, *o_key_pad, *i_key_pad, *i, *o
KeyLength = StringByteLength(key$, #PB_UTF8)
If KeyLength > blocksize
*key = AllocateMemory(KeyLength)
If *key
PokeS(*key, key$, -1, #PB_UTF8|#PB_String_NoZero)
key$ = Fingerprint(*key, MemorySize(*key),#PB_Cipher_MD5)
FreeMemory(*key)
KeyLength = StringByteLength(key$, #PB_UTF8)
*key = AllocateMemory(KeyLength)
EndIf
ElseIf KeyLength < blocksize
*key = AllocateMemory(blocksize)
EndIf
If *key
PokeS(*key, key$, -1, #PB_UTF8|#PB_String_NoZero)
*o_key_pad = AllocateMemory(blocksize, #PB_Memory_NoClear)
If *o_key_pad
For x = 0 To blocksize - 1
PokeA(*o_key_pad + x, PeekA(*key + x) ! opad)
Next x
*i_key_pad = AllocateMemory(blocksize, #PB_Memory_NoClear)
If *i_key_pad
For x = 0 To blocksize - 1
PokeA(*i_key_pad + x, PeekA(*key + x) ! ipad)
Next x
*i = AllocateMemory(blocksize + StringByteLength(msg$, #PB_UTF8))
If *i
CopyMemory(*i_key_pad, *i, blocksize)
PokeS(*i + blocksize, msg$, -1, #PB_UTF8|#PB_String_NoZero)
i_key$ = Fingerprint(*i, MemorySize(*i),#PB_Cipher_MD5)
FreeMemory(*i)
*o = AllocateMemory(blocksize + 16)
If *o
CopyMemory(*o_key_pad, *o, blocksize)
For x = 0 To 15
PokeA(*o + blocksize + x, Val("$" + Mid(i_key$, x * 2 + 1, 2)))
Next x
Result$ = Fingerprint(*o, MemorySize(*o),#PB_Cipher_MD5)
FreeMemory(*o)
EndIf
EndIf
FreeMemory(*i_key_pad)
EndIf
FreeMemory(*o_key_pad)
EndIf
FreeMemory(*key)
EndIf
ProcedureReturn Result$
EndProcedure
inc base32.pbi (idem pour celui-ci)
Code : Tout sélectionner
Procedure.s base32decode(in1.s)
keyStr$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="
For i = 1 To Len(in1)
vvll=FindString(keyStr$,Mid(in1,i,1))-1
If vvll >= 0 And vvll < 32
buffer << 5;
buffer | vvll;
bitsLeft + 5;
If bitsLeft >= 8
dStr$ + Chr((buffer >> (bitsLeft - 8)) & 255); + $FF;
bitsLeft - 8
EndIf
EndIf
Next
ProcedureReturn dStr$
EndProcedure
Procedure.s base32Encode(base32$,outputFormat$="bin") ;encode base32 string; outputFormat$ bin/hex
Protected key$="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", output$=""
Protected i=0, buffer=0, bitsLeft=0
While i < Len(base32$)
val=FindString(key$,Mid(base32$,i+1,1))-1
If val>=0 And val<32
buffer= (buffer << 5 ) | val
bitsLeft=bitsLeft+5
If bitsLeft>=8
If outputFormat$="hex"
output$=output$ + RSet(Hex((buffer >> (bitsLeft - 8)) & $FF),2,"0") ;0x1F;
Else
output$=output$ + Chr((buffer >> (bitsLeft - 8)) & $FF)
EndIf
bitsLeft=bitsLeft-8
EndIf
EndIf
i=i+1
Wend
If bitsLeft>2;0
buffer=buffer<<5
If outputFormat$="hex"
output$=output$ + RSet(Hex((buffer >> (bitsLeft - 3)) & $FF),2,"0")
Else
output$=output$ + Chr((buffer >> (bitsLeft - 3)) & $FF)
EndIf
EndIf
ProcedureReturn output$
EndProcedure
Procedure.s Hex2Bin(hex.s)
For i = 1 To Len(hex) /2 Step 2
bin$ = bin$ + Val("$"+ Mid(Hex,i,2))
Next
ProcedureReturn bin$
EndProcedure
Pour info, il me semble avoir modifié du code dans l'un des 2 includes.
En effet de façon aléatoire, j'avais aussi un problème, mais je ne saurais dire lequel !
J'espère que mon post résistera au modérateur, dans le passé j'ai posté sur ce forum, mais mets post ont été supprimés !