我已经获得了用于加密的Java实现,但是很遗憾,我们是.net商店,并且无法将Java集成到我们的解决方案中。不幸的是,我也不是Java专家,所以我已经为此奋斗了几天,以为我最终会在这里寻求帮助。
我一直在寻找一种与Java加密工作方式相匹配的方法,并且已经找到了在c#中使用RijndaelManaged所需的分辨率。我真的很近。我在c#中返回的字符串与前半部分匹配,但后半部分不同。
以下是Java实现的代码段:
private static String EncryptBy16( String str, String theKey) throws Exception
{
if ( str == null || str.length() > 16)
{
throw new NullPointerException();
}
int len = str.length();
byte[] pidBytes = str.getBytes();
byte[] pidPaddedBytes = new byte[16];
for ( int x=0; x<16; x++ )
{
if ( x<len )
{
pidPaddedBytes[x] = pidBytes[x];
}
else
{
pidPaddedBytes[x] = (byte) 0x0;
}
}
byte[] raw = asBinary( theKey );
SecretKeySpec myKeySpec = new SecretKeySpec( raw, "AES" );
Cipher myCipher = Cipher.getInstance( "AES/ECB/NoPadding" );
cipher.init( Cipher.ENCRYPT_MODE, myKeySpec );
byte[] encrypted = myCipher.doFinal( pidPaddedBytes );
return( ByteToString( encrypted ) );
}
public static String Encrypt(String stringToEncrypt, String key) throws Exception
{
if ( stringToEncrypt == null ){
throw new NullPointerException();
}
String str = stringToEncrypt;
StringBuffer result = new StringBuffer();
do{
String s = str;
if(s.length() > 16){
str = s.substring(16);
s = s.substring(0,16);
}else {
str = null;
}
result.append(EncryptBy16(s,key));
}while(str != null);
return result.toString();
}
我不完全确定为什么他们一次只传递16个字符,但是w /
e。我使用字符串生成器在c#实现中尝试了相同的操作,一次只发送16个字符,得到的结果与一次传递整个字符串时得到的结果相同。
这是我的c#实现的代码片段,大部分是从MS站点的RijndaelManaged复制和粘贴的:
public static string Encrypt(string stringToEncrypt, string key)
{
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
myRijndael.Key = StringToByte(key);
myRijndael.IV = new byte[16];
return EncryptStringToBytes(stringToEncrypt, myRijndael.Key, myRijndael.IV);
}
}
static string EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return ByteToString(encrypted);
}
正如我上面所说的,加密字符串的前半部分是相同的(请参见下面的示例),但是后半部分是关闭的。我在下面的输出中添加了空格,以更好地说明不同之处。我对加密或Java知之甚少,不知道下一步该怎么做。任何指导将不胜感激
Java输出:
49a85367ec8bc387bb44963b54528c97 8026d7eaeff9e4cb7cf74f8227f80752
C#输出:
49a85367ec8bc387bb44963b54528c97 718f574341593be65034627a6505f13c
根据以下克里斯的建议进行更新:
static string EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
rijAlg.Padding = PaddingMode.None;
rijAlg.Mode = CipherMode.ECB;
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
if (plainText.Length < 16)
{
for (int i = plainText.Length; i < 16; i++)
{
swEncrypt.Write((byte)0x0);
}
}
}
encrypted = msEncrypt.ToArray();
}
}
}
return ByteToString(encrypted);
}
您的C#转换在很大程度上看起来像是在做正确的事,因为第一个块匹配。不匹配的是最后一个块,这是因为Java代码对最后一个块进行零填充以填充它,而您的C#代码则不这样做,因此默认情况下将使用PKCS#5填充。
当然,PKCS#5填充比零填充要好得多,但是由于后者是Java代码使用的零填充,因此您必须做同样的事情。(这意味着再调用swEncrypt.Write((byte) 0)
几次,直到字节数为16的倍数为止。)
还有另一个微妙之处。Java代码使用将该字符串转换为字节String.getBytes()
,该字符串使用Java运行时的“默认编码”。这意味着,如果您的字符串包含非ASCII字符,则会遇到互操作性问题。最佳实践是使用UTF-8,但是鉴于您无法更改Java代码,我想您对此无能为力。
我试图解密C#加密数据在Java没有成功。我用的是128位密钥 这是java代码: 你知道会出什么问题吗? 谢谢 使现代化 对不起,我太笨了,我忘了写实际的错误消息。这是: 线程“main”javax中出现异常。加密。BadPaddingException:组织中的填充块已损坏。弹跳船舱。jcajce。供应商。对称的。util。基本分组密码。javax上的engineDoFinal(未知源代码)。
问题内容: 我似乎找不到使用AES 128位加密的漂亮示例。 有人有示例代码吗? 问题答案: 如果您只想使用内置的加密提供程序RijndaelManaged,请查看以下帮助文章(它也有一个简单的代码示例): http://msdn.microsoft.com/zh-CN/library/system.security.cryptography.rijndaelmanaged.aspx 以防万一您急
1.我有java函数,它加密xml文件并返回加密的字符串。 2.我有c#函数,它可以解密由java函数加密的消息。 Java加密功能运行良好。但问题是C函数, 当我解密时,会得到下面的错误消息 我使用下面的参考搜索解决方案 Java中的AES加密和C#中的解密 C#/Java|AES256加密/解密 C#和Java中的加密/解密 但我仍然面临同样的错误。谁能给我提个建议吗。 我只是改变我的C#加密
问题内容: 我尝试解密最初使用Java中的Objective-C加密的数据。 还有其他问题要提及,但是它们确实很混乱,许多问题还没有解决,因此我将发表自己的问题。 这是加密数据的代码: 我执行此功能,并使用以下代码将结果数据写入光盘: 在Java中,我使用以下代码来尝试实现相同的行为: 如果现在尝试解密通过Objective-C加密的文件,则会收到错误的填充异常。如果我打开两个带有加密内容的文件,
我正在使用C#在客户机/服务器应用程序中执行一些加密方法。NET框架和PHP。加密方法是AES-256-GCM,在PHP中非常简单。这个NET代码,我从这里复制了一些修改。这个NET版本产生了不同的值。 在PHP版本中,我可以这样写 在C#中,我试图使其保持一致 编辑: 所有方法都包括在内。 这个问题不是重复的
问题内容: 1.我有java函数来加密xml文件并返回加密的字符串。 2.我有c#函数可以解密通过java函数加密的消息。 Java加密功能运行良好。但是问题是C#函数, 当我解密时出现以下错误消息 我通过使用下面的参考来搜索解决方案 Java中的AES加密和C#中的解密 C#/ Java | AES256加密/解密 C#和Java中的加密/解密 但我仍然遇到同样的错误。有人可以给我建议吗? 更新