3DES加密实现报告与C#实现不同的输出
我一直试图使用BouncyCastle套件在java中使用3DES对明文进行加密,但没有成功。这个结果应该与现有C#实现产生的结果相匹配,因为我计划稍后对其进行解密 我不断得到不同的结果,尽管我确信我已经用Java生成了C#algo的“等价物”。有人能帮我看完这两个片段并提出建议吗?我将不胜感激 C#加密:3DES加密实现报告与C#实现不同的输出,c#,java,encryption,bouncycastle,3des,C#,Java,Encryption,Bouncycastle,3des,我一直试图使用BouncyCastle套件在java中使用3DES对明文进行加密,但没有成功。这个结果应该与现有C#实现产生的结果相匹配,因为我计划稍后对其进行解密 我不断得到不同的结果,尽管我确信我已经用Java生成了C#algo的“等价物”。有人能帮我看完这两个片段并提出建议吗?我将不胜感激 C#加密: public static byte[] encryptStringToBytes_3DES(string plainText, string passKey) {
public static byte[] encryptStringToBytes_3DES(string plainText, string passKey)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
// Declare the streams used
// to encrypt to an in memory
// array of bytes.
MemoryStream msEncrypt = null;
CryptoStream csEncrypt = null;
StreamWriter swEncrypt = null;
ASCIIEncoding ascii = new System.Text.ASCIIEncoding();
// used to encrypt the data.
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
string passphrase = passKey;
byte[] iv = ascii.GetBytes("AVREWASH");
byte[] key = ascii.GetBytes(passphrase);
try
{
// Create a TripleDES object
// with the specified key and IV.
//Console.WriteLine("Key size is " + tdes.KeySize+" and IV is "+tdes.IV+" and that of key is "+key.Length);
tdes.Key = key;
tdes.IV = iv;
tdes.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = tdes.CreateEncryptor(tdes.Key, tdes.IV);
// Create the streams used for encryption.
msEncrypt = new MemoryStream();
csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
swEncrypt = new StreamWriter(csEncrypt);
//Write all data to the stream.
swEncrypt.Write(plainText);
}
catch (Exception ex)
{
Console.WriteLine("Error is " + ex.Message);
while (true)
{
}
}
finally
{
// Clean things up.
// Close the streams.
if (swEncrypt != null)
swEncrypt.Close();
if (csEncrypt != null)
csEncrypt.Close();
if (msEncrypt != null)
msEncrypt.Close();
// Clear the TripleDES object.
if (tdes != null)
tdes.Clear();
}
// Return the encrypted bytes from the memory stream.
return msEncrypt.ToArray();
}
应该执行“等效”加密的Java代码段也如下所示:
public void encrypt(String plaintext, String IV, String tripleDesKey){
try{
SecretKey keySpec = new SecretKeySpec(tripleDesKey.getBytes("US-ASCII"),"DESede");
IvParameterSpec iv = new IvParameterSpec(IV.getBytes("US-ASCII"));
Cipher e_cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
e_cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte [] cipherText = e_cipher.doFinal(plaintext.trim().getBytes("US-ASCII"));
System.out.println("Ciphertext: " + asHex(cipherText));
}
catch(Exception exc){
ex.printStackTrace();
}
}
这是它对应的十六进制。。作用
public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
公共静态字符串asHex(字节buf[]{
StringBuffer strbuf=新的StringBuffer(buf.length*2);
int i;
对于(i=0;i
请帮助。您正在使用不同的填充模式。在C#中,您编写了
tdes.Padding=PaddingMode.Zeros代码>
在Java中,您在CBC模式下使用了PKCS5P。这是不一样的事情 您正在使用不同的填充模式。在C#中,您编写了tdes.Padding=PaddingMode.Zeros代码>
在Java中,您在CBC模式下使用了PKCS5P。这是不一样的事情 一些评论:
.NET TripleDESCryptoServiceProvider的默认模式实际上是CBC,这是您在JAVA代码中显式指定的模式,但如果您在C#代码中也显式指定它,则不会有任何影响
在原始代码中,在C#代码中使用PaddingMode.zero,但在JAVA代码中添加pkcs5p。Java中没有提供PaddingMode.zero等价物的内置密码提供程序。如果您仍然可以更改C#代码,则应改用PaddingMode.Pkcs7。否则,您必须为Java搜索第三方密码提供商来完成这项工作
避免使用ASCII编码,除非您能够保证输入实际上包含7位ASCII。如果传入带有其他字符的字符串,则输出未定义
传递给3DES构造函数的密钥数据的长度应为8、16或24,并且通常设置DES奇偶校验位。AFAIK.NET和Java都将忽略奇偶校验位,但如果密钥长度不属于任何一个正确的值,它们的行为可能会有所不同。因此,如果您希望对任何可能的密钥输入进行加密,则应该使用.NET和Java都支持的密钥派生函数。尝试使用Java中的pbewithhmacsha1和desede,并在C#中添加使用System.Security.Cryptography.Rfc2898DeriveBytes转换密钥的代码
一些评论:
.NET TripleDESCryptoServiceProvider的默认模式实际上是CBC,这是您在JAVA代码中显式指定的模式,但如果您在C#代码中也显式指定它,则不会有任何影响
在原始代码中,在C#代码中使用PaddingMode.zero,但在JAVA代码中添加pkcs5p。Java中没有提供PaddingMode.zero等价物的内置密码提供程序。如果您仍然可以更改C#代码,则应改用PaddingMode.Pkcs7。否则,您必须为Java搜索第三方密码提供商来完成这项工作
避免使用ASCII编码,除非您能够保证输入实际上包含7位ASCII。如果传入带有其他字符的字符串,则输出未定义
传递给3DES构造函数的密钥数据的长度应为8、16或24,并且通常设置DES奇偶校验位。AFAIK.NET和Java都将忽略奇偶校验位,但如果密钥长度不属于任何一个正确的值,它们的行为可能会有所不同。因此,如果您希望对任何可能的密钥输入进行加密,则应该使用.NET和Java都支持的密钥派生函数。尝试使用Java中的pbewithhmacsha1和desede,并在C#中添加使用System.Security.Cryptography.Rfc2898DeriveBytes转换密钥的代码
我会仔细检查字符集(UTF等)。字符串的默认值有时会使您在执行此类操作时出错,尤其是调用getBytes()时。确保阅读所有的javadoc。我会仔细检查字符集(UTF等)。字符串的默认值有时会使您在执行此类操作时出错,尤其是调用getBytes()时。确保阅读所有的javadoc。你是对的!我几分钟前就注意到了。。。。我不得不将Java中的填充方案更新为DESede/CBC/ZeroBytePadding。非常感谢!!ZeroBytePadding并不总是最佳填充方案。在解密过程中,您可能会在和处丢失消息的0x00
字节。我建议使用PKCS7、ISO 10126或ANSI x.923填充模式。这些填充模式将确保解密后消息长度保持不变。你是对的!我几分钟前就注意到了。。。。我不得不将Java中的填充方案更新为DESede/CBC/ZeroBytePadding。非常感谢!!ZeroBytePadding并不总是最佳填充方案。在解密过程中,您可能会在和处丢失消息的0x00
字节。我建议使用PKCS7、ISO 10126或ANSI x.923填充模式。这些填充模式将确保解密后消息长度保持不变。
public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}