题
我需要密串在iPhone上并发送给a.网网服务进行解密。我能够加密/解在iPhone上。净,但是加密的字符串的iPhone无法解密。网。错误我得到的是"填充是无效和不能被删除。"
。净码是:http://blog.realcoderscoding.com/index.php/2008/07/dot-net-encryption-simple-aes-wrapper/
IPhone代码使用的样本代码: http://nootech.wordpress.com/2009/01/17/symmetric-encryption-with-the-iphone-sdk/
据我所知,我的关键的设置是相同的:
result.BlockSize = 128; // iPhone: kCCBlockSizeAES128
result.KeySize = 128; // kCCBlockSizeAES128
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7; // kCCOptionPKCS7Padding
我尝试了不同的方式生成密文。你好/hello是:
e0PnmbTg/3cT3W+92CDw1Q==。净
yrKe5Z7p7MNqx9+CbBvNqQ==在iPhone
和"openssl enc-aes-128-cbc-nosalt-a-在hello.txt -通通的:你好"产生:QA+Ul+r6Zmr7yHipMcHSbQ==
更新: 我已经发布工作的代码这里.
解决方案
至少,你正在使用不同的初始化载体(IV)。
。净的代码使用的关键四。
private static AesCryptoServiceProvider GetProvider(byte[] key) { //Set up the encryption objects AesCryptoServiceProvider result = new AesCryptoServiceProvider(); byte[] RealKey = Encryptor.GetKey(key, result); result.Key = RealKey; result.IV = RealKey; return result; }
和
private static byte[] GetKey(byte[] suggestedKey, AesCryptoServiceProvider p) { byte[] kRaw = suggestedKey; List kList = new List(); for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8 ) { kList.Add(kRaw[i % kRaw.Length]); } byte[] k = kList.ToArray(); return k; }
这也许应该是:
kList.Add(kRaw[(i / 8) % kRaw.Length]);
.否则的一个关键的长%8==0将使用相同的字母,反反复复,doh!因此IV(和关键)的使用。净是:
hleolhleolhleolh
.这不是API的一部分,而是由于包装码,你指出在(其中有一个严重错误,在它...).IPhone代码使用0四。
// Initialization vector; dummy in this case 0's. uint8_t iv[kChosenCipherBlockSize]; memset((void *) iv, 0x0, (size_t) sizeof(iv));
openssl通过默认前面添加一个随机产生的盐(这就是为什么输出为再!).
Openssl输出更多的安全,因为它是前添加一个随机的初始化的矢量。它看起来像前几个字节的base64解码的字符串为"咸__".你也可以要求openssl不使用盐(-nosalt)和/或提供一个IV(-iv)。
从本质上讲,openssl.网,并iPhone使用的是相同的加密,你只需要小心如何初始化Api用加密钥和初始化的矢量。
其他提示
在C#
void test(){
string ctB64 = encrypt("hola");
Console.WriteLine(ctB64); // the same as in objective-c
}
string encrypt(string input)
{
try
{
// Create a new instance of the AesManaged class. This generates a new key and initialization vector (IV).
AesManaged myAes = new AesManaged();
// Override the cipher mode, key and IV
myAes.Mode = CipherMode.CBC;
myAes.IV = new byte[16] { 0x10, 0x16, 0x1F, 0xAD, 0x10, 0x10, 0xAA, 0x22, 0x12, 0x51, 0xF1, 0x1E, 0x15, 0x11, 0x1B, 0x10 }; // must be the same as in objective-c
myAes.Key = Encoding.UTF8.GetBytes(“0123456789123456”);
//CipherKey; // Byte array representing the key
myAes.Padding = PaddingMode.PKCS7;
// Create a encryption object to perform the stream transform.
ICryptoTransform encryptor = myAes.CreateEncryptor();
// perform the encryption as required...
MemoryStream ms = new MemoryStream();
CryptoStream ct = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
byte[] binput = Encoding.UTF8.GetBytes(input);
ct.Write(binput, 0, binput.Length);
ct.Close();
byte [] result = ms.ToArray();
return Convert.ToBase64String(result);
}
catch (Exception ex)
{
// TODO: Log the error
Console.WriteLine(ex);
throw ex;
}
}
·在Objective-C, 从 https://github.com/kelp404/CocoaSecurity
添加CocoaSecurity库#import "CocoaSecurity.h"
#import "Base64.h"
…
- (void) test{
unsigned char bytes[] = { 0x10, 0x16, 0x1F, 0xAD, 0x10, 0x10, 0xAA, 0x22, 0x12, 0x51, 0xF1, 0x1E, 0x15, 0x11, 0x1B, 0x10 }; // must be the same as in c#
NSData *iv = [NSData dataWithBytesNoCopy:bytes length:16 freeWhenDone:YES];
NSData* key = [@"0123456789123456" dataUsingEncoding:NSUTF8StringEncoding];
CocoaSecurityResult *result = [CocoaSecurity aesEncrypt:@"hola" key:key iv:iv];
NSLog(@"%@", result.base64); // the same as in c#
NSData *data = [NSData dataWithBase64EncodedString:result.base64];
CocoaSecurityResult *result2 = [CocoaSecurity aesDecryptWithData:data key:key iv:iv];
NSLog(@"%@", result2.utf8String); // show "hola"
}
您确认您使用的是在测试中相同的AES密钥?在文章的OpenSSL例子使用其中的OpenSSL导出密钥和从IV密码(和可能使用的盐为好。
生成随机的128比特的密钥并指定十六进制格式此键的OpenSSL与:
openssl enc -aes-128-cbc -a -in hello.txt -K KEY_IN_HEX -iv 0
您不应该以任何安全系统中使用IV = 0,但用于测试的互操作性是OK。