News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

HMAC MD5/SHA1

Started by Magnum, March 09, 2013, 01:58:59 AM

Previous topic - Next topic

Magnum

I thought this may be of interest.


001 #include <iostream>
002 #include "windows.h"
003 #include <wincrypt.h>
004
005 #ifndef CALG_HMAC
006 #define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
007 #endif
008
009 #ifndef CRYPT_IPSEC_HMAC_KEY
010 #define CRYPT_IPSEC_HMAC_KEY 0x00000100
011 #endif
012
013 #pragma comment(lib, "crypt32.lib")
014
015 using namespace std;
016
017 char * HMAC(char * str, char * password, DWORD AlgId);
018
019
020 typedef struct _my_blob{
021 BLOBHEADER header;
022 DWORD len;
023 BYTE key[0];
024 }my_blob;
025
026
027 int main(int argc, _TCHAR* argv[])
028 {
029
030      char * hash_sha1 = HMAC("ROSDEVIL", "password", CALG_SHA1);
031      char * hash_md5 = HMAC("ROSDEVIL", "password", CALG_MD5);
032      
033      cout<<"Hash HMAC-SHA1: "<<hash_sha1<<" ( "<<strlen(hash_sha1)<<" )"<<endl;
034      cout<<"Hash HMAC-MD5: "<<hash_md5<<" ( "<<strlen(hash_md5)<<" )"<<endl;
035      
036      cin.get();
037      return 0;
038 }
039
040 char * HMAC(char * str, char * password, DWORD AlgId = CALG_MD5){
041
042    HCRYPTPROV  hProv = 0;
043    HCRYPTHASH  hHash = 0;
044    HCRYPTKEY   hKey = 0;
045    HCRYPTHASH  hHmacHash = 0;
046    BYTE    * pbHash = 0;
047    DWORD       dwDataLen = 0;
048    HMAC_INFO   HmacInfo;
049
050    int err = 0;
051    
052    ZeroMemory(&HmacInfo, sizeof(HmacInfo));
053    
054    if (AlgId == CALG_MD5){
055         HmacInfo.HashAlgid = CALG_MD5;
056         pbHash = new BYTE[16];
057         dwDataLen = 16;
058    }else if(AlgId == CALG_SHA1){
059         HmacInfo.HashAlgid = CALG_SHA1;
060         pbHash = new BYTE[20];
061         dwDataLen = 20;
062    }else{
063         return 0;   
064    }
065    
066    ZeroMemory(pbHash, sizeof(dwDataLen));
067    char * res = new char[dwDataLen * 2];
068    
069    my_blob * kb = NULL;
070    DWORD kbSize = sizeof(my_blob) + strlen(password);
071
072    kb = (my_blob*)malloc(kbSize);
073    kb->header.bType = PLAINTEXTKEYBLOB;
074    kb->header.bVersion = CUR_BLOB_VERSION;
075    kb->header.reserved = 0;
076    kb->header.aiKeyAlg = CALG_RC2;
077    memcpy(&kb->key, password, strlen(password));
078    kb->len = strlen(password);
079
080
081    if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)){
082       err = 1;
083       goto Exit;
084    }
085
086
087    if (!CryptImportKey(hProv,  (BYTE*)kb, kbSize, 0, CRYPT_IPSEC_HMAC_KEY, &hKey)){
088        err = 1;
089        goto Exit;
090    }
091
092    if (!CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHmacHash)){
093        err = 1;
094        goto Exit;
095    }
096    
097    
098    if (!CryptSetHashParam(hHmacHash, HP_HMAC_INFO, (BYTE*)&HmacInfo, 0)){
099        err = 1;
100        goto Exit;
101    }
102
103    if (!CryptHashData(hHmacHash, (BYTE*)str, strlen(str), 0)){
104        err = 1;
105        goto Exit;
106    }
107    
108    if (!CryptGetHashParam(hHmacHash, HP_HASHVAL, pbHash, &dwDataLen, 0)){
109        err = 1;
110        goto Exit;
111    }
112
113    ZeroMemory(res, dwDataLen * 2);
114    char * temp;
115    temp = new char[3];
116    ZeroMemory(temp, 3);
117    for (unsigned int m = 0; m < dwDataLen; m++){
118        sprintf(temp, "%2x", pbHash[m]);
119        if (temp [1] == ' ') temp [1] = '0';  // note these two: they are two CORRECTIONS to the conversion in HEX, sometimes the Zeros are
120        if (temp [0] == ' ') temp [0] = '0';  // printed with a space, so we replace spaces with zeros; (this error occurs mainly in HMAC-SHA1)
121        sprintf(res,"%s%s", res,temp);
122    }
123    
124    delete [] temp;
125
126     Exit:
127     free(kb);
128     if(hHmacHash)
129         CryptDestroyHash(hHmacHash);
130     if(hKey)
131         CryptDestroyKey(hKey);
132     if(hHash)
133         CryptDestroyHash(hHash);   
134     if(hProv)
135         CryptReleaseContext(hProv, 0);
136    
137      
138     if (err == 1){
139         delete [] res;
140         return "";     
141     }
142      
143     return res;
144 }
145 //Note: using HMAC-MD5 you could perform the famous CRAM-MD5 used to authenticate
146 //smtp servers.
Take care,
                   Andy

