Java AES 256 CBC 模式无法正常工作

标签 java aes cbc-mode

这是在 ECB 和 CBC 中执行 AES 的 ruby​​ 代码:


require 'openssl'
require 'base64'
def encrypt(data, key, cipher_type)
  aes = OpenSSL::Cipher::Cipher.new(cipher_type)
  key = key.ljust(32, "\0")
  aes.encrypt
  aes.key = key
  Base64.encode64(aes.update(data) + aes.final).tr("\n","")
end


puts encrypt("XJ5QJSVMKZGBOQO7HMSIJO5BERW2OYWDVNPM3BH32NLSWUCNJ4FIP3BML7EKUBNO", "000000", 'AES-256-ECB')
puts encrypt("XJ5QJSVMKZGBOQO7HMSIJO5BERW2OYWDVNPM3BH32NLSWUCNJ4FIP3BML7EKUBNO", "000000", 'AES-256-CBC')

这是 Java 等价物:


import org.apache.commons.codec.binary.Base64;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class AESTest 
{ 
    public static void main(String [] args)
    {
        System.out.println(AESEncryptToBase64("AES/ECB/PKCS5padding", "000000", "XJ5QJSVMKZGBOQO7HMSIJO5BERW2OYWDVNPM3BH32NLSWUCNJ4FIP3BML7EKUBNO"));
        System.out.println(AESEncryptToBase64("AES/CBC/PKCS5padding", "000000", "XJ5QJSVMKZGBOQO7HMSIJO5BERW2OYWDVNPM3BH32NLSWUCNJ4FIP3BML7EKUBNO"));
    }

    /**
     * 
     * @param secret
     * @param cleartext
     * @return encrypted b64 string
     */
    public static String AESEncryptToBase64(String cypher, String secret, String clearText) {
        byte[] rawKey = new byte[32];
        java.util.Arrays.fill(rawKey, (byte) 0);
        byte[] secretBytes = secret.getBytes();
        for(int i = 0; i < secretBytes.length; i++){
            rawKey[i] = secretBytes[i];
        }

        SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
        try{ 
            Cipher cipher = Cipher.getInstance(cypher);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encryptedData = cipher.doFinal(clearText.getBytes());
            if(encryptedData == null) return null;
            // return "l";
            return Base64.encodeBase64String(encryptedData);
        } catch (Exception e){
            e.printStackTrace();
        }
        return null;      

    }
}

编译:commons jar:http://apache.mirrors.pair.com//commons/codec/binaries/commons-codec-1.7-bin.zip


 $ javac -cp .:commons-codec-1.7.jar AESTest.java 

运行


$ ruby aestest.rb 
hYnClaUD9brJfNpEp4YDH0l1Y/QBlGkclnVN8MObNZFsvykd2da8iT2pcwLftNfox1HK/KFWrdfXt0qhP0Aq/fudP1FPIhF3vUTOEDzJbiY=
hYnClaUD9brJfNpEp4YDH5xcdKI4W5soPmWMpU+NikmAEKGSZkDP3KaJVSqRyOHt3JlcoyQzPbuoHxPV6kw6GH/4atDrcmCwV5LacTp+mBg=

$ java -cp .:commons-codec-1.7.jar AESTest
hYnClaUD9brJfNpEp4YDH0l1Y/QBlGkclnVN8MObNZFsvykd2da8iT2pcwLftNfox1HK/KFWrdfXt0qhP0Aq/fudP1FPIhF3vUTOEDzJbiY=
kZZNkbxis/W9UtEgRkxakGH28QetvK4lbf/SxBLrNDYPkGnf3w4MwonOCsoi9FjLAQ34aElOJ3KUjm62fiYLWxwNiE/wls7AcQnXLD19ano=

请注意,ECB 模式对两者都适用。但CBC模式不同。我也在 C 上运行了它,结果证明 Ruby 是正确的,Java 不是。

我在 Java 中做错了什么?

最佳答案

对于CBC你需要提供一个初始化 vector ,例如:

cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));

在你的代码中有一个 if 语句和两个不同的初始化。欧洲央行的那个很好,这个不适用于欧洲央行。

关于Java AES 256 CBC 模式无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13767150/

相关文章:

java - 我可以在不同的 jre 实现中使用 java keytool 生成的 keystore 吗

c# - 在哪里存储 AES key ?

flutter - Dart中解密AES/CBC/PKCS5Padding加密

java - AES。 javax.crypto.Cipher 在解密模式下返回空数组

java.net.MalformedURLException : unknown protocol: rsrc

java - 如何从自定义IDE编译java源代码

Java AES 256 安全 key 生成器 - 非法 key 大小

Perl 地穴 :CBC encrypts/decrypts only first list

JAVA_HOME 错误

java/JSON 未显示解析 JSON 所需的值