【问题标题】:AES-Encryption result of C# code is not same as of Java AES-EncryptionC# 代码的 AES-Encryption 结果与 Java AES-Encryption 不同
【发布时间】:2020-06-18 05:56:46
【问题描述】:

我在 Java 中关注 aes 加密代码,我想用 C# 编写它,但它没有给出相同的输出。
Java代码

public String doEncryptString(String salt, String password,String token) throws CryptoException {
        try {
            Cipher cipher = Cipher.getInstance("AES");
            SecretKeySpec secretKeySpec = generateKeySpec(salt,password);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            byte[] inputBytes = token.getBytes();
            byte[] outputBytes = cipher.doFinal(inputBytes);
            return Base64Utils.encodeToString(outputBytes);
        } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException
                | IllegalBlockSizeException ex) {
            throw new CryptoException("Error encrypting password", ex);
        }
    } 

private SecretKeySpec generateKeySpec(String salt,String password) throws CryptoException{
        try {

        String generatedkey=salt+password;
        byte[] key = generatedkey.getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16); // use only first 128 bit
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
        return secretKeySpec;
    } catch (NoSuchAlgorithmException | IOException ex) {
        throw new CryptoException("Error encrypting password", ex);
    }
    }

这是我在 C# 中尝试过的

public static string DoEncrypt(string salt, string password, string token)
        {
            var tdes = new AesManaged();
            tdes.Key = GenerateKey(salt, password);
            tdes.Mode = CipherMode.ECB;
            tdes.Padding = PaddingMode.PKCS7;
            ICryptoTransform crypt = tdes.CreateEncryptor();
            byte[] plain = Encoding.UTF8.GetBytes(token);
            byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
            return Convert.ToBase64String(cipher);
        }

        private static byte[] GenerateKey(string salt, string password)
        {
            string generatedkey = $"{salt}{password}";
            var key = Encoding.UTF8.GetBytes(generatedkey);
            var sha1 = SHA1Managed.Create();
            key = sha1.ComputeHash(key);
            return key.Take(16).ToArray(); // use only first 128 bit
        }

要加密的字符串/令牌: ZHKRIWB310XVVWG315PI7UZZWU1V0YYL5WE9JL
Java 输出: eUjNH8kcgWtlEmuCFHMPwnCFWjy5Pye/gF+itrPs1g8AjtAEZQqlzW/v7kEt2haG
我的 C# 代码输出:强> O8sKdJWH+XCOIbexZPEwN5NxWqpWRHC5b3ZsihT8cfBqpI1eVr3PEr9Eq39a5pMn

我不知道我在这里做错了什么。任何帮助,将不胜感激。谢谢

更新

我向大家道歉。用 C# 翻译的代码运行良好。错误地,我传递了不同的盐值。谢谢大家。

【问题讨论】:

  • 两种情况下的 SHA1 结果是否相同?
  • 比较每个步骤和沿途的变量,毫无疑问,AES 实现没有任何问题,它是你给它的
  • 如果你再次为相同的值运行 C# 代码,它会给你不同的结果。
  • @viveknuna 不,它再次给出相同的结果。
  • @John 实际上我不确定。

标签: java c# encryption aes


【解决方案1】:

Java 代码的 TRANSFORMATION 中有什么?

您还需要使用相同的模式和填充来获得相同的结果,在您的情况下意味着 ECB 和 PKCS7。

Java 似乎只提供 PKCS5 填充?但它似乎与PKCS7兼容?我不是 Java 开发人员,无法提供详细信息,但这里有一个讨论:https://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding 他们说:

一些密码库,如 Java 中的 SUN 提供程序表明 应该使用 PKCS#7 的 PKCS#5 - “PKCS5Padding”应该是 “PKCS7填充”。这是 - 很有可能 - 来自 只有 8 字节块密码(例如(三重)DES 对称)的时间 密码可用。

顺便说一句:生产环境中永远不要使用 ECB 模式,因为它不安全。

【讨论】:

  • 对不起,我忘了添加常量值。在 Java 代码中,TRANSFORMATION 值为“AES”。我也更新了相关问题。谢谢您的回复。由于您要求使用相同的模式和填充,我认为在 Java 中,AES 的默认密码是 AES/ECB/PKCS5Padding,请参阅此处的讨论stackoverflow.com/questions/6258047。我将研究 PKCS5 填充与 PKCS7 填充。
猜你喜欢
  • 1970-01-01
  • 2013-07-07
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多