【发布时间】:2012-08-14 13:12:46
【问题描述】:
第一件事。前段时间,我需要在 Android 中使用简单的 AES 加密来加密密码并将其作为参数发送给密码被解密的 .net Web 服务。
以下是我的安卓加密:
private static String Encrypt(String text, String key)
throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
byte[] b= key.getBytes("UTF-8");
int len= b.length;
if (len > keyBytes.length) len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
String result = Base64.encodeBytes(results);
return result;
}
然后我用 C# 解密它:
public static string Decrypt(string textToDecrypt, string key)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
string decodedUrl = HttpUtility.UrlDecode(textToDecrypt);
byte[] encryptedData = Convert.FromBase64String(decodedUrl);
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return encoding.GetString(plainText);
}
这就像一个魅力,但是当我尝试在 iOS 中做同样的事情时问题就来了。我是 iphone/ipad 的新开发应用程序,所以我用谷歌搜索了它,几乎所有提供的代码示例如下:
- (NSData *)AESEncryptionWithKey:(NSString *)key {
char keyPtr[kCCKeySizeAES128]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
NULL /* initialization vector (optional) */,
[self bytes], [self length], /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
也许我有点过于乐观了,当时我希望这里能顺利过渡,因为当 Android 向我抛出类似以下内容时:
"EgQVKvCLS4VKLoR0xEGexA=="
然后iOS给我:
"yP42c9gajUra7n0zSEuVJQ=="
希望这只是我忘记了,还是某些设置有误?
[UPDATE] 结果现在显示在 base64 编码之后。
【问题讨论】:
-
android版本是一个URL编码的base64字符串,等于
"YHH+gTxyIxvAx1cPFLcP0IEW2HcVHQVi9X11656CFsk="(60 71 fe 81 3c 72 23 1b c0 c7 57 0f 14 b7 0f d0 81 16 d8 77 15 1d 05 62 f5 7d 75 eb 9e 82 16 c9)。 -
糟糕,抱歉我忘了提。我也在对iOS版本的结果进行编码,只是用另一种方法,但编码前的结果不同。
-
更新问题以显示base64编码后的结果。使用相同的密码和相同的密钥。
-
你验证过编码前的字节数相等吗?对于 iOS 添加
NSLog("%@", self);;