无法解密通过OpenSSL在iPhone上编码的数据 [英] Unable to decrypt data encoded via OpenSSL on iPhone

查看:127
本文介绍了无法解密通过OpenSSL在iPhone上编码的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我之前提到的一个问题是:
如何从OpenSSL加密数据获取初始化向量(iv)



我使用 OpenSSL 命令行实用程序来加密字符串,然后尝试使用< CommonCrypto / CommonCryptor.h> 解密iPhone上的字符串。使用Dropbox SDK,一个带加密字符串的xml文件被加载到我的应用程序尝试解析和解密该文件中的字符串的iPhone上。



以下是openssl命令的示例:

  printf%s 你好| openssl enc -aes-128-cbc -K 00ff349830193845af43984758690213 -iv 0 -base64 

以上基数64字符串被放置在XML文件中,然后由应用程序解析。



我使用Matt Gallagher的NSData附加码来解码base64文本。我假设这是正常工作我没有真正找到一个很好的方法来测试它。 (资料来源: http://cocoawithlove.com/2009 /06/base64-encoding-options-on-mac-and.html )。



以下是解密加密字符串的方法。

关键是NSString在这种情况下等于 @00ff349830193845af43984758690213

 code> +(NSString *)string:(NSString *)encryptedString withAES128Key:(NSString *)key {

//解码base64,来自Matt Gallagher的NSData类别
NSData * b64DecodedData = [NSData dataFromBase64String:encryptedString];

NSData * keyData = [key dataUsingEncoding:NSUTF8StringEncoding];

// fyi,我打算稍后用一个随机的替换这个iv
NSData * ivData = [@00000000000000000000000000000000dataUsingEncoding:NSUTF8StringEncoding];

//解密字符串
NSData * decodedData = [self doCipher:b64DecodedData iv:ivData key:keyData context:kCCDecrypt];

NSString * unencryptedString = [[NSString alloc] initWithBytes:[encodedData bytes] length:[decodeData length] encoding:NSUTF8StringEncoding];

return [unencryptedString autorelease];
}

以下是实际解密的方法:(该方法的信用转到其他stackoverflow用户

  +(NSData *)doCipher:(NSData *)dataIn 
iv:(NSData *)iv
key:(NSData *)symmetricKey
上下文:(CCOperation)encryptOrDecrypt
{
CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0; //移动到缓冲区的字节数。
NSMutableData * dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
[symmetricKey bytes],
kCCKeySizeAES128,
iv,
dataInbytes,
dataIn.length,
dataOut.mutableBytes,
dataOut.length,
& cryptBytes);

//这里发生错误,错误-4304 kCCDecodeError
if(ccStatus!= kCCSuccess){
//处理错误
NSLog(@CCCrypt status:% d,ccStatus);
}

dataOut.length = cryptBytes;

return dataOut;
}

发生错误,错误代码 -4304 这是 kCCDecodeError ,因为 ccStatus 不等于 kCCSuccess



我觉得键和iv没有正确设置为NSData对象。 OpenSSL需要键和iv作为十六进制值,我已经做了并仔细地将它们设置为128位。但是,我觉得我在为$ code> doCipher 方法将这些字符串转换为NSData时缺少某些东西。



任何帮助非常感谢!一整天都在这里玩耍。

解决方案

虽然iv被错误地处理是最少的问题。



解码错误听起来像参数长度不正确,因为任何随机的iv,键和数据都应该是有效的输入。 (我的妻子同意并且专业地做这个工作。)将它们转换成NSData后,检查键和数据长度。请注意,使用不正确或不兼容填充的加密数据也会导致解码错误。



为Base64编写测试,您的iOS代码与openssl。



通过简单的测试来处理解决方案。



例如删除base64,直到你获得加密顶部的工作。尝试简单的数据,说一个块长度为0,填充可能是一个问题。尝试一个更简单的键,如全0。您可以在Mac Terminal命令行上使用OPENSSL。



一旦基本加密工作,就可以添加所需的功能。



对于命令行中的openssl使用输入和输出文件,它们将处理二进制文件,因此至少不会有这个障碍。以下是一个示例:

 (file_orig.txt包含:1234567890123456)

openssl enc - e -aes-128-cbc -K 00ff349830193845af43984758690213 -p -iv 0 -nosalt -in file_orig.txt -out file_aes.txt

打印出它生成的密钥以及使用的密钥:

  key = 00ff349830193845af43984758690213 
iv = 000000000000000000000000000000000000

然后,您可以在iOS方法中阅读相同的数据文件。 >

以下是使用openssl创建的文件的iOS方法:

(将密钥openssl输出放入文件key-hex-openssl.txt) p>

  NSData * keyHexData = [@00ff349830193845af43984758690213dataUsingEncoding:NSUTF8StringEncoding]; 
NSData * testData = [NSData dataWithContentsOfFile:@yourDirectoryPath / file_aes.txt];
NSData * clearData = [NSData dataWithContentsOfFile:@yourDirectoryPath / file_orig.txt];

NSLog(@keyHexData:%@,keyHexData);
NSLog(@testData:%@,testData);
NSLog(@clearData:%@,clearData);

unsigned char keyBytes [16];
unsigned char * hex =(uint8_t *)keyHexData.bytes;

char byte_chars [3] = {'\0','\0','\0'}; (int i = 0; i <16; i ++){
byte_chars [0] = hex [i * 2];

byte_chars [1] = hex [(i * 2)+1];
keyBytes [i] = strtol(byte_chars,NULL,16);
}
NSData * keyData = [NSData dataWithBytes:keyBytes length:16];
NSLog(@keyData:%@,keyData);

NSData * ivData = [NSData dataWithBytes:(char []){0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0} length:16];
NSLog(@ivData:%@,ivData);

CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0; //移动到缓冲区的字节数。
NSMutableData * clearOut = [NSMutableData dataWithLength:testData.length];

ccStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyData.bytes,
kCCKeySizeAES128,
ivData.bytes,
testData.bytes,
testData.length,
clearOut.mutableBytes,
clearOut.length,
& cryptBytes);

