C#/Java | AES256加密/解密

本文关键字:加密 解密 AES256 Java | 更新日期: 2023-09-27 18:26:46

我想加密通过Java/C#套接字(Java服务器,C#客户端)发送的所有数据。我想使用AES256,但我无法让Java和C#生成相同的加密代码。有人能给我两个例子吗?一个在Java中,一个在C#中,它们生成相同的结果并正确地解密结果?

到目前为止我尝试了什么:

public Encrypt(AOBCore instance){
    try {
        String message="This is just an example";
           // Get the KeyGenerator
           KeyGenerator kgen = KeyGenerator.getInstance("AES");
           kgen.init(256); // 192 and 256 bits may not be available

           // Generate the secret key specs.
           SecretKey skey = kgen.generateKey(); //Cantget 'test' in here...
           byte[] raw = skey.getEncoded();
           SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

           // Instantiate the cipher
           Cipher cipher = Cipher.getInstance("AES");
           cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
           byte[] encrypted =
             cipher.doFinal(message.getBytes());
           System.out.println("encrypted string: " + asHex(encrypted));
           cipher.init(Cipher.DECRYPT_MODE, skeySpec);
           byte[] original =
             cipher.doFinal(encrypted);
           String originalString = new String(original);
           System.out.println("Original string: " +
             originalString + " " + asHex(original));
    } catch (Exception e) {
        instance.logMessage(e.getMessage());
    }
}
public static String asHex (byte buf[]) {
      StringBuffer strbuf = new StringBuffer(buf.length * 2);
      int i;
      for (i = 0; i < buf.length; i++) {
       if (((int) buf[i] & 0xff) < 0x10)
        strbuf.append("0");
       strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
      }
      return strbuf.toString();
     }

}

static void Main(string[] args)
    {
        while (true)
        {
            var plain = Console.ReadLine();
            var key = GenerateKey(256);
            var encoded = Encrypt(plain, key, 256);
            Console.WriteLine("Encoded: " + encoded);
            Console.WriteLine(Decrypt(encoded, key, 256));
        }
    }
    private static string GenerateKey(int keySize)
    {
        return "test";
    }
    private static string Encrypt(string plainStr, string completeEncodedKey, int keySize)
    {
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = keySize;
        aesEncryption.BlockSize = 256;
        aesEncryption.Mode = CipherMode.CBC;
        aesEncryption.Padding = PaddingMode.PKCS7;
        aesEncryption.IV = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(completeEncodedKey)).Split(',')[0]);
        aesEncryption.Key = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(completeEncodedKey)).Split(',')[1]);
        byte[] plainText = ASCIIEncoding.UTF8.GetBytes(plainStr);
        ICryptoTransform crypto = aesEncryption.CreateEncryptor();
        // The result of the encryption and decryption            
        byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length);
        return Convert.ToBase64String(cipherText);
    }
    private static string Decrypt(string encryptedText, string completeEncodedKey, int keySize)
    {
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = keySize;
        aesEncryption.BlockSize = 128;
        aesEncryption.Mode = CipherMode.CBC;
        aesEncryption.Padding = PaddingMode.PKCS7;
        aesEncryption.IV = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(completeEncodedKey)).Split(',')[0]);
        aesEncryption.Key = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(completeEncodedKey)).Split(',')[1]);
        ICryptoTransform decrypto = aesEncryption.CreateDecryptor();
        byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length);
        return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length));
    }

C#/Java | AES256加密/解密

问题是您没有在Java代码中指定密码模式或填充。这将使用算法默认值,当需要与其他库的互操作性时,您永远不想这样做。像这样初始化Cipher

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

根据这个答案,Java中的PKCS5应该与.Net中的PKCS7兼容。由于您明智地使用CBC,因此需要修改代码以使用相同的初始化向量进行加密和解密。您应该不要为此使用密钥。IV应该是随机生成的。您可以通过调用cipher.getIV()来使用Java Cipher生成的IV进行加密。

此外,注意与注释中提到的字符编码保持一致。