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

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

问题描述

我对上一个问题的跟进类型:
如何从OpenSSL加密数据获取初始化向量(iv)



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



以下是openssl命令的示例:

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

放在一个XML文件中,然后由应用程序解析。



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



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

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

  +(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:[decodedData bytes] length:[decodedData length] encoding:NSUTF8StringEncoding];

return [unencryptedString autorelease];
}

这里是实际解密的方法: a 伙伴stackoverflow用户。)

  +(NSData *)doCipher:(NSData *)dataIn 
iv: *)iv
key:(NSData *)symmetricKey
context:(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,
dataIn.bytes,
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位。但是,我想在将这些字符串转换为NSData的 doCipher 方法中缺少一些东西。



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

解决方案

虽然iv处理不正确,这是最少的问题。



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



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

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



例如,删除base64,直到获得加密顶部的工作。尝试简单的数据,说一个块长度为0,填充可以是一个问题。尝试一个更简单的键,如全0。您可以在Mac终端命令行上使用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 = 00000000000000000000000000000000

然后,您可以在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'};
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; //移动到缓冲区的字节数。
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.

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

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