Ubuntu-mate-18.04-desktop-amd64

http://www.goodnewsnetwork.org

dedndave

credits ?
where'd you get it ?

dedndave

i am no C guy, but.....
the first 3 lines look a little out of whack, to me   :biggrin:
001 #include <iostream>
002 #include "windows.h"
003 #include <wincrypt.h>

Magnum

ROSDEVIL wrote it. It's in the code.

Take care,
                   Andy

Ubuntu-mate-18.04-desktop-amd64

http://www.goodnewsnetwork.org

dedndave


CommonTater

Quote from: dedndave on March 10, 2013, 12:31:46 AM
i am no C guy, but.....
the first 3 lines look a little out of whack, to me   :biggrin:
001 #include <iostream>
002 #include "windows.h"
003 #include <wincrypt.h>


... because it's C++ code.

dedndave

i was refering to
1) i thought the windows.h file always went first
2) each of the 3 includes uses a slightly different syntax   :P

C, C+, C++, C- has nothing to do with it

ragdog

Hi

I know is a old post but i try to translate it to Asm

But i have here my problems can any translate it please?


020 typedef struct _my_blob{
021 BLOBHEADER header;

..
   my_blob * kb = NULL;
070    DWORD kbSize = sizeof(my_blob) + strlen(password);
071
072    kb = (my_blob*)malloc(kbSize);
073    kb->header.bType = PLAINTEXTKEYBLOB;
074    kb->header.bVersion = CUR_BLOB_VERSION;
075    kb->header.reserved = 0;
076    kb->header.aiKeyAlg = CALG_RC2;
077    memcpy(&kb->key, password, strlen(password));
078    kb->len = strlen(password);
079

TouEnMasm


Here is the c code written for c++ 10 express

// dos.cpp : définit le point d'entrée pour l'application console.
//

#include "stdafx.h"
#include "windows.h"
#include <iostream>
#include <wincrypt.h>
using  std::cout;
  using  std::endl;
  using  std::cin;
#ifndef CALG_HMAC
#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
#endif

#ifndef CRYPT_IPSEC_HMAC_KEY
#define CRYPT_IPSEC_HMAC_KEY 0x00000100
#endif

#pragma comment(lib, "crypt32.lib")


char * HMAC(char * str, char * password, DWORD AlgId);


typedef struct _my_blob{
BLOBHEADER header;
DWORD len;
BYTE key[0];
}my_blob;

int _tmain(int argc, _TCHAR* argv[])
{
char * hash_sha1 = HMAC("ROSDEVIL", "password", CALG_SHA1);
char * hash_md5 = HMAC("ROSDEVIL", "password", CALG_MD5);

cout <<"Hash HMAC-SHA1: "<<hash_sha1<<" ( "<<strlen(hash_sha1)<<" )"<<endl;
cout <<"Hash HMAC-MD5: "<<hash_md5<<" ( "<<strlen(hash_md5)<<" )"<<endl;

cin.get();

return 0;
}
char * HMAC(char * str, char * password, DWORD AlgId = CALG_MD5){

HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHmacHash = 0;
BYTE * pbHash = 0;
DWORD dwDataLen = 0;
HMAC_INFO HmacInfo;

int err = 0;

ZeroMemory(&HmacInfo, sizeof(HmacInfo));

if (AlgId == CALG_MD5){
HmacInfo.HashAlgid = CALG_MD5;
pbHash = new BYTE[16];
dwDataLen = 16;
}else if(AlgId == CALG_SHA1){
HmacInfo.HashAlgid = CALG_SHA1;
pbHash = new BYTE[20];
dwDataLen = 20;
}else{
return 0;
}

ZeroMemory(pbHash, sizeof(dwDataLen));
char * res = new char[dwDataLen * 2];

my_blob * kb = NULL;
DWORD kbSize = sizeof(my_blob) + strlen(password);

kb = (my_blob*)malloc(kbSize);
kb->header.bType = PLAINTEXTKEYBLOB;
kb->header.bVersion = CUR_BLOB_VERSION;
kb->header.reserved = 0;
kb->header.aiKeyAlg = CALG_RC2;
memcpy(&kb->key, password, strlen(password));
kb->len = strlen(password);


if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)){
err = 1;
goto Exit;
}

