Hi,
I'm whacking my head off a wall here. I just can't see the error.
The following code seems to work, only half way through the hash result it apparently corrupts and produces incorrect data. I just can't see a reason for it. If you look carefully, the complete hash result is there, only in the middle of it there is junk. :eek I also have no idea why it is printing more data than it should.
This is simply a test piece for integration into a larger project (when it eventually works). Just build as a console .EXE.
include \masm32\include\masm32rt.inc
include \masm32\include\advapi32.inc
includelib \masm32\lib\advapi32.lib
.386
.model flat,stdcall
.data?
hCSP DWORD ?
hHash DWORD ?
HashParam DWORD ?
LastErr DWORD ?
.data
HashLen DWORD 0
CryptCreateHashResult DWORD 0
CryptHashDataResult DWORD 0
CryptHashParamResult DWORD 0
HashResult DWORD 8 dup (0)
XPProvider BYTE "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)",0
DataToHash BYTE "abc",0
HashResultOut BYTE 33 dup (0)
ASCIITable BYTE "0123456789abcdef",0
Hash BYTE "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",0
.code
start:
push 0
call SetLastError
;---------------------------------------------
; Get the CSP ready
push CRYPT_VERIFYCONTEXT
push PROV_RSA_AES
push 0 ; Use default provider
push 0
lea eax,hCSP
push eax
call CryptAcquireContext
call GetLastError
mov LastErr,eax
print "CryptAcquireContext: "
print str$(hCSP),13,10
print "GetLastError: "
print str$(LastErr),13,10,10
push 0
call SetLastError
;---------------------------------------------
; Create the hash object
lea eax, hHash
push eax
push 0
push 0
push 800Ch ; 800Ch is SHA-256 ; 8004h is CALG_SHA ; 8003 is CALG_MD5
push hCSP
call CryptCreateHash
mov CryptCreateHashResult,eax
call GetLastError
mov LastErr,eax
print "CryptCreateHash: "
print str$(CryptCreateHashResult),13,10
print "GetLastError: "
print str$(LastErr),13,10,10
push 0
call SetLastError
;---------------------------------------------
; Hash some data
push 0
push 3
push offset DataToHash
push hHash
call CryptHashData
mov CryptHashDataResult,eax
call GetLastError
mov LastErr,eax
print "CryptHashData: "
print str$(CryptHashDataResult),13,10
print "GetLastError: "
print str$(LastErr),13,10,10
push 0
call SetLastError
;---------------------------------------------
; Get the hash result
; 1) call to get the buffer length
push 0
lea eax,HashLen
push eax
push 0 ; Get buffer length, not the data
push 2 ; HP_HASHVAL
push hHash
call CryptGetHashParam
;--------------------------------------------
; Get the hash result
; 2) call to actually get the hash
push 0
lea eax,HashLen
push eax
lea eax,HashResult
push eax
push 2 ; HP_HASHVAL
push hHash
call CryptGetHashParam
mov CryptHashParamResult,eax
call GetLastError
mov LastErr,eax
print "CryptGetHashParam: "
print str$(CryptHashParamResult),13,10
print "GetLastError: "
print str$(LastErr),13,10,10
print "HashLen: "
print str$(HashLen),13,10,10
;---------------------------------------------
; Convert HashResult to ASCII
push 8
lea eax,HashResultOut
push eax
call dw2ascii
print "Hash check: "
print offset Hash,13,10
print "Hash Result "
print offset HashResultOut,13,10,10
push hHash
call CryptDestroyHash
push 0
push hCSP
call CryptReleaseContext
ret
;===========================================================
dw2ascii proc ptrAscBuf:DWORD,Count:DWORD
push ebx
push edi
mov edi,0
mov eax,HashResult+[edi*4]
mov ebx,ptrAscBuf
mov ecx,0
@@:
mov edx,eax
and edx,0Fh
mov edx,[offset ASCIITable+edx]
mov byte ptr [ebx+ecx+1],dl
ror eax,4
mov edx,eax
and edx,0Fh
mov edx,[offset ASCIITable+edx]
mov byte ptr [ebx+ecx],dl
ror eax,4
add ecx,2
cmp ecx,8
jne @B
xor ecx,ecx
add ebx,8
inc edi
mov eax,HashResult+[edi*4]
cmp edi,Count
jne @B
pop edi
pop ebx
ret 8
dw2ascii endp
end start
Best regards,
Robin.
dw2ascii proc uses esi edi pstr:DWORD, pstrlen:DWORD
mov eax, pstrlen
mov ecx, 2d
mul ecx
inc eax
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, eax
mov edi, eax
mov esi, pstr
push edi
WriteHex:
xor eax, eax
lodsb
invoke wsprintf, edi, CTXT('%02x'), eax
add edi, 2d
dec pstrlen
jnz WriteHex
pop eax
ret
dw2ascii endp
I have also heard CryptoAPI can be used for SSL communication, but i cannot find any working examples. If you have any good resources for the API please let me know. Specifically I am trying to use IMAP, but any example code or tutorials would be great. Language does not matter.
@six_L: thanks for the code. I'd like to know what is wrong with my code though. I can't understand two things:
1) Where the junk comes from
2) Why it produces more output than the byte buffer can hold.
HashResultOut BYTE 33 dup (0)
I should only be writing 32 bytes to the buffer. The 33rd byte should remain zero regardless of anything else.
@joemc: I suggest you start a new thread on that in the Campus forum. :)
Best regards,
Robin.
the wrong is in your "dw2ascii" codes.
there are a lot codes about how hex to strings, and better speeds.
if your "dw2ascii" codes modify a bit, then modify; if your "dw2ascii" codes modify a lot, then start new one.
change the thinking way, don't care about where are being the errors
OK - thanks!! :bg
Best regards,
Robin.
OK - I ran some tests on my code, and found something interesting - it is OK up to the 5th element of the DWORD array, but at the 6th element onwards it screws up.
Is there something more fundamental I'm missing that explains this behavior? The test code below works. If you increase the dwrd array to 6, uncomment the 6th mov dwrd... statement and set the count passed to dw2ascii to 6 it screws up. I can't see a good reason for this.
.386
.model flat,stdcall
option casemap:none
include \masm32\include\masm32rt.inc
.data
dwrd DWORD 5 dup (0)
ASCIITable BYTE "0123456789abcdef"
b BYTE 128 dup(0)
.code
start:
mov [dwrd],12345678h
mov [dwrd+4],87654321h
mov [dwrd+8],12345678h
mov [dwrd+12],87654321h
mov [dwrd+16],12345678h
;mov [dwrd+24],87654321h
;mov [dwrd+32],12345678h
;mov [dwrd+40],87654321h
push 5
lea eax,b
push eax
call dw2ascii
print offset b
xor eax,eax
ret
;==========================================================================
; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
dw2ascii proc ptrAscBuf:DWORD,Count:DWORD
push ebx
push edi
mov edi,0
mov eax,dwrd+[edi*4]
mov ebx,ptrAscBuf
mov ecx,0
@@:
mov edx,eax
and edx,0Fh
mov edx,[offset ASCIITable+edx]
mov byte ptr [ebx+ecx+1],dl
ror eax,4
mov edx,eax
and edx,0Fh
mov edx,[offset ASCIITable+edx]
mov byte ptr [ebx+ecx],dl
ror eax,4
add ecx,2
cmp ecx,8
jne @B
mov ecx,0
add ebx,8
inc edi
mov eax,dwrd+[edi*4]
cmp edi,Count
jne @B
pop edi
pop ebx
ret 8
dw2ascii endp
end start
Best regards,
Robin.
This gets stranger........
Run the code as-is. Note the pattern.
Now set the size of the dwrd array from 9 to 8, and re-build.
.386
.model flat,stdcall
option casemap:none
include \masm32\include\masm32rt.inc
.data
dwrd DWORD 9 dup (0)
ASCIITable BYTE "0123456789abcdef"
b BYTE 128 dup(0)
.code
start:
mov dwrd,11111111h
mov [dwrd+4],88888888h
mov [dwrd+8],11111111h
mov [dwrd+12],88888888h
mov [dwrd+16],11111111h
mov [dwrd+24],88888888h
mov [dwrd+32],11111111h
mov [dwrd+40],87654321h
push 8
lea eax,b
push eax
call dw2ascii
print offset b
xor eax,eax
ret
;==========================================================================
; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
dw2ascii proc ptrAscBuf:DWORD,Count:DWORD
push ebx
push edi
mov edi,0
mov eax,dwrd+[edi*4]
mov ebx,ptrAscBuf
mov ecx,0
@@:
mov edx,eax
and edx,0Fh
mov edx,[offset ASCIITable+edx]
mov byte ptr [ebx+ecx+1],dl
ror eax,4
mov edx,eax
and edx,0Fh
mov edx,[offset ASCIITable+edx]
mov byte ptr [ebx+ecx],dl
ror eax,4
add ecx,2
cmp ecx,8
jne @B
mov ecx,0
add ebx,8
inc edi
mov eax,dwrd+[edi*4]
cmp edi,Count
jne @B
pop edi
pop ebx
ret 8
dw2ascii endp
end start
:dazzled:
Hi,
After fixing a glaring bug in my test code (check the offsets in the mov instructions after start: to see them :red ), there isn't a problem with the dw2ascii code that I wrote. I can create a DWORD array of 50 elements and it converts it without issue.
The problem seems to lie with the result returned by CryptGetHashParam in that the complete hash is there, only in the middle of it is junk.
It appears the junk occurs in the same place each time, and is the same length.
The start of the byte array Hash is also apparently corrupted, printing correctly at the start, but being corrupted somewhere along the way.
I just can't see why it is doing what it is doing. The API appears that it allocates the memory, and merely passes a pointer to me to read it, then I have to clear it up afterwards (I know I've not done that yet in the code above).
* sigh *
Best regards,
Robin.
FOUND IT!!!!!! :cheekygreen:
EDIT: I can't count. :(
Best regards,
Robin.
:bg
Its usually referred to as "MacroShafted". We have all learnt the virtues of Microsoft documentation.
You might want to edit your post Hutch! :D
When I've converted it from binary to ASCII it requires twice as much space as the binary data. My ASCII buffer was not long enough. I hadn't appreciated I was taking 4 bytes from the hash and writing it into 8 bytes in the output buffer, doubling its length.
Best regards,
Robin.