C# 加密显示的结果与 Java 等效的不同

问题描述 投票:0回答:1

我有一段 Java 代码需要转换为 C#。原始的Java代码如下所示

    public static String encryptPassword(String pwd, String key) {
        try {
            Security.addProvider(new com.sun.crypto.provider.SunJCE());
            Key secretKey = getDesSecretKey(key);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] data = pwd.getBytes(StandardCharsets.UTF_8);
            byte[] result = cipher.doFinal(data);
            return new sun.misc.BASE64Encoder().encode(result);
        } catch (Exception e) {
            return null;
        }
    }

    public static SecretKey getDesSecretKey(String key) {
        byte[] result = new byte[8];
        byte[] keys;
        keys = key.getBytes(StandardCharsets.UTF_8);
        for (int i = 0; i < 8; i++) {
            if (i < keys.length) {
                result[i] = keys[i];
            } else {
                result[i] = 0x01;
            }
        }
        return new SecretKeySpec(result, "DES");
    }

我将其转换为以下 C# 代码

    public static string EncryptPassword(string password, string key)
    {
        const int keyLength = 8;
        var bytes = new byte[keyLength];
        var keyBytes = Encoding.UTF8.GetBytes(key);
        for (int i = 0; i < keyLength; i++)
        {
            if (i < keyBytes.Length)
                bytes[i] = keyBytes[i];
            else
                bytes[i] = 0x01;
        }

#pragma warning disable S5547
        using var des = DES.Create();
#pragma warning restore S5547
        des.Key = bytes;
        des.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
#pragma warning disable S3329
        var encryptor = des.CreateEncryptor(des.Key, des.IV);
#pragma warning restore S3329
        var passwordBytes = Encoding.UTF8.GetBytes(password);
        var payload = encryptor.TransformFinalBlock(passwordBytes, 0, passwordBytes.Length);
        
        return Convert.ToBase64String(payload);
    }

对于简单的情况,效果很好。例如密码

000000
和密钥
18823214892
等。Java和C#代码给出相同的结果。但对于稍微复杂的情况,例如密码
crmeb.com
和密钥
demo
,结果在第 10 个字符处有所不同。 Java 给出
7iIl3H5zCinwrYbrxAR7cQ==
,但 C# 显示
7iIl3H5zCikSuWVlZa1dyA==
。我做错了什么?也许
des.IV
应该以不同的方式初始化?或者我选择了错误的加密类别?

下面是我的测试代码

var encryptedPassword = CryptoUtils.EncryptPassword("000000", "18823214892");
encryptedPassword.Should().Be("PwePP4OrK2o=");

encryptedPassword = CryptoUtils.EncryptPassword("123456", "admin");
encryptedPassword.Should().Be("L8qdg72wbeQ=");

encryptedPassword = CryptoUtils.EncryptPassword("000000", "18292417675");
encryptedPassword.Should().Be("w9LTrURn7xU=");

encryptedPassword = CryptoUtils.EncryptPassword("crmeb.com", "demo");
encryptedPassword.Should().Be("7iIl3H5zCinwrYbrxAR7cQ==");

最后一个测试用例不会通过

顺便说一句,我按照此链接进行了转换。 .NET 中的 Java 等效加密代码

java c# encryption
1个回答
0
投票

刚刚知道原因了。因为我没有设置

des.Mode
,应该如下设置

des.Mode = CipherMode.ECB;

之后一切正常

© www.soinside.com 2019 - 2024. All rights reserved.