if (!CryptImportKey(hProv, (BYTE*)kb, kbSize, 0, CRYPT_IPSEC_HMAC_KEY, &hKey)){
err = 1;
goto Exit;
}

if (!CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHmacHash)){
err = 1;
goto Exit;
}


if (!CryptSetHashParam(hHmacHash, HP_HMAC_INFO, (BYTE*)&HmacInfo, 0)){
err = 1;
goto Exit;
}

if (!CryptHashData(hHmacHash, (BYTE*)str, strlen(str), 0)){
err = 1;
goto Exit;
}

if (!CryptGetHashParam(hHmacHash, HP_HASHVAL, pbHash, &dwDataLen, 0)){
err = 1;
goto Exit;
}

ZeroMemory(res, dwDataLen * 2);
char * temp;
temp = new char[3];
ZeroMemory(temp, 3);
for (unsigned int m = 0; m < dwDataLen; m++){
sprintf(temp, "%2x", pbHash[m]);
if (temp [1] == ' ') temp [1] = '0'; // note these two: they are two CORRECTIONS to the conversion in HEX, sometimes the Zeros are
if (temp [0] == ' ') temp [0] = '0'; // printed with a space, so we replace spaces with zeros; (this error occurs mainly in HMAC-SHA1)
sprintf(res,"%s%s", res,temp);
}

delete [] temp;

Exit:
free(kb);
if(hHmacHash)
CryptDestroyHash(hHmacHash);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hProv)
CryptReleaseContext(hProv, 0);


if (err == 1){
delete [] res;
return "";
}

return res;
}
//Note: using HMAC-MD5 you could perform the famous CRAM-MD5 used to authenticate
//smtp servers.

The translate in asm (by cl) with the execute are in the attached zip
Best way is perhaps just rewrite it in masm with api call




Fa is a musical note to play with CL

ragdog

Yes i try it with api call

here is my stumpy code  :biggrin:

But is a first translate it work not i hope any can help me

my goal is use HmacMd5

The correct Hash is:bb41862dea18eaa6f1f426444a1382e6 or??




HMAC             PROTO :DWORD,:DWORD,:DWORD
HCRYPTPROV  TYPEDEF     DWORD
HCRYPTKEY   TYPEDEF     DWORD
HCRYPTHASH  TYPEDEF     DWORD
; structure for use with CryptSetHashParam with CALG_HMAC

HMAC_INFO STRUCT ;DEFALIGNMASM
HashAlgid DWORD ?
pbInnerString DWORD ?
cbInnerString DWORD ?
pbOuterString DWORD ?
cbOuterString DWORD ?
HMAC_INFO ENDS
BLOBHEADER STRUCT ;DEFALIGNMASM
bType BYTE ?
bVersion BYTE ?
reserved WORD ?
aiKeyAlg DWORD ?
BLOBHEADER ENDS
;typedef struct _my_blob{
; BLOBHEADER header;
; DWORD len;
; BYTE key[0];
; }my_blob;

_my_blob STRUCT
header BLOBHEADER <>
len DWORD ?
key dword ?;byte ?
_my_blob ends
.const

