【问题标题】:Java AES-256 Decryption - translating code from ActionScript 3Java AES-256 解密 - 从 ActionScript 3 转换代码
【发布时间】:2012-10-15 14:01:03
【问题描述】:

我在 ActionScript 3 中有一个有效的解密,现在我想在 Java 中解密时得到相同的结果。 (我知道 OFB 模式和 NullPadding 可能不是首选,但那是我当时使用的,也是我现在需要解密的……)

(非常旧的)Adobe ActionScript 3 代码:

static public function decryptTest(): Boolean {
    var iv: String = "0df1eff724d50157ab048d9ff214b73c";
    var cryptext: String = "2743be20314cdc768065b794904a0724e64e339ea6b4f13c510e2d2e8c95dd7409aa0aefd20daae80956dd2978c98d6e914d1d7b5b5be47b491d91e7e4f16f7f30d991ba80a81bafd8f0d7d83755ba0ca66d6b208424529c7111bc9cd6d11786f3f604a0715f";
    var kkey: String = "375f22c03371803ca6d36ec42ae1f97541961f7359cf5611bbed399b42c7c0be";

    var kdata: ByteArray = Hex.toArray(kkey);
    var data: ByteArray = Hex.toArray(cryptext);
    var name: String = 'aes-256-ofb';
    var pad:IPad = new NullPad();
    var mode: ICipher = Crypto.getCipher(name, kdata, pad);
    pad.setBlockSize(mode.getBlockSize());
    trace("mode block size: " + mode.getBlockSize());

    if (mode is IVMode) {
        var ivmode:IVMode = mode as IVMode;
        ivmode.IV = Hex.toArray(iv);
    }
    mode.decrypt(data);

    var res: String = data.toString();
    trace("result: " + res);

    return res == "01020506080b10131c22292d313536393b464c535466696d6e7d7f808a8e9899a2adb1b8babcbebfc1c6c7c8cecfd8e0e4e8ef";
}

trace("decryption test: " + netplay.decryptTest());

Flash 输出为:

mode block size: 16
result: 01020506080b10131c22292d313536393b464c535466696d6e7d7f808a8e9899a2adb1b8babcbebfc1c6c7c8cecfd8e0e4e8ef
decryption test: true

我尝试了什么?

我在 Java 中尝试了两种不同的方法,一种使用内置的 Cipher 类,另一种使用 this code/class。但是,第一种方法给了我一个 IllegalKeyException ,而另一种方法给了我垃圾。另外,第二种方法没有明确指定如何输入 IV 数据进行解密,也没有让我指定 OFB 模式或填充。

java.security.InvalidKeyException: Illegal key size
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1023)
    at javax.crypto.Cipher.implInit(Cipher.java:789)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:848)
    at javax.crypto.Cipher.init(Cipher.java:1347)
    at javax.crypto.Cipher.init(Cipher.java:1281)
    at test.net.zomis.ZomisTest.decryptCipher(ZomisTest.java:112)
@Test
public void decryptCipher() throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
    String iv = "0df1eff724d50157ab048d9ff214b73c";
    String cryptext = "2743be20314cdc768065b794904a0724e64e339ea6b4f13c510e2d2e8c95dd7409aa0aefd20daae80956dd2978c98d6e914d1d7b5b5be47b491d91e7e4f16f7f30d991ba80a81bafd8f0d7d83755ba0ca66d6b208424529c7111bc9cd6d11786f3f604a0715f";
    String key = "375f22c03371803ca6d36ec42ae1f97541961f7359cf5611bbed399b42c7c0be"; // Hexadecimal String, will be converted to non-hexadecimal String
    String expectedResult = "01020506080b10131c22292d313536393b464c535466696d6e7d7f808a8e9899a2adb1b8babcbebfc1c6c7c8cecfd8e0e4e8ef";

    byte[] kdata = Util.hex2byte(key);

    Assert.assertEquals(32, kdata.length); // 32 bytes = 256-bit key

    String result;

    Cipher cipher;
    cipher = Cipher.getInstance("AES/OFB/NoPadding");
    // Below line is 112, which is causing exception
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kdata, "AES"), new IvParameterSpec(iv.getBytes("UTF-8")));
    byte[] cryptData = Util.hex2byte(cryptext);
    byte[] ciphertext = cipher.doFinal(cryptData);
    result = new String(ciphertext);


    Assert.assertEquals(expectedResult, result);
}

@Test
public void decryptAES() {
    String iv = "0df1eff724d50157ab048d9ff214b73c"; 
    // Problem: Where should I specify the IV ???? Currently it is an unused variable...

    String cryptext = "2743be20314cdc768065b794904a0724e64e339ea6b4f13c510e2d2e8c95dd7409aa0aefd20daae80956dd2978c98d6e914d1d7b5b5be47b491d91e7e4f16f7f30d991ba80a81bafd8f0d7d83755ba0ca66d6b208424529c7111bc9cd6d11786f3f604a0715f";
    String key = "375f22c03371803ca6d36ec42ae1f97541961f7359cf5611bbed399b42c7c0be"; // Hexadecimal String, will be converted to non-hexadecimal String
    String expectedResult = "01020506080b10131c22292d313536393b464c535466696d6e7d7f808a8e9899a2adb1b8babcbebfc1c6c7c8cecfd8e0e4e8ef";

    Assert.assertEquals(64, key.length());

    AES aes = new AES();
    aes.setKey(Util.hex2byte(key));
    byte[] byteCryptedData = Util.hex2byte(cryptext);
    String byteCryptedString = new String(byteCryptedData);

    while (byteCryptedString.length() % 16 != 0) byteCryptedString += " ";


    String result = aes.Decrypt(byteCryptedString);
    Assert.assertEquals(expectedResult, result); // Assertion Failed
}

问题: 如何以与 ActionScript 3 相同的方式使 Java 解密?当然,我希望两者都得到相同的结果。

【问题讨论】:

  • 一个小错误new IvParameterSpec(iv.getBytes("UTF-8")) 应该是new IvParameterSpec(Util.hex2byte(iv));Illegal key size 仍然是她。

标签: java actionscript-3 encryption aes rijndael


【解决方案1】:

第一种方法是给您一个Illegal key size 错误消息,因为您没有安装不受限制的策略文件。如果没有这些,Java 将拒绝使用“强”密钥长度(例如 256 位 AES)。

如果在您的管辖范围内这样做是合法的,请在 Google 上搜索“Unlimited Strength Jurisdiction Policy Files”并下载适用于您的 Java 安装的版本。您最终将有两个文件转储到 JRE 中的 lib/security

【讨论】:

  • 如果我想将我的 JAR 文件部署给其他人,我能否以某种方式将我的 JAR 与策略文件一起部署,或者所有想要运行我的 JAR 文件的计算机也需要下载并安装策略文件?
  • 真的,每个人都应该自己做。使用这种密码学强度不一定在所有国家都是合法的。我建议您捕获异常并向用户呈现令人愉快的消息(甚至包括下载链接)。
  • 只需检查“无限强度管辖政策”并通过第一次测试。
  • 是的,这个作品。将来我将同时更改 AS3 和 Java 加密以使其更容易。也许 256 位 AES 加密有点矫枉过正。
【解决方案2】:

是的,有这样的库,看看 http://www.bouncycastle.org/ 。这个更具体一点Java Bouncy Castle Cryptography - Encrypt with AES

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-30
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 2022-10-16
    • 2023-03-18
    • 1970-01-01
    相关资源
    最近更新 更多