在PHP中加密,在IOS中解密

时间:2017-03-20 21:10:03

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

我正在尝试弄清楚如何从网页向我的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`“) -

在我用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];返回nil。

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

这是我的日志:

  

2017-03-24 13:20:26.222 GWM [47000:3317901]

     

IV = xiiRvStJen2M2VrUuavHZg ==

     

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

     

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

     

DecodedKey =

     

DecodedIV =

     

DecodedData =&lt; 7383a493 3f8c0a97 525fddf9 3ba9cdb9 da09d2e7 7ea12e2c   cfd19b3c 5303b022 f9fb225a 4349b325 c90fed2e 90fe81

     

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

     

HexKey = D399ECCC30A86CA8E36AF5817C6FD9702FC0E034

     

HexIV = C62891BD2B497A7D8CD95AD4B9ABC766

     

HexData =   7383A4933F8C0A97525FDDF93BA9CDB9DA09D2E77EA12E2CCFD19B3C5303B022F9FB225A4349B325C90FED2E90FE81

     

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

     

十六进制:( null)

     

数据:

3 个答案:

答案 0 :(得分:4)

正如人们所提到的,你只是错过了实际的解密步骤。通常最容易使用现有的第三方资源来帮助 - 像this这样的东西应该有效。所以基本上:

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

    以下内容改编自链接资源,可用于解密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);
    }
    

    请注意,某些设置可能需要稍微调整,但逻辑应该有效。

答案 1 :(得分:0)

您的PHP代码以JSON开头。

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

JSON&GT; SSL&GT; BASE64

在接收方,你需要:

  1. Base64解码接收到的字符串(输出将是二进制数据)
  2. SSL解密生成的二进制数据(输出将为JSON,表示为二进制数据)
  3. 解析JSON(JSONSerialization想要的是一个数据对象)
  4. 您在iOS代码中缺少第2步,因此失败。

答案 2 :(得分:0)

我最终使用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];