Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
oAuth HMAC-SHA1
#1
I'm working with oAuth and I'd like QM to generate my signature using HMAC-SHA1
http://en.wikipedia.org/wiki/HMAC

I'm cracking on this, but figured one of you'd come up with a brilliant solution,.

Thanks,
jim
#2
There are several libraries in C++/C#, it would be nice to make a dll:

cityhash-1.0.3
cryptopp561
HashCheck
mhash-0.9.9.9
openssl-1.0.1c
sphlib-3.0
zlib-1.2.7
#3
[deleted]

The MSDN code was incorrect.
#4
Thanks for the help.

I've found an example in javascript that does exactly what I need:
http://oauth.googlecode.com/svn/code/ja ... ature.html

str.HMAC_SHA1 returns some strange results and I'm not really sure how to use it to get the same as the webpage above.

I do have a hack to run JavaScript with QM...So I am using that right now to get the signature in HMAC-SHA1 from the data...I'd like to do code it all in QM because it will be faster.

Thanks,
jim

Here's a little more about the project:
QM prepares a cURL command line and saves to a script file. Then calls PuTTY with RunConsole2 to establish an SSH connection to run the script on a remote Linux (Ubuntu) virtual machine.
Looks like this:
Code:
Copy      Help
RunConsole2("c:\putty.exe -ssh [email protected] 22 -pw password -m c:\cURL.sh" 0 "" 0)

The cURL command uses all the OAuth information to make twitter posts. Right now I've got a prototype working...it's clunky all over for sure, but it's getting there.

It was easier to get the cURL commands to execute on Linux. I had a really hard time getting things to run in Windows environment.
#5
Thanks for your help, Gintaras.

I'm not sure if I understand how it works, but I have checked the example with some online calcs

"message" & "password"

HMAC_SHA1 result:
4c2de361ba8958558de3d049ed1fb5c115656e65

QM:

48 F2 57 38 29 29 43 16 FD F4 DB 58 31 E1 0C 74 48 8E D4 E2
#6
I've checked online calculators and the results are different from those obtained with QM.

Any idea what's going on?
#7
This gives correct result.
Don't need WINAPI2.

Member function str.HMAC_SHA1
Code:
Copy      Help
;/
function str&data str'password [flags] ;;flags: 1 hex-encode

;Creates a hashed message authentication checksum (HMAC) using SHA1 algorithm.
;Stores the HMAC (160-bit length binary data) in this variable. Error if fails.

;data - variable containing message data.
;password - key.

;REMARKS
;A hashed message authentication checksum (HMAC) is typically used to verify that a message has not been changed during transit. Both parties to the message must have a shared secret key. The sender combines the key and the message into a string, creates a digest of the string by using an algorithm such as SHA-1 or MD5, and transmits the message and the digest. The receiver combines the shared key with the message, applies the appropriate algorithm, and compares the digest thus obtained with that transmitted by the sender. If the digests are exactly the same, the message was not tampered with.

;EXAMPLE
;str data="message"
;str password="password"
;str s
;s.HMAC_SHA1(data password 1)
;out s


type HMAC_INFO HashAlgid !*pbInnerString cbInnerString !*pbOuterString cbOuterString
def CALG_SHA1 0x00008004
dll advapi32 [CryptAcquireContextA]#CryptAcquireContext *phProv $szContainer $szProvider dwProvType dwFlags
def PROV_RSA_FULL 1
def CRYPT_VERIFYCONTEXT 0xF0000000
dll advapi32 #CryptCreateHash hProv Algid hKey dwFlags *phHash
dll advapi32 #CryptHashData hHash !*pbData dwDataLen dwFlags
type BLOBHEADER !bType !bVersion @reserved aiKeyAlg
def PLAINTEXTKEYBLOB 0x8
def CUR_BLOB_VERSION 2
def CALG_RC2 0x00006602
dll advapi32 #CryptImportKey hProv !*pbData dwDataLen hPubKey dwFlags *phKey
def CRYPT_IPSEC_HMAC_KEY 0x00000100
def CALG_HMAC 0x00008009
dll advapi32 #CryptSetHashParam hHash dwParam !*pbData dwFlags
def HP_HMAC_INFO 0x0005
dll advapi32 #CryptGetHashParam hHash dwParam !*pbData *pdwDataLen dwFlags
def HP_HASHVAL 0x0002
dll advapi32 #CryptDestroyHash hHash
dll advapi32 #CryptDestroyKey hKey
dll advapi32 #CryptReleaseContext hProv dwFlags


if(password.len>1024) end "password too long (max 1024)"

int hProv ;;HCRYPTPROV
int hHash ;;HCRYPTHASH
int hKey ;;HCRYPTKEY
int hHmacHash ;;HCRYPTHASH
int dwDataLen
HMAC_INFO HmacInfo
str es ;;error string

HmacInfo.HashAlgid = CALG_SHA1

if(!CryptAcquireContext(&hProv 0 0 PROV_RSA_FULL CRYPT_VERIFYCONTEXT)) es.format(" Error in AcquireContext 0x%08x \n", GetLastError()); goto ErrorExit
if(!CryptCreateHash(hProv CALG_SHA1 0 0 &hHash)) es.format("Error in CryptCreateHash 0x%08x \n", GetLastError()); goto ErrorExit
if(!CryptHashData(hHash password password.len 0)) es.format("Error in CryptHashData 0x%08x \n", GetLastError()); goto ErrorExit

