I have a piece of Java code that I need to convert to C#. The original Java code looks like below
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");
}
I converted it to below C# code
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);
}
For simple cases, it worked fine. Such as password 000000
and key 18823214892
, etc. Both Java and C# code give same result. But for a little bit complex case, such as password crmeb.com
and key demo
, the result differs at the 10th character. Java gives out 7iIl3H5zCinwrYbrxAR7cQ==
, but C# shows 7iIl3H5zCikSuWVlZa1dyA==
. What have I done wrong? Maybe the des.IV
should be initialized differently? Or I have chosen the wrong encryption class?
Below is my test code
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==");
The last test case won't pass
BTW, I followed this link to do the conversion. Java equivalent encryption code in .NET
Just found out why. It's because that I didn't set des.Mode
, it should be set as below
des.Mode = CipherMode.ECB;
after that, everything works