Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[AHK_L] Crypt - ahk cryptography class (Encryption, Hashing)


  • Please log in to reply
83 replies to this topic
muriloq
  • Members
  • 6 posts
  • Last active: Jun 17 2011 12:11 PM
  • Joined: 14 Jun 2011
Deo

Indeed I was testing using the old version, thanks for the tip. :-)

But there's still a problem, the output is very different from aespipe. .. Then by trial and error I changed the line

if !dllCall("Advapi32\CryptHashData","Ptr",hHash,"Ptr",&passBuf,"Uint",passLen,"Uint",0 )

to (notice the passLen-1 part)

if !dllCall("Advapi32\CryptHashData","Ptr",hHash,"Ptr",&passBuf,"Uint",passLen-1,"Uint",0 )

And now, for my surpise the first block (the first 16 bytes) match exactly the output of aespipe, but the next one doesn't!

If the input is less than 16-bytes aespipe produces an encrypted message of 16 bytes, but Crypt.ahk output has 32 bytes. The first 16 bytes are the same produced by aespipe.


Any suggestions?

Thanks a lot again.

Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
really it seems like aespipe do not consider a null character of the password string

what if you pass a data with lenght about 60 bytes? Can we expect an aespipe result in 64 bytes and crypt in 80? Will the first 64 bytes be identical in this case?

it would be nice if you can post here a few examples of aespipe encryption results (as hash) with all parameters, so i could investigate it more

muriloq
  • Members
  • 6 posts
  • Last active: Jun 17 2011 12:11 PM
  • Joined: 14 Jun 2011
A few examples using aespipe and Java Cryptography API:

The input always use:

Encoding=UTF-8
Plain Text=abcdefghijklmnop ( 3031323334353637383930313233343536373839 )
Password=01234567890123456789 ( 6162636465666768696A6B6C6D6E6F70 )

aespipe -e aes -H sha256 -P p < m | hexdump -v -e '/1 "%02X "'
111A883229F29D02576763850D4620C1

Java (algorithm="AES", key size 128 bit, message digest="SHA-256"):
111A883229F29D02576763850D4620C1B188E0E482B593F71A565F7DBB752AE1

Patched Crypt.ahk ( passLen - 1):
111A883229F29D02576763850D4620C1BE32EB5C190D19964AF87EA3D6F4C1B23

Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
ok, here what i found
a few differences between aespipe and MS enryption algorithm makes them incompatible, unfortunately

- aespipe always adds nulls to the data so it could be a multiple of 16 bytes blocks,
this way a hashes like
6162636465666768696A6B6C60000000    (16 bytes)
6162636465666768696A6B6C6000 		(14 bytes)
6162636465666768696A6B6C60			(13 bytes)
will always produce same result through aespipe and always different through MS AES

- in case when data lenght is equal to block size of cipher, aespipe adds nothing when MS AES adds one additional block

If the key is a block cipher key, the data is padded to a multiple of the block size of the cipher. If the data length equals the block size of the cipher, one additional block of padding is appended to the data.
<!-- m -->http://msdn.microsof...ry ... 85).aspx<!-- m -->

Thats why string "abcdefghijklmnop" produces one block from aespipe and two blocks from MS AES
And this is also a case why first block of data is identical in this hashes
111A883229F29D02576763850D4620C1 
111A883229F29D02576763850D4620C1 EDBF6D5CADC9FB30FB096F0505A43EA4 (second block is some mystical data RSA AES adding to the actual string)

i don't see a way to decrypt aespipe encrypted string using MS AES
But, you definetly can decrypt MS AES encrypted string using aespipe, if you will pad any data passed to MS encryption algorithm with nulls so it's len could be a multiple of cipher block size. Then, after encryption done, you need to cut the last 16 bytes block and it will be the actual hash for aespipe

muriloq
  • Members
  • 6 posts
  • Last active: Jun 17 2011 12:11 PM
  • Joined: 14 Jun 2011
That's very interesting, thank you!

What about the Java implementation? It produces a two-block output, as the MS version, but the second block is different... I think it's caused by different padding, right?

What if I pad the byte array before submitting it to the encryption algorithm? Do you think it will work?

Another point, specific to Crypt.ak: when using RC4/MD5 the output by Crypt.ahk does NOT has the same length of the input. Since RC4 isn't a block cipher it seems to be an error, right? If I use passLen-1 and discard the last byte the output match with the one from the Java version.

Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
strange, RC4 works fine for me, always same input and output len
which string/password do you use?
here is example
str:= "abcdefghijkl"
pass := "01234567890123456789"
AE84EAEFCDE3D4ABE9AE89BA with RC4/MD5

i'm not sure about java crypting, it may do encryption in a bit different way than MS, where can i get it to test?,

muriloq
  • Members
  • 6 posts
  • Last active: Jun 17 2011 12:11 PM
  • Joined: 14 Jun 2011
About RC4/MD5:

