Skip to content
This repository has been archived by the owner on Dec 23, 2020. It is now read-only.

Add an AES encryption and decryption example #111

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

stevenroose
Copy link
Member

No description provided.

Copy link

@Cretezy Cretezy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! I think this library definitely needs example of common use case, and this is a great start to that goal

example/aes.dart Outdated
void main() {
// Key must be multiple of block size (16 bytes).
var key = new Digest("SHA-256").process(
UTF8.encode("correct horse battery staple"));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use new utf8 (lowercase). I would also highly recommend to set any non-reassigned values (like this one) as final instead, which is generally considered a good practice.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, since we're now in the Dart 2 age, I would remove all instances of new.

encryptionCipher.init(true, params);
Uint8List encrypted = encryptionCipher.process(UTF8.encode(message));

print("Encrypted: \n" + HEX.encode(encrypted));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lower cased hex.

example/aes.dart Outdated

BlockCipher decryptionCipher = new PaddedBlockCipher("AES/CBC/PKCS7");
decryptionCipher.init(false, params);
String decrypted = UTF8.decode(decryptionCipher.process(encrypted));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utf8 again

import "dart:convert";
import "dart:typed_data";

import "package:hex/hex.dart";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need, use standard library (included in dart:convert).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -16,6 +16,7 @@ dependencies:
dev_dependencies:
benchmark_harness: ">=1.0.4 <2.0.0"
browser: ">=0.9.0 <0.10.0"
hex: ">=0.1.1 <1.0.0"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use stdlib.

@stevenroose
Copy link
Member Author

If you want, I'd accept a PR from you with the suggested changes :)

@stevenroose
Copy link
Member Author

If someone could review the example, that would be appreciated!

@Cretezy
Copy link

Cretezy commented Oct 4, 2018

I'll take a good look and fix/add to it when I have time! I have yet to upgrade to the newer version of the registry (was using the "take 1" re-implementation).

@hoboris
Copy link

hoboris commented Oct 23, 2018

Apologies for hijacking this pull request. I used your example code to encrypt a message with aes 256 and md5

// Key must be multiple of block size (16 bytes).
    var key = new Digest("MD5").process(
        utf8.encode("correcthorsebatterystaple"));
    // Can be anything.
    var message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed d o eiusmod tempor incididunt ut labore et dolore magna aliqua.";
    // The initialization vector must be unique for every message, so it is a
    // good idea to use a message digest as the IV.
    // IV must be equal to block size (16 bytes).
    var iv = new Digest("MD5").process(utf8.encode(message)).sublist(0, 16);
    // The parameters your cipher will need. (PKCS7 does not need params.)
    CipherParameters params = new PaddedBlockCipherParameters(
        new ParametersWithIV(new KeyParameter(key), iv), null);
    print("Message: \n$message");
    ////////////////
    // Encrypting //
    ////////////////
    // As for why you would need CBC mode and PKCS7 padding, consult the internet
    // (f.e. http://www.di-mgt.com.au/properpassword.html).
    BlockCipher encryptionCipher = new PaddedBlockCipher("AES/CBC/PKCS7");
    encryptionCipher.init(true, params);
    Uint8List encrypted = encryptionCipher.process(utf8.encode(message));
    print("Encrypted: \n" + HEX.encode(encrypted));

It does decrypt well with your decryption method. But I tried to decrypt it with openssl with

echo "$encrypted" | openssl enc -d -aes-256-cbc -k $key -a -md md5
encrypted being the hexa encrypted message

But I get a bad magic number error. Am I mising something ?

@stevenroose
Copy link
Member Author

I have no idea, tbh. Did that command work with an openssl encrypted message? (f.e. echo adds a newline, not sure if that could break things -- try printf)

It's quite possible that there is an issue with our implementation that we're not aware off. Did you try decrypting with BouncyCastle, f.e.?

@hoboris
Copy link

hoboris commented Oct 29, 2018

I have just tried with javax.crypto library and it is the same, so it must be something else I haven't figured out yet, but the problem does not lie with with PointyCastle or your example.

@guoyuanzhuang
Copy link

@Cretezy AES result is different with Java.
`public class AESUtil {

private static String AES_ALGORITHM = "AES/ECB/PKCS5Padding";
private static String CHAR_ENCODING = "UTF-8";

public static byte[] encrypt(byte[] data, byte[] key) {
	try {
		SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
		cipher.init(Cipher.ENCRYPT_MODE, seckey);
		byte[] result = cipher.doFinal(data);
		return result; // 加密
	} catch (Exception e) {
		e.printStackTrace();
	}
	return null;
}

public static byte[] decrypt(byte[] data, byte[] key) {
	try {
		SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, seckey);
		byte[] result = cipher.doFinal(data);
		return result; // 加密
	} catch (Exception e) {
		e.printStackTrace();
	}
	return null;
}

public static String encrypt(String data, String key) {
	try {
		byte[] valueByte = encrypt(data.getBytes(CHAR_ENCODING),
				key.getBytes(CHAR_ENCODING));
		return new String(Base64.encode(valueByte, Base64.DEFAULT));
	} catch (Exception e) {
		e.printStackTrace();
	}
	return null;
}

public static String decrypt(String data, String key) {
	try {
		byte[] originalData = Base64.decode(data.getBytes(), Base64.DEFAULT);
		byte[] valueByte = decrypt(originalData,
				key.getBytes(CHAR_ENCODING));
		return new String(valueByte, CHAR_ENCODING);
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	}
	return null;
}

public static String parseByte2HexStr(byte buf[]) {
	StringBuffer sb = new StringBuffer();
	for (int i = 0; i < buf.length; i++) {
		String hex = Integer.toHexString(buf[i] & 0xFF);
		if (hex.length() == 1) {
			hex = '0' + hex;
		}
		sb.append(hex.toUpperCase());
	}
	return sb.toString();
}

}
`
What went wrong? thank you

@guoyuanzhuang
Copy link

It's solved
thank you

@SopheapSK
Copy link

@Cretezy AES result is different with Java.
`public class AESUtil {

private static String AES_ALGORITHM = "AES/ECB/PKCS5Padding";
private static String CHAR_ENCODING = "UTF-8";

public static byte[] encrypt(byte[] data, byte[] key) {
	try {
		SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
		cipher.init(Cipher.ENCRYPT_MODE, seckey);
		byte[] result = cipher.doFinal(data);
		return result; // 加密
	} catch (Exception e) {
		e.printStackTrace();
	}
	return null;
}

public static byte[] decrypt(byte[] data, byte[] key) {
	try {
		SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, seckey);
		byte[] result = cipher.doFinal(data);
		return result; // 加密
	} catch (Exception e) {
		e.printStackTrace();
	}
	return null;
}

public static String encrypt(String data, String key) {
	try {
		byte[] valueByte = encrypt(data.getBytes(CHAR_ENCODING),
				key.getBytes(CHAR_ENCODING));
		return new String(Base64.encode(valueByte, Base64.DEFAULT));
	} catch (Exception e) {
		e.printStackTrace();
	}
	return null;
}

public static String decrypt(String data, String key) {
	try {
		byte[] originalData = Base64.decode(data.getBytes(), Base64.DEFAULT);
		byte[] valueByte = decrypt(originalData,
				key.getBytes(CHAR_ENCODING));
		return new String(valueByte, CHAR_ENCODING);
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	}
	return null;
}

public static String parseByte2HexStr(byte buf[]) {
	StringBuffer sb = new StringBuffer();
	for (int i = 0; i < buf.length; i++) {
		String hex = Integer.toHexString(buf[i] & 0xFF);
		if (hex.length() == 1) {
			hex = '0' + hex;
		}
		sb.append(hex.toUpperCase());
	}
	return sb.toString();
}

}
`
What went wrong? thank you

my code in java is exactly the same as yours. but I still cannot find the way to configure code in dart to work as java yet. the result is different.

// The initialization vector must be unique for every message, so it is a
// good idea to use a message digest as the IV.
// IV must be equal to block size (16 bytes).
var iv = new Digest("SHA-256").process(utf8.encode(message)).sublist(0, 16);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking the hash of the plaintext for the IV might not be a good idea, as it leaks information about the plaintext. If the text is encrypted twice the IV will be the same. Might be better to use a PRNG.

@izaera
Copy link
Member

izaera commented Dec 23, 2020

I'm archiving this repo as per #239 (see the issue for more info).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants