我收到了一个用Java实现的加密程序,但不幸的是我们是一家.NET公司,我无法将Java融入我们的解决方案中。可悲的是,我也不是Java专业人员,所以我已经为此奋斗了几天,想最终在这里求助。
我已经四处寻找一种匹配Java加密方式的方法,并得出结论,我需要在C#中使用RijndaelManaged。我离成功很近了,但是我返回的字符串只匹配到前半部分,后半部分却不同。
这里是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个字符,但无所谓。我使用字符串构建器尝试了与我的c#实现相同的方法,每次只发送16个字符,并在一次性传入整个字符串时获得了与发送16个字符相同的结果。
下面是我c#实现的代码片段,大部分都是从微软的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
根据下面Chris的建议更新:
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);
}