有人可以帮我让我的 AES 加密在 Java、Javascript 和 C# 之间工作吗?

Can someone help me get my AES encryption working between Java, Javascript and C#?

我已经让它在 Java 和 Java 脚本之间工作,但 C# 代码的工作方式不同。也就是说,给定一个要加密的特定字符串,Java 和 Java 脚本代码将生成相同的结果,但 C# 代码生成不同的结果。

这里是 Java脚本代码(使用 CryptoJS):

AesUtil.prototype.encrypt = function(salt, iv, passPhrase, plainText) {
    var key = this.generateKey(salt, passPhrase);
    var encrypted = CryptoJS.AES.encrypt(
            plainText,
            key,
            { iv: CryptoJS.enc.Hex.parse(iv) });
    return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}

此代码会将 "guest" 加密为 "WsH/YEUqqrWDxD15zxsUPg=="。

这里是 Java 代码:

public String encrypt(String plainText, String salt, String passphrase, String iv) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException{
    byte[] plainTextbytes = plainText.getBytes(characterEncoding);
    //byte[] keyBytes = getKeyBytes(salt);
    SecretKey key = generateKey(salt, passphrase);
    byte[] ivBytes = hex(iv);
    return Base64.getEncoder().encodeToString(encrypt(plainTextbytes,key, ivBytes));//, Base64.DEFAULT);
}

private static SecretKey generateKey(String salt, String passphrase) {
    try {
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new javax.crypto.spec.PBEKeySpec(passphrase.toCharArray(), hex(salt), 10000, 128);
        SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "Rijndael");
        return key;
    }
    catch (NoSuchAlgorithmException e) {
        throw fail(e);
    }
    catch (InvalidKeySpecException e) {
        throw fail(e);
    }
}
public static String hex(byte[] bytes) {
    return Hex.encodeHexString(bytes);
}

此代码还将 "guest" 加密为 "WsH/YEUqqrWDxD15zxsUPg=="。

这是我的 C# 代码:

public String Encrypt(String plainText, String passphrase, String salt, String iv, int iterations) {
    var plainBytes = Encoding.UTF8.GetBytes(plainText);
    return Convert.ToBase64String(Encrypt(plainBytes, GetSymmetricAlgorithm(passphrase, salt, iv, iterations)));
}

public byte[] Encrypt(byte[] plainBytes, SymmetricAlgorithm sa) {
    return sa.CreateEncryptor().TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}

public SymmetricAlgorithm GetSymmetricAlgorithm(String passphrase, String salt, String iv, int iterations) {
    var saltBytes = new byte[16];
    var ivBytes = new byte[16];
    Rfc2898DeriveBytes rfcdb = new System.Security.Cryptography.Rfc2898DeriveBytes(passphrase, Encoding.UTF8.GetBytes(salt), iterations);
    saltBytes = rfcdb.GetBytes(16);
    var tempBytes = Encoding.UTF8.GetBytes(iv);
    Array.Copy(tempBytes, ivBytes, Math.Min(ivBytes.Length, tempBytes.Length));
    var rij =  new RijndaelManaged(); //SymmetricAlgorithm.Create();
    rij.Mode = CipherMode.CBC;
    rij.Padding = PaddingMode.PKCS7;
    rij.FeedbackSize = 128;
    rij.KeySize = 128;
    rij.BlockSize = 128;
    rij.Key = saltBytes;
    rij.IV = ivBytes;
    return rij;
}

public byte[] Encrypt(byte[] plainBytes, SymmetricAlgorithm sa) {
    return sa.CreateEncryptor().TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}

此代码将 "guest" 加密为 "F8t0D0vA2rxU3Ez1O5artA=="。请注意,结果值是相同的长度,但它不是相同的值,并且不能用 Java 代码解密(我没有在此处提供 - 我主要关心将所有三种加密一样)。

有人能帮忙吗?提前致谢。

您在 JS 和 Java 中从十六进制解码 IV,但在 C# 中您有 var tempBytes = Encoding.UTF8.GetBytes(iv);。您需要在 C# 中执行相同的十六进制解码。