type __KEYBLOB BLOBHEADER'hdr len key[1024]
__KEYBLOB key_blob
key_blob.hdr.bType = PLAINTEXTKEYBLOB
key_blob.hdr.bVersion = CUR_BLOB_VERSION
key_blob.hdr.aiKeyAlg = CALG_RC2
key_blob.len = password.len
memcpy &key_blob.key password password.len
if(!CryptImportKey(hProv &key_blob sizeof(key_blob) 0 CRYPT_IPSEC_HMAC_KEY &hKey)) es.format("Error in CryptImportKey 0x%08x \n", GetLastError()); goto ErrorExit

if(!CryptCreateHash(hProv CALG_HMAC hKey 0 &hHmacHash)) es.format("Error in CryptCreateHash 0x%08x \n", GetLastError()); goto ErrorExit
if(!CryptSetHashParam(hHmacHash HP_HMAC_INFO &HmacInfo 0)) es.format("Error in CryptSetHashParam 0x%08x \n", GetLastError()); goto ErrorExit
if(!CryptHashData(hHmacHash data data.len 0)) es.format("Error in CryptHashData 0x%08x \n", GetLastError()); goto ErrorExit

if(!CryptGetHashParam(hHmacHash HP_HASHVAL 0 &dwDataLen 0)) es.format("Error in CryptGetHashParam 0x%08x \n", GetLastError()); goto ErrorExit
this.all(dwDataLen 2)
if(!CryptGetHashParam(hHmacHash HP_HASHVAL this &dwDataLen 0)) es.format("Error in CryptGetHashParam 0x%08x \n", GetLastError()); goto ErrorExit

int ok=1

;ErrorExit
if(hHmacHash) CryptDestroyHash(hHmacHash)
if(hKey) CryptDestroyKey(hKey)
if(hHash) CryptDestroyHash(hHash)
if(hProv) CryptReleaseContext(hProv 0)

if(!ok) end "failed. %s" 0 es

if(flags&1) this.encrypt(8)
#8
sorry but each time i test this function with the example, i get an error on the line containing :

HMAC_INFO HmacInfo


Error in str.HMAC_SHA1: unknown identifier.


I don't understand why ?

Thank's Dominique
#9
restart QM. It is because in previous version was used WINAPI2.
#10
Thanks a lot, Gintaras. Now it works like a charm!
#11
thank's it works ok now !

dominique
#12
Going from this webpage: https://dev.twitter.com/docs/auth/creating-signature

I've been able to write a QM script that outputs the correct binary string "B6 79 C0 AF 18 F4 E9 C5 87 AB 8E 20 0A CD 4E 48 A9 3F 8C B6"

The trouble is when the string is encrypted Base64 returns:
QjYgNzkgQzAgQUYgMTggRjQgRTkgQzUgODcgQUIgOEUgMjAgMEEgQ0QgNEUgNDggQTkgM0YgOEMg
QjY=

But according to the webpage, supposed to be: "tnnArxj06cWHq44gCs1OSKk/jLY="


Function OAuthSignature
Code:
Copy      Help
REPLACERX r.frepl=&replacerx_UCASE
;;/
;function# REPLACERXCB&x
;x.match.ucase

str HTTP_method="POST"
str URL="https://api.twitter.com/1/statuses/update.json"
str Consumer_secret="kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw"
str OAuth_token_secret="LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"
str status="Hello Ladies + Gentlemen, a signed OAuth request!"
str include_entities="true"
str oauth_consumer_key="xvz1evFS4wEEPTGEFPHBog"
str oauth_nonce="kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg"
str oauth_signature_method="HMAC-SHA1"
str oauth_timestamp="1318622958"
str oauth_token="370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb"
str oauth_version="1.0"

;;;how to escape all these in one line?
HTTP_method.escape(9)
URL.escape(9)
Consumer_secret.escape(9)
OAuth_token_secret.escape(9)
status.escape(9)
include_entities.escape(9)
oauth_consumer_key.escape(9)
oauth_nonce.escape(9)
oauth_signature_method.escape(9)
oauth_timestamp.escape(9)
oauth_token.escape(9)
oauth_version.escape(9)

str Parameter_string=
F
;include_entities={include_entities}
;&oauth_consumer_key={oauth_consumer_key}
;&oauth_nonce={oauth_nonce}
;&oauth_signature_method={oauth_signature_method}
;&oauth_timestamp={oauth_timestamp}
;&oauth_token={oauth_token}
;&oauth_version={oauth_version}
;&status={status}
Parameter_string.findreplace("[]")
Parameter_string.replacerx("\%[\d\w]{2}" &r)
Parameter_string.escape(9)

str signature_base=F"{HTTP_method}&{URL}&{Parameter_string}"
str signing_key=F"{Consumer_secret}&{OAuth_token_secret}"

signature_base.replacerx("\%[\d\w]{2}" &r)
signing_key.replacerx("\%[\d\w]{2}" &r)

str OAuth_signature.HMAC_SHA1(signature_base signing_key)
OAuth_signature.encrypt(8 OAuth_signature "" 1)
OAuth_signature.trim

OAuth_signature.encrypt(4)
out OAuth_signature
#13
Running this VBS script http://www.rlmueller.net/Programs/HexToBase64.txt with "B6 79 C0 AF 18 F4 E9 C5 87 AB 8E 20 0A CD 4E 48 A9 3F 8C B6" encrypts to "tnnArxj06cWHq44gCs1OSKk/jLY="

I don't know what I am doing wrong with QM.

-Jim
#14
Do base64 on binary data.
"B6 79 C0 AF 18 F4 E9 C5 87 AB 8E 20 0A CD 4E 48 A9 3F 8C B6" is binary converted to string in hex format.
Remove the '.encrypt(8' line which does it, and the trim line.
#15
I thought I had done that while I was troubleshooting. Works like a charm. Thanks,

-jim


Forum Jump:


Users browsing this thread: 3 Guest(s)