简体   繁体   中英

Encrypting in PHP, decrypting in IOS

I'm trying to figure out how to send encrypted data to my IOS app from a web page.

In php I have a page that encrypts a string and then echos it out as a base64 encoded string:

<?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);
?>

I am able to take that echoed string and decode it in PHP just fine.

In IOS I have a function that opens that page and grabs the encoded string:

-(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];
}

I'm assuming it's failing because of the encoding:NSUTF8StringEncoding part, but I'm not sure what to do about that. I did try encoding:NSUTF32StringEncoding but didn't fare much better.

The PHP encrypting line has OPENSSL_RAW_DATA as an option, but I have not yet found anywhere that tells what encoding RAW data is...

EDIT:

This is what I get for trying to squeeze the question out while rushing to head home...

openssl_encrypt ($json, 'AES-256-CTR', $key, OPENSSL_RAW_DATA, $iv)
returns this: . m #6 : ĕO;֧ ª 0`") -

And after I base64 encode it with the IV I get this:
INI70ZBDUjYouoGlSIFGbzo6v6Eu320Hyg2pIzaOCIw6zMSVTzvWpyDCqr0wYCIpmy2P

On the IOS side, I can use NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; to send the base62 string into the text variable

But when I use [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding]; to turn the base64 string into the openssl_encrypt string, it just returns nil

After I get get it to return a value then I can work on the actual decryption. I'm just trying to figure out one step at a time.

EDIT: Trying again...

So, playing around with it, I think I'm missing something vital...

    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);

    }

And then for my Data to hex:

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]; returns nil.

`NSData *decryptedData = [decrypt DecryptBytes:decodedMsg]; NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];' Also returns nil.

Here is my log:

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

IV = xiiRvStJen2M2VrUuavHZg==

Data = c4Okkz+MCpdSX935O6nNudoJ0ud+oS4sz9GbPFMDsCL5+yJaQ0mzJckP7S6Q/oE=

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

DecodedKey =

DecodedIV =

DecodedData = <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] decoded and decrypted

Hex: (null)

Data:

As people have mentioned, you're just missing the actual decryption step. Usually easiest to use an existing 3rd party resource to help - something like this should work. So basically:

  1. Base64 decode.
  2. Decrypt the data using the above library, and your encryption key.
  3. Then convert the decrypted data to a string (likely using UTF8.)

Edit:

The following is adapted from the linked resources, and should work for decrypting your Base64 decoded data:

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);
}

Note that some of the settings may need a little tweaking, but the logic should work.

Your PHP code starts with JSON.

It runs SSL on the JSON, then base64 encodes the results. So you have

JSON>SSL>base64.

On the receiving side, you need to:

  1. Base64 decode the received string (output will be binary data)
  2. SSL decrypt the resulting binary data (output will be JSON, represented as binary data)
  3. Parse the JSON (JSONSerialization want's a Data object)

You are missing step 2 in your iOS code, so it fails.

I ended up getting this to work using RNCryptor because it has versions for both IOS and PHP, and even Android for down the road. This way I don't have to try to work around different methods on each platform.

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];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM