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

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

本文关键字:Javascript Java 之间 工作 加密 帮助 AES 我的      更新时间:2023-09-26

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

以下是Javascript代码(使用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# 中执行相同的十六进制解码。