Page 2 of 2
Posted: Wed May 03, 2006 4:31 pm
by srod
Excellent. Nicely done.
Any problems with zero's in this one? That is, is it possible that one of the encrypted characters could be Chr(0) ?
Posted: Wed May 03, 2006 4:59 pm
by HeX0R
No problem with zero-bytes!
Posted: Wed May 03, 2006 5:17 pm
by srod
Perfect. Thank you for this.
Posted: Wed Aug 09, 2006 6:01 am
by Straker
@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.
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.s
Thanks in advance.
Posted: Fri Aug 18, 2006 11:33 am
by HeX0R
Sorry, i am very
stressed at the moment, so i didn't see your post earlier
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
Re: Windows: Encryption with password using the Windows API
Posted: Sat Aug 19, 2006 2:21 pm
by NoahPhense
Nice .. yeah rc4 is good, and modified rc4 is very tight. Especially when
you want it to be machine dependant.
- np
Posted: Mon Aug 21, 2006 8:16 pm
by Straker
Works great HeX0R! Thanks.
And congratulations.
Posted: Mon Feb 12, 2007 6:46 pm
by utopiomania
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?
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
Posted: Mon Feb 12, 2007 9:37 pm
by ABBKlaus
only a suggestion

, but base64Encoder/Decoder is not unicode compatible.
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 . . . . . . . .
Posted: Mon Feb 12, 2007 10:28 pm
by utopiomania
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:
Code: Select all
Encode: 14c4b06b824ec593239362517f538b29
Decode: 14c4b06b824ec593
So, we're half-way there

but I can't figure out where things go wrong.
Posted: Mon Feb 12, 2007 11:59 pm
by utopiomania
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.
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
Posted: Sat Feb 16, 2008 7:34 am
by Elias Montoya
I see this thread is not very old, so i might as well try.
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)
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?

Posted: Wed Sep 24, 2008 1:31 pm
by PB
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.