since a user needed it and the original stuff was not working, I implemented it from scratch.
Save it as hmac.pbi
Code: Select all
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
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$ = SHA1Fingerprint(*key, MemorySize(*key))
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$ = SHA1Fingerprint(*i, MemorySize(*i))
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$ = SHA1Fingerprint(*o, MemorySize(*o))
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$ = MD5Fingerprint(*key, MemorySize(*key))
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$ = MD5Fingerprint(*i, MemorySize(*i))
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$ = MD5Fingerprint(*o, MemorySize(*o))
FreeMemory(*o)
EndIf
EndIf
FreeMemory(*i_key_pad)
EndIf
FreeMemory(*o_key_pad)
EndIf
FreeMemory(*key)
EndIf
ProcedureReturn Result$
EndProcedure
;-Demo
CompilerIf #PB_Compiler_IsMainFile
Debug "Examples from: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code"
Debug ""
Debug "hmac_md5('', '')"
Debug "Calculated: " + hmac_md5("", "")
Debug "Should be : 74e6f7298a9c2d168935f58c001bad88"
Debug ""
Debug "hmac_sha1('', '')"
Debug "Calculated: " + hmac_sha1("", "")
Debug "Should be : fbdb1d1b18aa6c08324b7d64b71fb76370690e1d"
Debug ""
Debug "hmac_md5('key', 'The quick brown fox jumps over the lazy dog')"
Debug "Calculated: " + hmac_md5("key", "The quick brown fox jumps over the lazy dog")
Debug "Should be : 80070713463e7749b90c2dc24911e275"
Debug ""
Debug "hmac_sha1('key', 'The quick brown fox jumps over the lazy dog')"
Debug "Calculated: " + hmac_sha1("key", "The quick brown fox jumps over the lazy dog")
Debug "Should be : de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
Debug ""
Debug "user example:"
Define.i x, Size
Define accessID$, secretKey$, expires$, stringToSign$, signature$, encoded$
Define *in, *out
accessID$ = "mozscape-3030303030"
secretKey$ = "8adea7512f787f2c98097ec526a9dac1"
expires$ = "1429403104"
stringToSign$ = accessID$ + #LF$ + expires$
signature$ = hmac_sha1(secretKey$, stringToSign$)
Debug "HMAC_SHA1: " + signature$
*in = AllocateMemory(40)
*out = AllocateMemory(40 * 1.4)
For x = 0 To 19
PokeA(*in + x, Val("$" + Mid(signature$, x * 2 + 1, 2)))
Next x
Size = Base64Encoder(*in, 20, *out, MemorySize(*out))
encoded$ = PeekS(*out, Size, #PB_Ascii)
Debug "Base64 encoded: " + encoded$
encoded$ = ReplaceString(encoded$,"+","%2B")
encoded$ = ReplaceString(encoded$,"=","%3D")
encoded$ = ReplaceString(encoded$,"/","%2F")
Debug "URLEncoded: " + encoded$
CompilerEndIf
Also the AllocateMemory() for *i can be omitted if *i_key_pad is used for this too.
hmac_sha256 from Helle can be found here:
http://www.purebasic.fr/english/viewtop ... 7&p=358165
Bernd