【问题标题】:Encrypting in PHP, decrypting in IOSPHP加密,IOS解密
【发布时间】:2017-08-12 08:17:03
【问题描述】:

我试图弄清楚如何从网页将加密数据发送到我的 IOS 应用程序。

在 php 中,我有一个页面加密一个字符串,然后将其作为 base64 编码的字符串回显:

<?php
    function encode($json, $key, $iv){
        echo base64_encode($iv . "::" . openssl_encrypt ($json, 'AES-256-CTR', $key, OPENSSL_RAW_DATA, $iv));
    }

    $key = substr(sha1("super awesome key goes here", true), 0, 16);
    $iv = openssl_random_pseudo_bytes(16);
    $table = array("key1"=>"value1", "key2"=>"value2");
    $json = json_encode($table);

    encode($json, $key, $iv);
?>

我可以把那个回显的字符串用 PHP 解码就好了。

在 IOS 中,我有一个函数可以打开该页面并获取编码字符串:

-(IBAction)fetchData:(id)sender{
    // Fetch data
    NSURL *url = [NSURL URLWithString: @"https://www.website.com/dataupdate.php"];

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:nil  delegateQueue:[NSOperationQueue mainQueue]];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
    NSString *params = @"";
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];

    NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest: urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
        NSLog(@"response: %@ %@\n",response, error);
        if(error == nil){
            NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"Data = %@", text);

            NSData *decodedData = [[NSData alloc] initWithBase64EncodedString: text options:0];
            // Fails here
            NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
            NSLog(@"64 Decoded: %@",decodedString);
        }
    }];
    [dataTask resume];
}

我假设它失败是因为 encoding:NSUTF8StringEncoding 部分,但我不知道该怎么做。我确实尝试过encoding:NSUTF32StringEncoding,但效果并没有好多少。

PHP 加密行有 OPENSSL_RAW_DATA 作为一个选项,但我还没有找到任何地方告诉我编码 RAW 数据是什么......

编辑:

这就是我在赶回家时试图挤出问题的结果......

openssl_encrypt ($json, 'AES-256-CTR', $key, OPENSSL_RAW_DATA, $iv)
返回这个: ��.�m���#6��:�ĕO;֧ª�0`")�-�

在我用 IV 对其进行 base64 编码后,我得到了这个:
INI70ZBDUjYouoGlSIFGbzo6v6Eu320Hyg2pIzaOCIw6zMSVTzvWpyDCqr0wYCIpmy2P

在IOS端,我可以使用NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];将base62字符串发送到文本变量中

