Any problems with zero's in this one? That is, is it possible that one of the encrypted characters could be Chr(0) ?
Windows: Encryption with password using the Windows API
No problem with zero-bytes!
{Home}.:|:.{Dialog Design0R}.:|:.{Codes}.:|:.{History Viewer Online}.:|:.{Send a Beer}
@HeXOR - Can you help me with this? I took your modified RC4 routine and am trying to convert it to Triple-DES. It seems to be working, but the decrypted string has trailing chars. Maybe this is due to it being a block cipher instead of a stream cipher. I'm stumped.
Thanks in advance.
Code: Select all
;Crypt-Constants
#PROV_RSA_FULL = 1
#ALG_SID_MD5 = 3
#ALG_SID_RC4 = 1
#ALG_SID_RC5 = 13
#ALG_CLASS_DATA_ENCRYPT = 3<<13 ;$6000
#ALG_CLASS_HASH = 4<<13 ;$8000
#ALG_TYPE_ANY = 0
#ALG_TYPE_STREAM = 4<<9
#CALG_MD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD5
#ALG_TYPE_BLOCK = 1536
#CRYPT_OAEP = $40
; Valid hashing algorithms:
;
; #ALG_SID_HMAC = 9
; #ALG_SID_MAC = 5
; #ALG_SID_MD2 = 1
; #ALG_SID_SHA = 4
; #ALG_SID_SHA1 = 4
; #ALG_SID_SSL3SHAMD5 = 8
; #CALG_HMAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_HMAC
; #CALG_MAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MAC
; #CALG_MD2 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD2
; #CALG_SHA = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA
; #CALG_SHA1 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA1
; #CALG_SSL3_SHAMD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SSL3SHAMD5
#CALG_RC4 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_STREAM|#ALG_SID_RC4
#CALG_RC5 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_RC5
#CRYPT_CREATE_SALT = 4
#CRYPT_EXPORTABLE = 1
#CRYPT_NEWKEYSET = 8
#MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
; added for Triple DES
#ALG_SID_3DES = 3
#CALG_3DES = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_3DES
#MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0"
Procedure.s EnCrypt(String$, Key$)
Protected *Buffer
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Len(String$)
PokeS(*Buffer, String$)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
;CryptDeriveKey_(hProv, #CALG_RC4, hHash, #CRYPT_EXPORTABLE, @hKey)
CryptDeriveKey_(hProv, #CALG_3DES, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptEncrypt_(hKey, 0, #True, #Null, *Buffer, @DataLength, Len(String$) * 2 + 64)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
result.s = Space(DataLength * 3)
Base64Encoder(*Buffer, DataLength, @result, DataLength * 3)
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure
Procedure.s Decrypt(String$, Key$)
Protected *Buffer
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Base64Decoder(@String$, Len(String$), *Buffer, Len(String$) * 2 + 64)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
CryptDeriveKey_(hProv, #CALG_3DES, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptDecrypt_(hKey, 0, #True, 0, *Buffer, @DataLength)
result.s = PeekS(*Buffer)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure
lStringToEncrypt.s = "macromedia"
lKey.s = "key"
Debug lStringToEncrypt.s
lEncrypted.s = EnCrypt(lStringToEncrypt.s,lKey.s)
Debug lEncrypted.s
lDeCrypted.s = Decrypt(lEncrypted.s,"key")
Debug lDeCrypted.sSorry, i am very stressed at the moment, so i didn't see your post earlier 
Just make use of the DataLength-Variable like this:
Just make use of the DataLength-Variable like this:
Code: Select all
;Crypt-Constants
#PROV_RSA_FULL = 1
#ALG_SID_MD5 = 3
#ALG_SID_RC4 = 1
#ALG_SID_RC5 = 13
#ALG_CLASS_DATA_ENCRYPT = 3<<13 ;$6000
#ALG_CLASS_HASH = 4<<13 ;$8000
#ALG_TYPE_ANY = 0
#ALG_TYPE_STREAM = 4<<9
#CALG_MD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD5
#ALG_TYPE_BLOCK = 1536
#CRYPT_OAEP = $40
; Valid hashing algorithms:
;
; #ALG_SID_HMAC = 9
; #ALG_SID_MAC = 5
; #ALG_SID_MD2 = 1
; #ALG_SID_SHA = 4
; #ALG_SID_SHA1 = 4
; #ALG_SID_SSL3SHAMD5 = 8
; #CALG_HMAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_HMAC
; #CALG_MAC = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MAC
; #CALG_MD2 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_MD2
; #CALG_SHA = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA
; #CALG_SHA1 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SHA1
; #CALG_SSL3_SHAMD5 = #ALG_CLASS_HASH|#ALG_TYPE_ANY|#ALG_SID_SSL3SHAMD5
#CALG_RC4 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_STREAM|#ALG_SID_RC4
#CALG_RC5 = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_RC5
#CRYPT_CREATE_SALT = 4
#CRYPT_EXPORTABLE = 1
#CRYPT_NEWKEYSET = 8
#MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
; added for Triple DES
#ALG_SID_3DES = 3
#CALG_3DES = #ALG_CLASS_DATA_ENCRYPT|#ALG_TYPE_BLOCK|#ALG_SID_3DES
#MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0"
Procedure.s EnCrypt(String$, Key$)
Protected *Buffer
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Len(String$)
PokeS(*Buffer, String$)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
;CryptDeriveKey_(hProv, #CALG_RC4, hHash, #CRYPT_EXPORTABLE, @hKey)
CryptDeriveKey_(hProv, #CALG_3DES, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptEncrypt_(hKey, 0, #True, #Null, *Buffer, @DataLength, Len(String$) * 2 + 64)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
result.s = Space(DataLength * 3)
Base64Encoder(*Buffer, DataLength, @result, DataLength * 3)
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure
Procedure.s Decrypt(String$, Key$)
Protected *Buffer
*Buffer = AllocateMemory(Len(String$) * 2 + 64)
DataLength.l = Base64Decoder(@String$, Len(String$), *Buffer, Len(String$) * 2 + 64)
If CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, 0) = 0
CryptAcquireContext_(@hProv, #Null, #MS_ENHANCED_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
EndIf
If hProv
CryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
If hHash
CryptHashData_(hHash, @Key$, Len(Key$), 0)
CryptDeriveKey_(hProv, #CALG_3DES, hHash, #CRYPT_EXPORTABLE, @hKey)
If hKey
If CryptDecrypt_(hKey, 0, #True, 0, *Buffer, @DataLength)
result.s = PeekS(*Buffer, DataLength)
EndIf
CryptDestroyKey_(hKey)
EndIf
CryptDestroyHash_(hHash)
EndIf
CryptReleaseContext_(hProv, 0)
EndIf
FreeMemory(*Buffer)
ProcedureReturn result
EndProcedure
lStringToEncrypt.s = "macromedia"
lKey.s = "key"
Debug lStringToEncrypt.s
lEncrypted.s = EnCrypt(lStringToEncrypt.s,lKey.s)
Debug lEncrypted.s
lDeCrypted.s = Decrypt(lEncrypted.s,lKey)
Debug lDeCrypted.s
{Home}.:|:.{Dialog Design0R}.:|:.{Codes}.:|:.{History Viewer Online}.:|:.{Send a Beer}
- NoahPhense
- Addict

- Posts: 1999
- Joined: Thu Oct 16, 2003 8:30 pm
- Location: North Florida
Re: Windows: Encryption with password using the Windows API
Nice .. yeah rc4 is good, and modified rc4 is very tight. Especially when
you want it to be machine dependant.
- np
you want it to be machine dependant.
- np
- utopiomania
- Addict

- Posts: 1655
- Joined: Tue May 10, 2005 10:00 pm
- Location: Norway
I'm using Hexor's modified RC4 sample below. The problem is, it fails if compiled to a unicode executable.
Have any of you managed to get them to work in both unicode and non-unicode executables?
Have any of you managed to get them to work in both unicode and non-unicode executables?
Code: Select all
#PROV_RSA_FULL = 1
#CRYPT_NEWKEYSET = 8
#CRYPT_EXPORTABLE = 1
#CALG_MD5 = 4 << 13 | 0 | 3
#CALG_RC4 = 3 << 13 | 4 << 9 | 1
#MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
procedure.s enCrypt(string.s, key.s)
protected *buffer
*buffer = allocateMemory(1024)
dataLength = len(string)
pokeS(*buffer, string)
if cryptAcquireContext_(@hProv, #NULL, #MS_DEF_PROV, #PROV_RSA_FULL, 0) = 0
cryptAcquireContext_(@hProv, #NULL, #MS_DEF_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
endIf
if hProv
cryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
if hHash
cryptHashData_(hHash, @key, len(key), 0)
cryptDeriveKey_(hProv, #CALG_RC4, hHash, #CRYPT_EXPORTABLE, @hKey)
if hKey
if cryptEncrypt_(hKey, 0, #TRUE, #NULL, *buffer, @dataLength, 1024)
endIf
cryptDestroyKey_(hKey)
endIf
cryptDestroyHash_(hHash)
endIf
cryptReleaseContext_(hProv, 0)
endIf
result.s = ""
for i = 0 to dataLength - 1
result + rset(hex(peekB(*buffer + i) & $FF), 2, "0")
next i
freeMemory(*buffer)
procedureReturn result
endProcedure
procedure.s decrypt(string.s, key.s)
protected *buffer
*buffer = allocateMemory(1024)
result.s = ""
o = 0
for i = 1 to len(string) step 2
hi = asc(mid(string, i, 1)) - 48
if hi > 9
hi - 7
endIf
lo = asc(mid(string, i + 1, 1)) - 48
if lo > 9
lo - 7
endIf
pokeB(*buffer + o, (hi * 16) + lo)
o + 1
next i
datalength = len(string) / 2
if cryptAcquireContext_(@hProv, #NULL, #MS_DEF_PROV, #PROV_RSA_FULL, 0) = 0
cryptAcquireContext_(@hProv, #NULL, #MS_DEF_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
endIf
if hProv
cryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
if hHash
cryptHashData_(hHash, @key, len(key), 0)
cryptDeriveKey_(hProv, #CALG_RC4, hHash, #CRYPT_EXPORTABLE, @hKey)
if hKey
if cryptDecrypt_(hKey, 0, #TRUE, 0, *buffer, @dataLength)
result = peekS(*buffer)
endIf
cryptDestroyKey_(hKey)
endIf
cryptDestroyHash_(hHash)
endIf
cryptReleaseContext_(hProv, 0)
endIf
freeMemory(*buffer)
procedureReturn result
endProcedure
e.s = "14c4b06b824ec593239362517f538b29"
d.s = encrypt(e, "abcd")
messageRequester("Result", "Encode: " + e + #CRLF$ + "Decode: " + decrypt(d, "abcd"))
end
Last edited by utopiomania on Mon Feb 12, 2007 10:21 pm, edited 1 time in total.
only a suggestion
, but base64Encoder/Decoder is not unicode compatible.
Memory Viewer shows this in unicode
Memory Viewer shows this in unicode
008947D0 74 4B 7A 63 73 58 34 54 4D 32 79 4E 6D 58 70 32 tKzcsX4TM2yNmXp2
008947E0 44 4A 63 44 31 4F 33 30 7A 4E 45 34 47 2B 32 45 DJcD1O30zNE4G+2E
008947F0 69 50 76 31 51 2F 48 42 46 71 67 3D 00 00 20 00 iPv1Q/HBFqg=.. .
00894800 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 . . . . . . . .
- utopiomania
- Addict

- Posts: 1655
- Joined: Tue May 10, 2005 10:00 pm
- Location: Norway
Seems from the helpfile that you're right. I've posted another above without the base64 stuff.
If compiled to unicode, it decrypts only half the string:
So, we're half-way there
but I can't figure out where things go wrong.
If compiled to unicode, it decrypts only half the string:
Code: Select all
Encode: 14c4b06b824ec593239362517f538b29
Decode: 14c4b06b824ec593
- utopiomania
- Addict

- Posts: 1655
- Joined: Tue May 10, 2005 10:00 pm
- Location: Norway
Maybe this is it. I went back to El-Chonis original post, and used a memory buffer instead of a string
to avoid problems with zeroes in the cipher string.
to avoid problems with zeroes in the cipher string.
Code: Select all
#PROV_RSA_FULL = 1
#CRYPT_NEWKEYSET = 8
#CRYPT_EXPORTABLE = 1
#CALG_MD5 = 4 << 13 | 0 | 3
#CALG_RC4 = 3 << 13 | 4 << 9 | 1
#MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
procedure encrypt(*mem, length, password$)
if cryptAcquireContext_(@hProv, #NULL, #NULL, #PROV_RSA_FULL, 0) = 0
cryptAcquireContext_(@hProv, #NULL, #NULL, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
endIf
cryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
cryptHashData_(hHash, password$, Len(password$), 0)
cryptDeriveKey_(hProv, #CALG_RC4, hHash, #CRYPT_EXPORTABLE, @hKey)
cryptEncrypt_(hKey, 0, #TRUE, #NULL, *mem, @length, length)
cryptDestroyKey_(hKey)
cryptDestroyHash_(hHash)
cryptReleaseContext_(hProv, 0)
endProcedure
procedure decrypt(*mem, length, password$)
if cryptAcquireContext_(@hProv, #NULL, #NULL, #PROV_RSA_FULL, 0) = 0
cryptAcquireContext_(@hProv, #NULL, #NULL, #PROV_RSA_FULL, #CRYPT_NEWKEYSET)
endIf
cryptCreateHash_(hProv, #CALG_MD5, 0, 0, @hHash)
cryptHashData_(hHash, password$, len(password$), 0)
cryptDeriveKey_(hProv, #CALG_RC4, hHash, #CRYPT_EXPORTABLE, @hKey)
cryptDecrypt_(hKey, 0, #TRUE, 0, *mem, @length)
cryptDestroyKey_(hKey)
cryptDestroyHash_(hHash)
cryptReleaseContext_(hProv, 0)
endProcedure
e.s = "1089338MSHMFSFSYUS3783264P973AS3M3R8YSN4RTR67NSZ187TS3T170SEMS3298YMYMAY31"
lim = len(e) * 2
*mem = allocateMemory(lim)
*ptr = *mem
copyMemoryString(@e, @*ptr)
debug peekS(*mem)
encrypt(*mem, lim, "abcd")
debug peekS(*mem)
debug str(peekC(*mem + 57)) + " at offset 57"
decrypt(*mem, lim, "abcd")
debug peekS(*mem)
end
-
Elias Montoya
- New User

- Posts: 8
- Joined: Tue May 08, 2007 9:31 pm
- Location: Mexico
I see this thread is not very old, so i might as well try.
im trying to port this pyton code to pb:
Complete reference in this link:
http://www.openrce.org/blog/view/449/MS ... scheme_REd
The part that is giving me problems is the "# Encrypt nonce with DES3 using key3 ". i think the DES3 code that hexor posted can be used. But where do i use the IV part??
Would you guys help me?
im trying to port this pyton code to pb:
Code: Select all
def mbi_encrypt(key, nonce):
def derive_key(key, magic):
hash1 = HMAC.new(key, magic, SHA).digest()
hash2 = HMAC.new(key, hash1 + magic, SHA).digest()
hash3 = HMAC.new(key, hash1, SHA).digest()
hash4 = HMAC.new(key, hash3 + magic, SHA).digest()
return hash2 + hash4[0:4]
#
# Read key and generate two derived keys
#
key1 = standard_b64decode(key)
key2 = derive_key(key1, "WS-SecureConversationSESSION KEY HASH")
key3 = derive_key(key1, "WS-SecureConversationSESSION KEY ENCRYPTION")
#
# Create a HMAC-SHA-1 hash of nonce using key2
#
hash = HMAC.new(key2, nonce, SHA).digest()
#
# Encrypt nonce with DES3 using key3
#
# IV: 8 bytes of random data
iv = randpool.KeyboardRandomPool().get_bytes(8)
obj = DES3.new(key3, DES3.MODE_CBC, iv)
# XXX: win32's Crypt API seems to pad the input with 0x08 bytes to align on 72/36/18/9 boundary
ciph = obj.encrypt(nonce + "\x08\x08\x08\x08\x08\x08\x08\x08")
#
# Generate the blob
#
blob = struct.pack("<LLLLLLL", 28, CRYPT_MODE_CBC, CALC_3DES, CALG_SHA1,
len(iv), len(hash), len(ciph))
blob += iv + hash + ciph
return standard_b64encode(blob)http://www.openrce.org/blog/view/449/MS ... scheme_REd
The part that is giving me problems is the "# Encrypt nonce with DES3 using key3 ". i think the DES3 code that hexor posted can be used. But where do i use the IV part??
Would you guys help me?
Just wanted to mention that this RC4 code using the Windows API is not
reliable between PCs. What it encodes on my home PC doesn't decode
on my work PC, making it useless for portability. Bear that in mind.
reliable between PCs. What it encodes on my home PC doesn't decode
on my work PC, making it useless for portability. Bear that in mind.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.



