PointyCastle / pointycastle

Moved into the Bouncy Castle project: https://github.com/bcgit/pc-dart
MIT License
270 stars 76 forks source link

Add an AES encryption and decryption example #111

Open stevenroose opened 7 years ago

stevenroose commented 6 years ago

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

stevenroose commented 5 years ago

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

Cretezy commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

@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 commented 5 years ago

It's solved thank you

SopheapSK commented 5 years ago

@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.

izaera commented 3 years ago

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