但是当我使用[[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding]; 将base64 字符串转换为openssl_encrypt 字符串时,它只是返回nil

在我得到它返回一个值之后,我就可以进行实际的解密了。我只是想一步一步来。

编辑:再试一次...

所以,玩弄它,我想我错过了一些重要的东西......

    if(error == nil){
        NSString *key = @"05nszDCobKjjavWBfG/ZcC/A4DQ=";
        NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSArray *items = [text componentsSeparatedByString:@"::"];
        NSString *iv = [items objectAtIndex:0];
        NSString *msg = [items objectAtIndex:1];
        NSLog(@"\n\n\n IV = %@ \n\n\n Data = %@", iv, msg);

        NSData *decodedKey = [[NSData alloc] initWithBase64EncodedString:key options:0];
        NSData *decodedIV = [[NSData alloc] initWithBase64EncodedString: iv options:0];
        NSData *decodedMsg = [[NSData alloc] initWithBase64EncodedString: msg options:0];
        NSLog(@"\n\n\n DecodedKey = %@ \n\n\n DecodedIV = %@ \n\n\n DecodedData = %@", decodedKey, decodedIV, decodedMsg);

        NSString *hexKey = NSDataToHex(decodedKey);
        NSString *hexIV = NSDataToHex(decodedIV);
        NSString *hexMsg = NSDataToHex(decodedMsg);
        NSLog(@"\n\n\n HexKey = %@ \n\n\n HexIV = %@ \n\n\n HexData = %@", hexKey, hexIV, hexMsg);

        CkoCrypt2 *decrypt = [[CkoCrypt2 alloc] init];

        decrypt.CryptAlgorithm = @"aes";
        decrypt.CipherMode = @"ctr";
        decrypt.KeyLength = [NSNumber numberWithInt: 256];
        decrypt.EncodingMode = @"hex";
        [decrypt SetEncodedIV:hexIV encoding:@"hex"];
        [decrypt SetEncodedKey:hexKey encoding:@"hex"];

        NSString *decryptedStringHex = [decrypt DecryptEncoded:hexMsg];

        NSData *decryptedData = [decrypt DecryptBytes:decodedMsg];
        NSString *decryptedStringData = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
        NSLog(@"decoded and decrypted Hex: %@ /n/nData: %@",decryptedStringHex, decryptedStringData);

    }

然后将我的数据转换为十六进制:

static inline char itoh(int i){
    if (i > 9) return 'A' + (i - 10);
    return '0' + i;
}

NSString * NSDataToHex(NSData *data) {
    NSUInteger i, len;
    unsigned char *buf, *bytes;

    len = data.length;
    bytes = (unsigned char*)data.bytes;
    buf = malloc(len*2);

    for (i=0; i<len; i++){
        buf[i*2] = itoh((bytes[i] >> 4) & 0xF);
        buf[i*2+1] = itoh(bytes[i] & 0xF);
    }

    return [[NSString alloc] initWithBytesNoCopy:buf length:len*2 encoding:NSASCIIStringEncoding freeWhenDone:YES];
}

NSString *decryptedString = [decrypt DecryptEncoded:hexMsg]; 返回零。

`NSData *decryptedData = [解密 DecryptBytes:decodedMsg]; NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];'也返回 nil。

这是我的日志:

2017-03-24 13:20:26.222 长城汽车[47000:3317901]

IV = xiiRvStJen2M2VrUuavHZg==

数据 = c4Okkz+MCpdSX935O6nNudoJ0ud+oS4sz9GbPFMDsCL5+yJaQ0mzJckP7S6Q/oE=

2017-03-24 13:49:40.548 长城[47283:3332493]

解码密钥 =

解码IV =

解码数据 =

2017-03-24 13:49:40.548 长城[47283:3332493]

HexKey = D399ECCC30A86CA8E36AF5817C6FD9702FC0E034

HexIV = C62891BD2B497A7D8CD95AD4B9ABC766

十六进制数据 = 7383A4933F8C0A97525FDDF93BA9CDB9DA09D2E77EA12E2CCFD19B3C5303B022F9FB225A4349B325C90FED2E90FE81

2017-03-24 13:49:49.779 GWM[47283:3332493] 解码解密

十六进制:(空)

数据:

【问题讨论】:

  • 失败怎么办?您收到错误消息吗?或者预期结果与实际结果是什么?此外,由于您没有提供输入、输出或加密密钥,因此任何人都很难复制。对于加密密钥,您当然需要提供一个您不打算实际使用的密钥;-)
  • 您的 PHP 代码正在构建一个 JSON 字符串,使用 SSL 对其进行加密,然后对结果进行 base-64 编码。因此,您需要在接收端以相反的顺序执行这些步骤:base-64 解码(现在您有 8 位数据。)使用 SSL 和相同的密钥解密数据。现在将生成的数据转换为 JSON 字符串(可能使用 UTF8 或 ASCII,但这无关紧要,因为 JSON 字符串不应包含任何非 ASCII 字符。)
  • 您发布的代码根本没有任何SSL解密代码。怎么可能成功?
  • 提供一些调试输出、示例输入数据、中间值以及确切的错误。
  • @Dijkgraaf 添加了一些细节。对不起

标签: php ios objective-c encryption php-openssl


【解决方案1】:

正如人们所提到的,您只是缺少实际的解密步骤。通常最容易使用现有的第 3 方资源来提供帮助 - 像 this 这样的东西应该可以工作。所以基本上:

  1. Base64 解码。
  2. 使用上述库和您的加密密钥解密数据。
  3. 然后将解密后的数据转换为字符串(可能使用 UTF8。)

编辑:

以下内容改编自链接资源,适用于解密您的 Base64 解码数据:

if(error == nil){
    NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"Data = %@", text);
    NSData *decodedData = [[NSData alloc] initWithBase64EncodedString: text options:0];

    CkoCrypt2 *decrypt = [[CkoCrypt2 alloc] init];

    decrypt.CryptAlgorithm = @"aes";
    decrypt.CipherMode = @"ctr";
    decrypt.KeyLength = [NSNumber numberWithInt:256];
    decrypt.EncodingMode = @"hex";
    [decrypt SetEncodedIV:IV encoding:@"hex"];
    [decrypt SetEncodedKey:KEY encoding:@"hex"];

    NSData *decryptedData = [decrypt decryptEncoded:decodedData];

    NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
    NSLog(@"64 Decoded and decrypted: %@",decodedString);
}

请注意,某些设置可能需要稍作调整,但逻辑应该可以工作。

【讨论】:

  • 感谢您的回复。我添加了更多细节。基本上我有麻烦 base54 解码它,因为我不认为 N​​SString(或至少 UTF8)可以处理 AES 加密文本。它只返回nil
  • 您收到的数据不会包含 AES 加密文本。它将包含 AES 加密文本的 Base64 转换。看我的回答。
  • @AndyD273 我已经根据链接资源中的代码更新了我的答案。希望至少能让你朝着正确的方向前进:)
【解决方案2】:

我最终使用RNCryptor 让它工作,因为它有适用于 IOS 和 PHP 的版本,甚至还有适用于未来的 Android 版本。这样我就不必尝试在每个平台上解决不同的方法。

PHP:

$table = array("first"=>"First Value", "second"=>"Second value");

$json = json_encode($table);

$password = "my super awesome password";
$cryptor = new \RNCryptor\RNCryptor\Encryptor;
$base64Encrypted = $cryptor->encrypt($json, $password);
echo $base64Encrypted;

XCode:

NSURL *url = [NSURL URLWithString:@"https://www.website.com/dataupdate.php"];
NSData *encryptedData = [[NSData alloc] initWithBase64EncodedString: [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil] options:0];

NSString *password = @"my super awesome password";
NSError *error = nil;
NSData *decryptedData = [RNDecryptor decryptData: encryptedData withPassword:password error:&error];

self.jsonList = [NSJSONSerialization JSONObjectWithData:decryptedData options:NSJSONReadingMutableContainers error:&error];

【讨论】:

    【解决方案3】:

    您的 PHP 代码以 JSON 开头。

    它在 JSON 上运行 SSL,然后对结果进行 base64 编码。所以你有

    JSON>SSL>base64.

    在接收方,您需要:

    1. Base64 解码接收到的字符串(输出将是二进制数据)
    2. SSL 解密生成的二进制数据(输出将是 JSON,表示为二进制数据)
    3. 解析 JSON(JSONSerialization 需要一个 Data 对象)

    您的 iOS 代码中缺少第 2 步,因此它失败了。

    【讨论】:

    • 所以如果我理解正确,我想尝试直接解码 NSData?如果是这样,我可能无法像现在这样 ($iv . "::" . openssl_encrypt(...)) 将 IV 放入数据中,除非有办法将其从 NSData 中取出...我已经看到了你删除第一个的例子16 个字节,但我不知道如何在 IOSyet 中做到这一点。在我花很多时间弄清楚之前有没有更好的方法?
    猜你喜欢
    • 1970-01-01
    • 2011-10-11
    • 2018-01-08
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 2018-01-20
    相关资源
    最近更新 更多