IDD_DIALOG   equ 1000
MS_ENHANCED_PROV equ <"Microsoft Enhanced Cryptographic Provider v1.0">
ALG_TYPE_BLOCK equ < 3 SHL 9>
ALG_CLASS_DATA_ENCRYPT equ < 3 SHL 13>
ALG_CLASS_HASH           equ    00008000h  ;(4 << 13)1000000000000000
CALG_MD5                 equ   ALG_CLASS_HASH OR ALG_TYPE_ANY OR ALG_SID_MD5
CALG_RC4 equ   ALG_CLASS_DATA_ENCRYPT OR ALG_TYPE_STREAM OR ALG_SID_RC4
CALG_RC2 equ < ALG_CLASS_DATA_ENCRYPT OR ALG_TYPE_BLOCK OR ALG_SID_RC2>
;#########################################################################
.data

.data?

hInstance   dd ?
HmacInfo           HMAC_INFO <>
kb  _my_blob <>

;HMAC("ROSDEVIL", "password", CALG_MD5);

invoke HMAC,chr$ ("ROSDEVIL"),chr$ ("password"),CALG_MD5

HMAC Proc pString:DWORD,pPassWord:DWORD,CALG_ID:DWORD
LOCAL hProv:HCRYPTPROV ;handle to the crypto provider
LOCAL hHash:HCRYPTHASH
LOCAL hKey:HCRYPTKEY
LOCAL hHmacHash:HCRYPTHASH
LOCAL pbHash [16]:BYTE
LOCAL dwDataLen:DWORD
LOCAL kbSize:DWORD


invoke RtlZeroMemory,addr HmacInfo, sizeof HmacInfo
mov HmacInfo.HashAlgid,CALG_MD5
mov dwDataLen,16

invoke RtlZeroMemory,addr pbHash, sizeof dwDataLen

;   kb->len = strlen(password);
mov kbSize,sizeof _my_blob +9

mov kb.header.bType,PLAINTEXTKEYBLOB
mov kb.header.bVersion, CUR_BLOB_VERSION
mov kb.header.reserved,0
mov kb.header.aiKeyAlg,CALG_RC2
mov eax,pPassWord
mov kb.key,eax
  invoke lstrlen,pString
mov kb.len,eax

invoke CryptAcquireContext,addr hProv, NULL, 0, PROV_RSA_FULL,CRYPT_VERIFYCONTEXT + CRYPT_NEWKEYSET
invoke CryptImportKey,hProv,  pPassWord, kbSize, 0, CRYPT_IPSEC_HMAC_KEY, addr hKey
invoke CryptCreateHash,hProv, CALG_HMAC, hKey, 0, addr hHmacHash
invoke CryptSetHashParam,hHmacHash, HP_HMAC_INFO, addr HmacInfo, 0
invoke lstrlen,pString
invoke CryptHashData,hHmacHash,  pString, eax, 0
invoke CryptGetHashParam,hHmacHash, HP_HASHVAL,addr pbHash,addr dwDataLen, 0

ret
HMAC endp

TouEnMasm


Here a verified soluce in asm

HMAC             PROTO :DWORD,:DWORD,:DWORD
HCRYPTPROV  TYPEDEF     DWORD
HCRYPTKEY   TYPEDEF     DWORD
HCRYPTHASH  TYPEDEF     DWORD
; structure for use with CryptSetHashParam with CALG_HMAC

my_blob STRUCT
header BLOBHEADER <>
len DWORD ?
key BYTE ?
my_blob ends
.const
RET_ON_FALSE MACRO
.if eax == FALSE
ret
.ENDIF
ENDM

IDD_DIALOG   equ 1000
MS_ENHANCED_PROV equ <"Microsoft Enhanced Cryptographic Provider v1.0">
ALG_TYPE_BLOCK equ < 3 SHL 9>
ALG_CLASS_DATA_ENCRYPT equ < 3 SHL 13>
ALG_CLASS_HASH           equ    00008000h  ;(4 << 13)1000000000000000
CALG_MD5                 equ   ALG_CLASS_HASH OR ALG_TYPE_ANY OR ALG_SID_MD5
CALG_RC4 equ   ALG_CLASS_DATA_ENCRYPT OR ALG_TYPE_STREAM OR ALG_SID_RC4
CALG_RC2 equ < ALG_CLASS_DATA_ENCRYPT OR ALG_TYPE_BLOCK OR ALG_SID_RC2>
;#########################################################################
.data
HmacInfo           HMAC_INFO <>
;kb  my_blob <>

