Page 1 of 2
hmac_sha1
Posted: Wed May 25, 2011 6:29 am
by hss
PB implantation of HMAC_SHA1;
useful for authentication signing - e.g. Twitter's OAuth
http://en.wikipedia.org/wiki/HMAC
Code: Select all
; hss/2011
Procedure.s hmac_sha1(key.s,msg.s)
If(Len(key)>64)
key=SHA1Fingerprint(@key,Len(key))
For x=1 To 20:PokeB(@key+x-1,Val("$"+Mid(key,(x*2)-1,2))):Next
For x=20 To Len(key):PokeB(@key+x,0):Next
EndIf
key=LSet(key,64,Chr(0)):ipad.s=LSet(ipad,64,Chr($36)):opad.s=LSet(opad,64,Chr($5c))
*ipadt=AllocateMemory(64+Len(msg)):*opadt=AllocateMemory(64+20)
PokeS(*ipadt,ipad,64):PokeS(*opadt,opad,64)
For x=1 To 64
PokeB(*opadt+x-1,Asc(Mid(opad,x,1))!Asc(Mid(key,x,1)))
PokeB(*ipadt+x-1,Asc(Mid(ipad,x,1))!Asc(Mid(key,x,1)))
Next
PokeS(*ipadt+64,msg,Len(msg))
one.s=SHA1Fingerprint(*ipadt,MemorySize(*ipadt))
For x=64 To 84:xx+1:PokeB(*opadt+x,Val("$"+Mid(one,(xx*2)-1,2))):Next
two.s=SHA1Fingerprint(*opadt,64+20)
*i=AllocateMemory(20)
For x=1 To 20:PokeB(*i+x-1,Val("$"+Mid(two,(x*2)-1,2))):Next
*o=AllocateMemory(20*1.35)
Base64Encoder(*i,20,*o,20*1.35)
r.s=PeekS(*o)
r=ReplaceString(r,"+","%2B")
r=ReplaceString(r,"=","%3D")
r=ReplaceString(r,"/","%2F")
ProcedureReturn r
EndProcedure
JS testing -
http://jssha.sourceforge.net/ (Debug two.s in PB to compare results)
PHP
Code: Select all
echo rawurlencode(base64_encode(hash_hmac('sha1',$msg,$key,TRUE)));
Re: hmac_sha1
Posted: Wed Aug 03, 2011 10:49 am
by giammy
Great job!
I am a newbie
I need for an hmac_sha256 implementation in Purebasic
can anyone help me?
Thanks in advance!
Re: hmac_sha1
Posted: Sat Apr 08, 2023 4:02 am
by Seymour Clufley
Trying to update this code to work with PB6.01, and I've run into trouble.
Code: Select all
Procedure.s hmac_sha1(key.s,msg.s)
UseSHA1Fingerprint()
If(Len(key)>64)
key = StringFingerprint(key,#PB_Cipher_SHA1)
For x=1 To 20:PokeB(@key+x-1,Val("$"+Mid(key,(x*2)-1,2))):Next
For x=20 To Len(key):PokeB(@key+x,0):Next
EndIf
key = LSet(key,64,Chr(0))
ipad.s = LSet(ipad,64,Chr($36))
opad.s = LSet(opad,64,Chr($5c))
*ipadt = AllocateMemory(64+Len(msg))
PokeS(*ipadt,ipad,64)
*opadt = AllocateMemory(64+20)
PokeS(*opadt,opad,64)
For x=1 To 64
PokeB(*opadt+x-1,Asc(Mid(opad,x,1))!Asc(Mid(key,x,1)))
PokeB(*ipadt+x-1,Asc(Mid(ipad,x,1))!Asc(Mid(key,x,1)))
Next
PokeS(*ipadt+64,msg,Len(msg))
ipadt.s = PeekS(*ipadt,MemorySize(*ipadt))
one.s = StringFingerprint(ipadt,#PB_Cipher_SHA1)
For x=64 To 84:xx+1:PokeB(*opadt+x,Val("$"+Mid(one,(xx*2)-1,2))):Next
opadt.s = PeekS(*opadt,64+20)
two.s = StringFingerprint(opadt,#PB_Cipher_SHA1)
*i = AllocateMemory(20)
For x = 1 To 20
PokeB(*i+x-1,Val("$"+Mid(two,(x*2)-1,2)))
Next
r.s = Base64Encoder(*i,20)
r=ReplaceString(r,"+","%2B")
r=ReplaceString(r,"=","%3D")
r=ReplaceString(r,"/","%2F")
ProcedureReturn r
EndProcedure
key.s = "testkey123"
msg.s = "test string"
sha.s = hmac_sha1(key,msg)
Debug URLEncoder(sha)
Debug "XosSbTmfw5OJ4mh1NSupUH3l7HY=" ; what the PHP version outputs
Can anyone see where I'm going wrong?
Re: hmac_sha1
Posted: Sat Apr 08, 2023 12:13 pm
by infratec
Was a problem between unicode and ascii.
But it was to complicated to change this, so I implemented it from scratch:
Code: Select all
;
; https://en.wikipedia.org/wiki/HMAC
;
; HMAC(M) = H((K XOR opad) + H((K XOR ipad) + M))
;
; M = message
; K = key
; opad = 0x5C
; ipad = 0x36
; H = hash function
;
; https://www.purebasic.fr/english/viewtopic.php?p=599038#p599038
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
Procedure StringHMAC_HexStringToBin(*HexString.Ascii, *Destination.Ascii)
Protected HighNibble, LowNibble
If *HexString And *Destination
While *HexString\a
HighNibble = *HexString\a - '0'
If HighNibble > $f
HighNibble - $27
EndIf
*HexString + 2
LowNibble = *HexString\a - '0'
If LowNibble > $f
LowNibble - $27
EndIf
*HexString + 2
*Destination\a = HighNibble << 4 | LowNibble
*Destination + 1
;Debug Hex(HighNibble << 4 | LowNibble, #PB_Ascii)
Wend
EndIf
EndProcedure
Procedure.s StringHMAC(msg$, key$, cipher.i=#PB_Cipher_SHA1, bits.i=256, encode$="Hex")
#IPAD = $36
#OPAD = $5C
Protected.i i, BlockSize, cipherResultSize
Protected result$, innerHash$
Protected *tmp, *ptr.Ascii, *innerHash, *outerHash
; adjust the needed values for different ciphers
BlockSize = 64
Select cipher
Case #PB_Cipher_MD5
cipherResultSize = 16
Case #PB_Cipher_SHA1
cipherResultSize = 20
Case #PB_Cipher_SHA2
If bits > 256
BlockSize = 128
EndIf
cipherResultSize = bits / 8
Case #PB_Cipher_SHA3
Select bits
Case 224
BlockSize = 1152 / 8
Case 256
BlockSize = 1088 / 8
Case 384
BlockSize = 832 / 8
Case 512
BlockSize = 576 / 8
EndSelect
cipherResultSize = bits / 8
Default
ProcedureReturn "cipher not implemented"
EndSelect
; special rule if length of the key is larger then the blocksize:
; use H(K) instead of K
If StringByteLength(key$, #PB_Ascii) > BlockSize
key$ = StringFingerprint(key$, cipher, bits, #PB_Ascii)
*tmp = AllocateMemory(cipherResultSize)
If *tmp
StringHMAC_HexStringToBin(@key$, *tmp)
key$ = PeekS(*tmp, cipherResultSize, #PB_Ascii)
FreeMemory(*tmp)
EndIf
EndIf
*outerHash = AllocateMemory(BlockSize + cipherResultSize)
If *outerHash
; K XOR opad
*ptr = *outerHash
PokeS(*outerHash, key$, -1, #PB_Ascii|#PB_String_NoZero)
For i = 0 To BlockSize - 1
*ptr\a = *ptr\a ! #OPAD
*ptr + 1
Next i
*innerHash = AllocateMemory(BlockSize + StringByteLength(msg$, #PB_UTF8))
If *innerHash
; K XOR ipad
*ptr = *innerHash
PokeS(*innerHash, key$, -1, #PB_Ascii|#PB_String_NoZero)
For i = 0 To BlockSize - 1
*ptr\a = *ptr\a ! #IPAD
*ptr + 1
Next i
; (K XOR ipad) + M)
PokeS(*ptr, msg$, -1, #PB_UTF8|#PB_String_NoZero)
; H((K XOR ipad) + M))
innerHash$ = Fingerprint(*innerHash, MemorySize(*innerHash), cipher, bits)
; (K XOr opad) + H((K XOr ipad) + M)
StringHMAC_HexStringToBin(@innerHash$, *outerHash + BlockSize)
; H((K XOR opad) + H((K XOR ipad) + M))
result$ = Fingerprint(*outerHash, BlockSize + cipherResultSize, cipher, bits)
; optional result is coded in Base64
If LCase(encode$) = "base64"
*tmp = AllocateMemory(cipherResultSize)
If *tmp
StringHMAC_HexStringToBin(@result$, *tmp)
result$ = Base64Encoder(*tmp, MemorySize(*tmp))
FreeMemory(*tmp)
EndIf
EndIf
FreeMemory(*innerHash)
EndIf
FreeMemory(*outerHash)
EndIf
ProcedureReturn result$
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Define key$, msg$
UseMD5Fingerprint()
UseSHA1Fingerprint()
UseSHA2Fingerprint()
UseSHA3Fingerprint()
msg$ = "test string"
key$ = "testkey123"
Debug "Hex : " + StringHMAC(msg$, key$)
Debug "Base64: " + StringHMAC(msg$, key$, #PB_Cipher_SHA1, 0, "Base64")
Debug "PHP : XosSbTmfw5OJ4mh1NSupUH3l7HY="
; Example from:
; https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature
msg$ = "POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521"
key$ = "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw&LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"
Debug ""
Debug "twitter " + StringHMAC(msg$, key$)
Debug "Should be: 842b5299887e88760212a056ac4ec2ee1626b549"
; following tests are verified by
; (https://www.freeformatter.com/hmac-generator.html) no SHA-3 calculations
; https://appdevtools.com/hmac-generator generates false SHA-3 !!!!!!
; https://www.liavaag.org/English/SHA-Generator/HMAC/
; https://wtools.io/generate-hmac-hash
Debug ""
Debug "test For non ASCII:"
msg$ = "Begrüßung"
key$ = "123"
Debug "msg: " + msg$
Debug "key: " + key$
Debug ""
Debug "SHA1 " + StringHMAC(msg$, key$)
Debug "Should be: 149b6e8402e9526bbcbc93dc99b0fea3b65e25b0"
msg$ = "PureBasic"
key$ = "123456"
Debug ""
Debug "All ciphers tests:"
Debug "msg: " + msg$
Debug "key: " + key$
Debug ""
Debug "MD5 " + StringHMAC(msg$, key$, #PB_Cipher_MD5)
Debug "Should be: bc2c0b90c3b8b46ebdab6a188ce7546c"
Debug ""
Debug "SHA1 " + StringHMAC(msg$, key$, #PB_Cipher_SHA1)
Debug "Should be: 9fa85352d7a125c06f1c0f4653633ee482b9e216"
Debug ""
Debug "SHA2 224 " + StringHMAC(msg$, key$, #PB_Cipher_SHA2, 224)
Debug "Should be: b230ab71aca84befc565276112a3c16356cbdbd70c465080e1c7ee89"
Debug ""
Debug "SHA2 256 " + StringHMAC(msg$, key$, #PB_Cipher_SHA2, 256)
Debug "Should be: 27d722c54c40d9b9b4e15db1e5da439b493f22872d469b7bc60ab73d05d7a486"
Debug ""
Debug "SHA2 384 " + StringHMAC(msg$, key$, #PB_Cipher_SHA2, 384)
Debug "Should be: c348fe1e3a4acfd2d180feaca699145100f0f6a0bc02472ee775b250a99a5dcca947496c86ae9ed62cda320f99e7bc54"
Debug ""
Debug "SHA2 512 " + StringHMAC(msg$, key$, #PB_Cipher_SHA2, 512)
Debug "Should be: cc0d17134c476566e6d19d9bb6f08ca127209b711cf1669d3169541d038de1dae9efd031f473b8f502326ee1aec1612dc2309da00f49c163746e4e1f85e305d1"
Debug ""
Debug "SHA3 224 " + StringHMAC(msg$, key$, #PB_Cipher_SHA3, 224)
Debug "Should be: 8a3e3c00fa9ecec23c8e14336936ea6b62b81e2742ac9c171e931a27"
Debug ""
Debug "SHA3 256 " + StringHMAC(msg$, key$, #PB_Cipher_SHA3, 256)
Debug "Should be: 56d40211ecbf9825d2545fadb2768aed781fe9bd0cbf33e874e2308e430241b7"
Debug ""
Debug "SHA3 384 " + StringHMAC(msg$, key$, #PB_Cipher_SHA3, 384)
Debug "Should be: af025b8dea23ee1db0ceaa60904ec28778a6e3a8c1d12924cf63c952a0689cc98e1df1cb448c2c7b7544cc33a26e3632"
Debug ""
Debug "SHA3 512 " + StringHMAC(msg$, key$, #PB_Cipher_SHA3, 512)
Debug "Should be: 7a46e0efc0fe813c992f2e86a70c304cc65b590e0cc6f3870936e0b96cf39d4aa98a480e66aae359d72f851c133e6b6a53fe06a1f7ebcd02186ab65c06f9a9fb"
CompilerEndIf
Re: hmac_sha1
Posted: Sat Apr 08, 2023 12:17 pm
by mk-soft
PB Strings are Unicode (2 bytes)
Re: hmac_sha1
Posted: Sat Apr 08, 2023 12:28 pm
by Fred
Cool stuff
Re: hmac_sha1
Posted: Sat Apr 08, 2023 1:25 pm
by blueb
Lunasole's excellent code (with Rinzwind's #PB_UTF8 mods) has worked well for me.
(using Win 11 Pro)
Includes MD5 / SHA1 / SHA2
see:
viewtopic.php?p=493022#p493022
Code: Select all
; =================================================================
;
; Author: Luna Sole
; Date: August 19th, 2016
; Explain: HMAC function implementation (hash-based message authentication code)
;
; In cryptography, a keyed-hash message authentication code (HMAC) is a specific type of message
; authentication code (MAC) involving a cryptographic hash function (hence the 'H') in combination
; with a secret cryptographic key. As with any MAC, it may be used to simultaneously verify both
; the data integrity and the authentication of a message. Any cryptographic hash function, such
; as MD5 or SHA-1, may be used in the calculation of an HMAC; the resulting MAC algorithm is termed
; HMAC-MD5 or HMAC-SHA1 accordingly. The cryptographic strength of the HMAC depends upon the
; cryptographic strength of the underlying hash function, the size of its hash output, and on the
; size and quality of the key.
; An iterative hash function breaks up a message into blocks of a fixed size and iterates over them
; with a compression function. For example, MD5 and SHA-1 operate on 512-bit blocks. The size of the
; output of HMAC is the same as that of the underlying hash function (128 or 160 bits in the case of
; MD5 or SHA-1, respectively), although it can be truncated if desired.
;
; Typical Usage: HMAC Sample.pb
; =================================================================
; Modifications Feb 2020 by Rizwind
; You might want to use #PB_UTF8 as encoding to make it compatible with other generator results when using unicode strings.
; Replaced all #PB_ASCII constants with #PB_UTF8
; Results for ascii values will stay the same since utf-8 is backward compatible.
; 'random' test text: Begrüßenภาษาไทย!
; SHA2: 7596eaf61caf36289d5b1c9c8780dc657767e867a00d079bd9da518bb254a6c3
; see the bottom for example
; Another example of why PB should include hash functions that return raw byte data.
; ------------------------------------------------------------------------------------------------
EnableExplicit
Procedure Hex2Dec (Array Out.a (1), Hex$) ; 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
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
; -------------------------------------------------
Procedure$ StringHMAC (PB_Cipher, Message$, Key$) ; 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: - a string representing HMAC hash
; --------------------------------------------------------
UseMD5Fingerprint() : UseSHA1Fingerprint() : UseSHA2Fingerprint() ; currently only verified with these algorithms
#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_UTF8) > #HMAC_BLOCKSIZE)
PokeS(@key_bdata(0), StringFingerprint(Key$, PB_Cipher), -1, #PB_UTF8 | #PB_String_NoZero)
Else
PokeS(@key_bdata(0), Key$, -1, #PB_UTF8 | #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_UTF8))
PokeS(@TempRaw(0), Message$, -1, #PB_UTF8 | #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
; some tests
Debug "* HMAC of empty data and empty key *"
Debug "MD5: " + StringHMAC(#PB_Cipher_MD5, "", "") ; MD5 = 74e6f7298a9c2d168935f58c001bad88
Debug "SHA1: " + StringHMAC(#PB_Cipher_SHA1, "", "") ; SHA1 = fbdb1d1b18aa6c08324b7d64b71fb76370690e1d
Debug "SHA2: " + StringHMAC(#PB_Cipher_SHA2, "", "") ; SHA256 = b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad
Debug ""
Debug "* HMAC of control data to check is it OK *"
Debug "MD5: " + StringHMAC(#PB_Cipher_MD5, "The quick brown fox jumps over the lazy dog", "key") ; MD5 = 80070713463e7749b90c2dc24911e275
Debug "SHA1: " + StringHMAC(#PB_Cipher_SHA1, "The quick brown fox jumps over the lazy dog", "key") ; SHA1 = de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
Debug "SHA2: " + StringHMAC(#PB_Cipher_SHA2, "The quick brown fox jumps over the lazy dog", "key") ; SHA256 = f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
Debug ""
; 'random' test text: Begrüßenภาษาไทย! (Rinzwind sample)
Debug "Rinzwind's sample... SHA2: " + StringHMAC(#PB_Cipher_SHA2, "Begrüßenภาษาไทย!", "key") ; SHA2: 7596eaf61caf36289d5b1c9c8780dc657767e867a00d079bd9da518bb254a6c3
Debug " Expected: 7596eaf61caf36289d5b1c9c8780dc657767e867a00d079bd9da518bb254a6c3"
Debug ""
Debug "- Done -"
; Control data and resulting HMAC-hashes for it taken from wiki page:
; https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Examples
Re: hmac_sha1
Posted: Sat Apr 08, 2023 1:31 pm
by Seymour Clufley
infratec wrote: Sat Apr 08, 2023 12:13 pm
Was a problem between unicode and ascii.
But it was to complicated to change this, so I implemented it from scratch
Thank you very much!
Re: hmac_sha1
Posted: Sat Apr 08, 2023 5:16 pm
by Seymour Clufley
Infratec's algorithm works as expected for the test string above and for the
Wikipedia test string, but not for
this Twitter test string. That page says what the HMAC_SHA1 should produce, and that is outputted by the PHP's algorithm, but not by Infratec's algorithm.
Code: Select all
Procedure.s HMAC_SHA1(msg.s, key.s, outputFormat.s)
#IPAD = $36
#OPAD = $5C
UseSHA1Fingerprint()
Protected.i i
Protected.s r, inner
Protected *ipad, *opad, *r, *buffer
If Len(key) > 64
key = StringFingerprint(key, #PB_Cipher_SHA1)
EndIf
*opad = AllocateMemory(64)
If *opad
PokeS(*opad, key, -1, #PB_Ascii|#PB_String_NoZero)
For i = 0 To 63
PokeA(*opad + i, PeekA(*opad + i) ! #OPAD)
Next i
*ipad = AllocateMemory(64)
If *ipad
PokeS(*ipad, key, -1, #PB_Ascii|#PB_String_NoZero)
For i = 0 To 63
PokeA(*ipad + i, PeekA(*ipad + i) ! #IPAD)
Next i
*buffer = AllocateMemory(64 + 20)
If *buffer
CopyMemory(*opad, *buffer, 64)
inner = StringFingerprint(PeekS(*ipad, 64, #PB_Ascii) + msg, #PB_Cipher_SHA1)
For i = 0 To 19
PokeA(*buffer + 64 + i, Val("$" + Mid(inner, i * 2 + 1, 2)))
Next i
r = Fingerprint(*buffer, 84, #PB_Cipher_SHA1)
If LCase(outputFormat) = "base64"
*r = AllocateMemory(20)
If *r
For i = 0 To 19
PokeA(*r + i, Val("$" + Mid(r, i * 2 + 1, 2)))
Next i
r = Base64Encoder(*r, MemorySize(*r))
FreeMemory(*r)
EndIf
EndIf
FreeMemory(*buffer)
EndIf
FreeMemory(*ipad)
EndIf
FreeMemory(*opad)
EndIf
ProcedureReturn r
EndProcedure
signatureBaseString.s = "POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521"
signingKey.s = "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw&LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"
Debug "hCtSmYh+iHYCEqBWrE7C7hYmtUk=" ; this is what it should be, according to Twitter
Debug HMAC_SHA1(signatureBaseString,signingKey,"Base64")
This cipher stuff is all beyond my expertise, so I hope someone else (Infratec?) can work out what is going on here.
Re: hmac_sha1
Posted: Sat Apr 08, 2023 6:46 pm
by infratec
Fixed my code above:
viewtopic.php?p=599038#p599038
As expected, it was a problem when the key was longer then the blocksize.
But lunasoles code looks better then mine.
Unfortunately he also has a bug inside.
I will try to fix this too.
Re: hmac_sha1
Posted: Sat Apr 08, 2023 7:36 pm
by infratec
Changed the listing above:
Now also supports non ASCII msgs and other ciphers.
Re: hmac_sha1
Posted: Sat Apr 08, 2023 8:10 pm
by infratec
I fixed lunasoles stuff, but this breaks the multicipher possibility.
viewtopic.php?p=599072#p599072
And after a closer look, I prefer my memory pointer solution.
Re: hmac_sha1
Posted: Sat Apr 08, 2023 11:54 pm
by Seymour Clufley
Thank you very much, Infratec. This has been a great help for me. You could rename the procedure to simply "HMAC", since it now supports the other ciphers as well.
Re: hmac_sha1
Posted: Sat Apr 08, 2023 11:57 pm
by infratec
I already renamed it to StringHMAC()
And I just optimized the Hex string to bin conversion.
Re: hmac_sha1
Posted: Sun Apr 09, 2023 12:26 pm
by infratec
Added the possibility for different bit length in SHA2 and 3