if(ccStatus!= kCCSuccess){
NSLog(@CCCrypt status:%d,ccStatus);
}

clearOut.length = cryptBytes;
NSLog(@clearOut:%@,clearOut);
keyHexData:< 41393641 34344436 31343245 43463546 33444339 30303038 46453941 34383838>
testData:< 86a8b306 0f33db02 01e77e66 af5bcb3a>
clearData:< 31323334 35363738 39303132 33343536>
keyData:< a96a44d6 142ecf5f 3dc90008 fe9a4888>
ivData:< 00000000 00000000 00000000 00000000>
clearOut:< 31323334 35363738 39303132 33343536>

请注意,clearData已恢复为clearOut



这表明使用openssl加密并用CommonCrypto进行解密。

要解决的问题:

1)需要添加Base64



这是完成加密的起点需要。


Kind of a followup to my previous question to: How do I get the initialization vector (iv) from OpenSSL encrypted data

I'm using OpenSSLcommand line utility to encrypt a string and then attempting to use <CommonCrypto/CommonCryptor.h> to decrypt the string on an iPhone. Using Dropbox SDK, an xml file with encrypted strings is loaded onto the iPhone where my app attempts to parse and decrypt strings within this file.

Here's an example of the openssl command:

printf %s "Hello" | openssl enc -aes-128-cbc -K 00ff349830193845af43984758690213 -iv 0 -base64

The above base 64 string is placed in an XML file which is then parsed by the app.

I'm using Matt Gallagher's NSData addition to decode the base64 text. I'm assuming that's working correctly; I haven't really found a good way to test it. (Source: http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html).

Here's the method to decode the encrypted string.
The key is an NSString in this case equal to @"00ff349830193845af43984758690213".

+ (NSString *)string:(NSString *)encryptedString withAES128Key:(NSString *)key {

// decode base64, from Matt Gallagher's NSData category
NSData *b64DecodedData = [NSData dataFromBase64String:encryptedString];

NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];

// fyi, I plan to replace this later with a random iv
NSData *ivData = [@"00000000000000000000000000000000" dataUsingEncoding:NSUTF8StringEncoding];

// decrypt the string
NSData *decodedData = [self doCipher:b64DecodedData iv:ivData key:keyData context:kCCDecrypt];

NSString *unencryptedString = [[NSString alloc] initWithBytes:[decodedData bytes] length:[decodedData length] encoding:NSUTF8StringEncoding];

return [unencryptedString autorelease];
}

Here's the method that does the actual decrypting: (Credit for this method goes to a fellow stackoverflow user.)

+ (NSData *)doCipher:(NSData *)dataIn
              iv:(NSData *)iv
             key:(NSData *)symmetricKey
         context:(CCOperation)encryptOrDecrypt
{
CCCryptorStatus ccStatus   = kCCSuccess;
size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

ccStatus = CCCrypt( encryptOrDecrypt,
                   kCCAlgorithmAES128,
                   kCCOptionPKCS7Padding,
                   [symmetricKey bytes], 
                   kCCKeySizeAES128,
                   iv,
                   dataIn.bytes,
                   dataIn.length,
                   dataOut.mutableBytes,
                   dataOut.length,
                   &cryptBytes);

// error occurs here, error -4304 kCCDecodeError
if (ccStatus != kCCSuccess) {
    // Handle error
    NSLog(@"CCCrypt status: %d", ccStatus);
}

dataOut.length = cryptBytes;

return dataOut;
}