we use MD5 to hash the password, then RC4 to compress the message. The encrypted message must have the same length of the original message.

Calling Crypt.Encrypt.StrEncrypt("MS","007",1,1)

Should returns two bytes ( 71CF ), not three...

About using Java:

Below you will find the source code for the Java version.

Save it as Crypt.java, compile with javac Crypt.java, then run with java Crypt . You'need the Java Development Kit (JDK) from http://www.oracle.co...oads/index.html

If you change "SHA-256" to "MD5" and "AES" to "RC4" you can test this method, too.

import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;


public class Crypt {

	public static void main(String[] args) throws Exception{
		String hash = "SHA-256";
		String algorithm = "AES";
		
		String inputStr = "abcdefghijklmnop";
		String keyStr = "01234567890123456789";
		
		byte[] input = inputStr.getBytes("UTF-8");
		byte[] key = keyStr.getBytes("UTF-8");

		
		key = MessageDigest.getInstance(hash).digest(key); 
		key = Arrays.copyOf(key, 16); // use only first 128 bit
		
		SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
		Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.ENCRYPT_MODE, keySpec);
		byte[] output = cipher.doFinal(input);
		
		cipher.init(Cipher.DECRYPT_MODE, keySpec);
		byte[] decoded = cipher.doFinal(output);
		String decodedStr = new String(decoded,"UTF-8");
		
		System.out.println("Input "+inputStr+" "+DatatypeConverter.printHexBinary(input));
		System.out.println("Key "+keyStr+" "+DatatypeConverter.printHexBinary(key));
		System.out.println("Output "+DatatypeConverter.printHexBinary(output));
		System.out.println("Decoded "+decodedStr+" "+DatatypeConverter.printHexBinary(decoded));

	}
}


Thanks!

Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
oh yeah, again we forgot about null character, thats why returned string len is one byte longer
you can remove it by specifying
len := StrPutVar(string, str_buf,100,this.StrEncoding)[color=red]-1[/color]
or "-2" for UTF-16, but in case block cipher like aes it may not decrypt returned hash properly then (will add some trash at the end)

thank you for java crypt lib, i'll check it on this weekend

art
  • Members
  • 57 posts
  • Last active: Mar 11 2019 07:48 AM
  • Joined: 23 Sep 2008
Hi Deo and thanks for this Cryptography API.

Can you please provide two more functions like:
* EncryptedHash := Crypt.Encrypt.FileEncryptToStr(pFileIn,password,CryptAlg = 1, HashAlg = 1)
* Crypt.Encrypt.StrDecryptToFile(EncryptedHash,pFileOut,password,CryptAlg = 1, HashAlg = 1)

I'm trying to write a script that will Encrypt a binary file and save it's EncryptedHash as a value to an .ini (or .xml) file.
Later, it will read the EncryptedHash from the .ini (or .xml) file, Decrypt it and create the original file.

Thanks

Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
ok, added, here is example of usage:
pass := "somepass"
cv := FileOPen("res.txt","w","CP0")
cv.Write(Crypt.Encrypt.FileEncryptToStr("WinError.h",pass,7, 6))
cv.close()

cv := FileOPen("res.txt","r","CP0")
hash := cv.Read()
Crypt.Encrypt.StrDecryptToFile(hash,"WinError2.h",pass,7, 6)
hash =
cv.close()
use it carefully though because hash of file is always twice as large than file itself, do not forget to free unused variables, etc..

art
  • Members
  • 57 posts
  • Last active: Mar 11 2019 07:48 AM
  • Joined: 23 Sep 2008
thank you Deo for the two new functions, i'll check them on this weekend.

Qriist
  • Members
  • 11 posts
  • Last active: Dec 30 2011 01:28 PM
  • Joined: 28 Jun 2009
Gentle reminder of my request for CRC32 support. :)

daveerickson
  • Members
  • 1 posts
  • Last active: Aug 09 2013 07:37 PM
  • Joined: 12 Aug 2011
I must really be missing something up here...

When I try to include Crpyt.ahk in any of my files I get a message stating:

Error at line 147 in #include file: "C:\path\to\my\file.ahk".

Line Text: var StrEncoding := "UTF-16"
Error: Expected assignment or class/method definition.

The program will exit.

Any ideas?

sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008

I must really be missing something up here...


No, I'm pretty sure you just downloaded the latest version of AHK_L, in which the var prefix is no longer allowed inside of classes:

[color=red]var[/color] StrEncoding := "UTF-16"

I believe if you change those instances from var to static it should work fine.

yourbuddypal
  • Members
  • 32 posts
  • Last active: May 17 2013 06:50 AM
  • Joined: 29 Jun 2009

I must really be missing something up here...


No, I'm pretty sure you just downloaded the latest version of AHK_L, in which the var prefix is no longer allowed inside of classes:

[color=red]var[/color] StrEncoding := "UTF-16"

I believe if you change those instances from var to static it should work fine.


I had this same problem too after reformatting. I changed 4 variables to static and it works! thanks.