;HMAC("ROSDEVIL", "password", CALG_MD5);
.code

HMAC Proc uses ebx pString:DWORD,pPassWord:DWORD,AlgId:DWORD
LOCAL hProv:HCRYPTPROV ;handle to the crypto provider
LOCAL hHash:HCRYPTHASH
LOCAL hKey:HCRYPTKEY
LOCAL hHmacHash:HCRYPTHASH
LOCAL pbHash:DWORD
LOCAL dwDataLen:DWORD
Local EncryptedBuffer[50h]:BYTE
LOCAL kbSize:DWORD
ZEROLOCALES kbSize

.if AlgId == CALG_MD5
mov HmacInfo.HashAlgid,CALG_MD5
mov dwDataLen,sizeof EncryptedBuffer  ;> 16
lea edx,EncryptedBuffer
mov pbHash,edx
.elseif AlgId == CALG_SHA1
mov HmacInfo.HashAlgid,CALG_SHA1
mov dwDataLen,sizeof EncryptedBuffer  ;> 20
lea edx,EncryptedBuffer
mov pbHash,edx
.else
mov eax,0
ret
.endif
;---------------------
mov kbSize,sizeof my_blob +9
invoke malloc,kbSize
mov ebx,eax
mov kb,eax
.LISTALL
mov [ebx].my_blob.header.bType,PLAINTEXTKEYBLOB
mov [ebx].my_blob.header.bVersion, CUR_BLOB_VERSION
.NOLIST
mov [ebx].my_blob.header.reserved,0
mov [ebx].my_blob.header.aiKeyAlg,CALG_RC2
lea edx,[ebx].my_blob.key
invoke lstrcpy,edx,pPassWord ;password is zero terminated,don't take care of lenght
invoke lstrlen,pPassWord
mov [ebx].my_blob.len,eax

invoke CryptAcquireContext,addr hProv, NULL, 0, PROV_RSA_FULL,CRYPT_VERIFYCONTEXT + CRYPT_NEWKEYSET
RET_ON_FALSE
invoke CryptImportKey,hProv,ebx, kbSize, 0, CRYPT_IPSEC_HMAC_KEY, addr hKey
RET_ON_FALSE
invoke CryptCreateHash,hProv, CALG_HMAC, hKey, 0, addr hHmacHash
RET_ON_FALSE
invoke CryptSetHashParam,hHmacHash, HP_HMAC_INFO, addr HmacInfo, 0
RET_ON_FALSE
invoke lstrlen,pString
invoke CryptHashData,hHmacHash,  pString, eax, 0
RET_ON_FALSE
invoke CryptGetHashParam,hHmacHash, HP_HASHVAL,pbHash,addr dwDataLen, 0
RET_ON_FALSE
mov edx,pbHash
mov ecx,dwDataLen
ret
HMAC endp

Fa is a musical note to play with CL

ragdog

Thanks it works with  MD5/SHA1

But i have try to use 3Des without good results

Is 3Des different?

Regards,

TouEnMasm


If it failed with various values,you need to know the use of the constants.
Here there is four constants:
CALG_SHA1,CALG_RC2,CALG_HMAC,HP_HMAC_INFO
Quote
invoke CryptSetHashParam,hHmacHash, HP_HMAC_INFO, addr HmacInfo, 0

CryptSetHashParam failed with the CALG_3DES perhaps the function need a HP_HASHVAL

Quote
HP_HMAC_INFO. A pointer to an HMAC_INFO structure that specifies the cryptographic hash algorithm and the inner and outer strings to be used.

HP_HASHVAL. A byte array that contains a hash value to place directly into the hash object. Before setting this value, the size of the hash value must be determined by using the CryptGetHashParam function to read the HP_HASHSIZE value.

Some cryptographic service providers (CSPs) do not support this capability

search in the internet seems a good soluce to find the good use for parameters.
Fa is a musical note to play with CL

ragdog

Hi

Here is a Hmac-Md5 algo i write this algo with the Rfc2104
This works without CSP (crypto apis)


key:Jefe
len:4
string:what do ya want for nothing?
len:28
HMAC-MD5:750c783e6ab0b503eaa86e310a5db738



Greets,