Java 相当于 C# DESCrypto
Java equivalent of C# DESCrypto
我在 C# 中有 DESCrypto,Java 如下。我在使用 C# 时得到了正确的结果。我在使用 Java 时遇到问题。如何解决这个问题?
// 这在主函数中,它将调用安全性中的加密函数 class (C#)。
private void button1_Click(object sender, EventArgs e)
{
string plainText = "0123456789";
Debug.WriteLine("plainText:" + plainText );
// plainText:0123456789
byte[] encrypted = Security.Encrypt(Encoding.ASCII.GetBytes(plainText));
Debug.WriteLine("encrypted:" + Security.GetString(encrypted));
// encrypted:4F792B474936462B6A4F62635A6142464D54782F4E413D3D
byte[] decrypted = Security.Decrypt(encrypted);
Debug.WriteLine("decrypted:" + Encoding.ASCII.GetString(decrypted)); //
// decrypted:0123456789
}
// 这是一个安全 class (C#)
public class Security
{
private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 };
public static byte[] GetBytes(string value)
{
SoapHexBinary shb = SoapHexBinary.Parse(value);
return shb.Value;
}
public static string GetString(byte[] value)
{
SoapHexBinary shb = new SoapHexBinary(value);
return shb.ToString();
}
public static byte[] Decrypt(byte[] value)
{
MemoryStream mstream = new MemoryStream(Convert.FromBase64String(Encoding.ASCII.GetString(value)));
CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateDecryptor(KEY_64, IV_64), CryptoStreamMode.Read);
StreamReader reader = new StreamReader(cstream);
return Encoding.ASCII.GetBytes(reader.ReadToEnd());
}
public static byte[] Encrypt(byte[] value)
{
MemoryStream mstream = new MemoryStream();
CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateEncryptor(KEY_64, IV_64), CryptoStreamMode.Write);
StreamWriter writer = new StreamWriter(cstream);
writer.Write(Encoding.UTF8.GetString(value));
writer.Flush();
cstream.FlushFinalBlock();
mstream.Flush();
return Encoding ASCII.GetBytes(Convert.ToBase64String(mstream.GetBuffer(), 0, Convert.ToInt32(mstream.Length)));
}
}
// 这是在主函数中调用安全性中的加密函数 class (Java).
String plainText = "0123456789";
Log.d("test", String.format("plainText:%s\n", plainText));
// plainText:0123456789
byte[] encrypted = Security.Encrypt(plainText.getBytes());
Log.d("test", String.format("encrypted:%s\n", Security.GetString(encrypted)));
// encrypted:3B2F8623A17E8CE6DC65A045313C7F34
byte[] decrypted = Security.Decrypt(encrypted);
Log.d("test", String.format("decrypted: %s\n", String.valueOf(decrypted)));
// decrypted:[B@6801b34
//这是证券class(JAVA)
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Security {
private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 };
private static String KEY_TYPE = "DES";
private static String ALGORITHM = "DES/CBC/PKCS5Padding";
public static String GetString(byte[] value) {
StringBuilder builder = new StringBuilder();
for (byte i : value) {
builder.append(String.format("%02X", i & 0xff));
}
return builder.toString();
}
public static byte[] GetByte(String value) {
StringBuilder builder = new StringBuilder();
for (char i : value.toCharArray()) {
builder.append(String.format("%02X", i & 0xff));
}
return String.valueOf(builder).getBytes();
}
public static byte[] Encrypt(byte[] value) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64));
return cipher.doFinal(value);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
public static byte[] Decrypt(byte[] value) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64));
return cipher.doFinal(value);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
}
在 java 中,当 plainText = "0123456789"
时,加密的预期输出是 4F792B474936462B6A4F62635A6142464D54782F4E413D3D(就像在 C# 中一样),但我得到 3B2F8623A17E8CE6DC65A045313C7F34。
在 C# 中,您在 Security
class 内部使用 Base64 对密文进行编码,然后在其外部使用十六进制再次对其进行编码。在 Java 中,您只进行了十六进制编码。你应该坚持一种编码而不是结合两种。
其他注意事项:
- DES现在真的不应该用了。 brute-force.
相当容易
- 如果你使用CBC模式,那么你每次都需要使用一个新的不可预测的IV(随机生成)。它不一定是秘密的,所以你可以把它放在密文前面,然后在解密之前把它切掉。
- 您真的应该考虑为密文添加身份验证。否则,可能会 运行 在您的系统中进行 padding oracle 攻击。使用像 GCM 或 EAX 这样的身份验证模式,或者使用像 HMAC-SHA256.
这样具有强 MAC 的 encrypt-then-MAC 方案
我在 C# 中有 DESCrypto,Java 如下。我在使用 C# 时得到了正确的结果。我在使用 Java 时遇到问题。如何解决这个问题?
// 这在主函数中,它将调用安全性中的加密函数 class (C#)。
private void button1_Click(object sender, EventArgs e)
{
string plainText = "0123456789";
Debug.WriteLine("plainText:" + plainText );
// plainText:0123456789
byte[] encrypted = Security.Encrypt(Encoding.ASCII.GetBytes(plainText));
Debug.WriteLine("encrypted:" + Security.GetString(encrypted));
// encrypted:4F792B474936462B6A4F62635A6142464D54782F4E413D3D
byte[] decrypted = Security.Decrypt(encrypted);
Debug.WriteLine("decrypted:" + Encoding.ASCII.GetString(decrypted)); //
// decrypted:0123456789
}
// 这是一个安全 class (C#)
public class Security
{
private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 };
public static byte[] GetBytes(string value)
{
SoapHexBinary shb = SoapHexBinary.Parse(value);
return shb.Value;
}
public static string GetString(byte[] value)
{
SoapHexBinary shb = new SoapHexBinary(value);
return shb.ToString();
}
public static byte[] Decrypt(byte[] value)
{
MemoryStream mstream = new MemoryStream(Convert.FromBase64String(Encoding.ASCII.GetString(value)));
CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateDecryptor(KEY_64, IV_64), CryptoStreamMode.Read);
StreamReader reader = new StreamReader(cstream);
return Encoding.ASCII.GetBytes(reader.ReadToEnd());
}
public static byte[] Encrypt(byte[] value)
{
MemoryStream mstream = new MemoryStream();
CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateEncryptor(KEY_64, IV_64), CryptoStreamMode.Write);
StreamWriter writer = new StreamWriter(cstream);
writer.Write(Encoding.UTF8.GetString(value));
writer.Flush();
cstream.FlushFinalBlock();
mstream.Flush();
return Encoding ASCII.GetBytes(Convert.ToBase64String(mstream.GetBuffer(), 0, Convert.ToInt32(mstream.Length)));
}
}
// 这是在主函数中调用安全性中的加密函数 class (Java).
String plainText = "0123456789";
Log.d("test", String.format("plainText:%s\n", plainText));
// plainText:0123456789
byte[] encrypted = Security.Encrypt(plainText.getBytes());
Log.d("test", String.format("encrypted:%s\n", Security.GetString(encrypted)));
// encrypted:3B2F8623A17E8CE6DC65A045313C7F34
byte[] decrypted = Security.Decrypt(encrypted);
Log.d("test", String.format("decrypted: %s\n", String.valueOf(decrypted)));
// decrypted:[B@6801b34
//这是证券class(JAVA)
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Security {
private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 };
private static String KEY_TYPE = "DES";
private static String ALGORITHM = "DES/CBC/PKCS5Padding";
public static String GetString(byte[] value) {
StringBuilder builder = new StringBuilder();
for (byte i : value) {
builder.append(String.format("%02X", i & 0xff));
}
return builder.toString();
}
public static byte[] GetByte(String value) {
StringBuilder builder = new StringBuilder();
for (char i : value.toCharArray()) {
builder.append(String.format("%02X", i & 0xff));
}
return String.valueOf(builder).getBytes();
}
public static byte[] Encrypt(byte[] value) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64));
return cipher.doFinal(value);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
public static byte[] Decrypt(byte[] value) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64));
return cipher.doFinal(value);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
}
在 java 中,当 plainText = "0123456789"
时,加密的预期输出是 4F792B474936462B6A4F62635A6142464D54782F4E413D3D(就像在 C# 中一样),但我得到 3B2F8623A17E8CE6DC65A045313C7F34。
在 C# 中,您在 Security
class 内部使用 Base64 对密文进行编码,然后在其外部使用十六进制再次对其进行编码。在 Java 中,您只进行了十六进制编码。你应该坚持一种编码而不是结合两种。
其他注意事项:
- DES现在真的不应该用了。 brute-force. 相当容易
- 如果你使用CBC模式,那么你每次都需要使用一个新的不可预测的IV(随机生成)。它不一定是秘密的,所以你可以把它放在密文前面,然后在解密之前把它切掉。
- 您真的应该考虑为密文添加身份验证。否则,可能会 运行 在您的系统中进行 padding oracle 攻击。使用像 GCM 或 EAX 这样的身份验证模式,或者使用像 HMAC-SHA256. 这样具有强 MAC 的 encrypt-then-MAC 方案