我一直在寻找和看这几个小时。我拼命想让iOS使用AES-256加密来加密一小段文本,然后由openssl解密。
直接前进?不。
我在iOS上找到的代码与openssl的密钥和IV不兼容,所以我不得不对它进行调整,但它显然不起作用。
所以这里是加密的代码我正在使用...传递一个字符串来加密(dataString)一个字符串键(key)和一个字符串初始化向量(iv)......
- (NSData *)AES256Encrypt:(NSString *)dataString WithKey:(NSString *)key iv:(NSString *)iv {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
//char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
//bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
//[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
//NSLog(@"keyPtr: '%s'", keyPtr);
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"keyPtr: '%s'", keyData.bytes);
NSData *dataToEncrypt = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = [dataToEncrypt length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeAES256,
ivData.bytes, // initialisation vector
dataToEncrypt.bytes,
dataToEncrypt.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;
}
对于要编码的相同字符串,这不会产生与使用具有相同密钥和iv的openssl时相同的值...例如这个命令行:
openssl enc -aes-256-cbc -e -in secrets.txt -a -iv 0000 -K 0000 -p
secrets.txt只是一个包含要加密的字符串的文本文件
输出如下内容:
salt=3C66000000000000
key=0000000000000000000000000000000000000000000000000000000000000000
iv =00000000000000000000000000000000
qTMfgtAxbF8Yyh27ZDrcIQ==
要解密,请执行相反的操作(假设上面加密的最后一行数据位于test.secrets.out中)
openssl enc -aes-256-cbc -d -in test.secrets.out -a -iv 0000 -K 0000 -p
salt=3C66000000000000
key=0000000000000000000000000000000000000000000000000000000000000000
iv =00000000000000000000000000000000
< text of the secrets.txt file >
现在,如果我使用4个字符的密钥和iv,则在iOS中无法正确编码。如果我使用全长密钥和iv,则无法正确编码。
基本上,这是一个检查,如果我发送一段加密数据,它是正确的数据。
我错过了什么?
我试图找到答案的一些代码...
http://robnapier.net/blog/aes-commoncrypto-564
https://github.com/rnapier/RNCryptor
也在这里广泛搜索过,找不到答案。
任何帮助表示感谢。
答案 0 :(得分:2)
OpenSSL具有唯一的(读取“不接近任何标准,也不是特别安全”)方法,用于将密码转换为IV和密钥。如果查看RNOpenSSLCryptor,您会看到使用的算法:
// For aes-128:
//
// key = MD5(password + salt)
// IV = MD5(Key + password + salt)
//
// For aes-256:
//
// Hash0 = ''
// Hash1 = MD5(Hash0 + Password + Salt)
// Hash2 = MD5(Hash1 + Password + Salt)
// Hash3 = MD5(Hash2 + Password + Salt)
// Hash4 = MD5(Hash3 + Password + Salt)
//
// Key = Hash1 + Hash2
// IV = Hash3 + Hash4
//
// File Format:
//
// |Salted___|<salt>|<ciphertext>|
//
使用RNOpenSSLCryptor
允许RNCryptor
支持OpenSSL格式。我目前正在async
分支上重新编写代码以支持异步操作,并且该分支尚不支持OpenSSL,但我计划很快(2012年7月中旬)重新编写代码。 / p>
如果您想要实现此功能的代码供您自己使用,请查看keyForPassword:salt:
和IVForKey:password:salt:
。
请注意,OpenSSL文件格式有几个安全问题,如果可以避免,我不建议使用它。它不使用非常好的KDF来生成其密钥,不具有应该随机的IV,并且不提供用于认证的HMAC。这些安全问题是我设计different file format的原因,就像我讨厌创建“另一个不兼容的容器”一样。