An error occurs, error code -4304 which is kCCDecodeError because ccStatus is not equal to kCCSuccess.

I feel the key and iv are not being set as NSData objects correctly. OpenSSL requires the key and iv to be hex values, which I have done and careful to set them to exactly 128 bits. However, I think I'm missing something in converting those strings to NSData for the doCipher method.

Any help is greatly appreciated! Been toying with this all day.

解决方案

While the iv is handles incorrectly that is the least of the problems.

A decode error sounds like incorrect argument lengths since any random iv, key and data should be valid input. (my wife agrees and she does this stuff professionally.) Check things like the key and data length after converting them to NSData. Note that passing encrypted data with an incorrect or incompatible padding will also result in a decoding error.

Write a test for Base64, your iOS code vs openssl.

Work up to the solution from simpler tests.

For example drop the base64 until you get the encryption top work. Try simple data, say one block length of 0's, padding can be a problem. Try a simpler key such as all 0's. You can use OPENSSL on the Mac Terminal command line.

Once the basic encryption is working add back in the needed functionality.

For openssl from the command line use input and output files, they will handle binary so you will not have that hurdle at least initially. Here is a sample:

(file_orig.txt contains: "1234567890123456")

openssl enc -e -aes-128-cbc -K 00ff349830193845af43984758690213 -p -iv 0 -nosalt -in file_orig.txt -out file_aes.txt

which prints out the key it generated as well as the iv it used:

key=00ff349830193845af43984758690213
iv =00000000000000000000000000000000

Then you can read the same data files in your iOS method.

Here is an iOS method that uses the files openssl creates:
(put the key openssl output into the file key-hex-openssl.txt)

NSData *keyHexData = [@"00ff349830193845af43984758690213" dataUsingEncoding:NSUTF8StringEncoding];
NSData *testData   = [NSData dataWithContentsOfFile:@"yourDirectoryPath/file_aes.txt"];
NSData *clearData  = [NSData dataWithContentsOfFile:@"yourDirectoryPath/file_orig.txt"];

NSLog(@"keyHexData: %@", keyHexData);
NSLog(@"testData:   %@", testData);
NSLog(@"clearData:  %@", clearData);

unsigned char keyBytes[16];
unsigned char *hex = (uint8_t *)keyHexData.bytes;

char byte_chars[3] = {'\0','\0','\0'};
for (int i=0; i<16; i++) {
    byte_chars[0] = hex[i*2];
    byte_chars[1] = hex[(i*2)+1];
    keyBytes[i] = strtol(byte_chars, NULL, 16);
}
NSData *keyData = [NSData dataWithBytes:keyBytes length:16];
NSLog(@"keyData:    %@", keyData);

NSData *ivData = [NSData dataWithBytes:(char []){0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} length:16];
NSLog(@"ivData:     %@", ivData);

CCCryptorStatus ccStatus   = kCCSuccess;
size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
NSMutableData  *clearOut   = [NSMutableData dataWithLength:testData.length];

ccStatus = CCCrypt(kCCDecrypt,
                   kCCAlgorithmAES128,
                   kCCOptionPKCS7Padding,
                   keyData.bytes, 
                   kCCKeySizeAES128,
                   ivData.bytes,
                   testData.bytes,
                   testData.length,
                   clearOut.mutableBytes,
                   clearOut.length,
                   &cryptBytes);

if (ccStatus != kCCSuccess) {
    NSLog(@"CCCrypt status: %d", ccStatus);
}

clearOut.length = cryptBytes;
NSLog(@"clearOut:   %@", clearOut);
keyHexData: <41393641 34344436 31343245 43463546 33444339 30303038 46453941 34383838>
testData:   <86a8b306 0f33db02 01e77e66 af5bcb3a>
clearData:  <31323334 35363738 39303132 33343536>
keyData:    <a96a44d6 142ecf5f 3dc90008 fe9a4888>
ivData:     <00000000 00000000 00000000 00000000>
clearOut:   <31323334 35363738 39303132 33343536>

Note that clearData has been recovered into clearOut

This demonstrates encrypting with openssl and decrypting with CommonCrypto.

Problems to be overcome:
1) Base64 needs to be added

This is a starting point to complete the encryption needed.

这篇关于无法解密通过OpenSSL在iPhone上编码的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