在 PHP 中加密,在 IOS 中解密
Encrypting in PHP, decrypting in IOS
我正在尝试弄清楚如何将加密数据从网页发送到我的 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)
return是这样的:
��.��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
字符串时,它只是returns nil
在我得到 return 一个值之后,我就可以进行实际的解密了。我只是想一步一个脚印。
编辑:重试...
所以,玩弄它,我想我错过了一些重要的东西......
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];
return无.
`NSData *decryptedData = [解密DecryptBytes:decodedMsg];
NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];'也 return 为零。
这是我的日志:
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:
正如人们提到的,您只是缺少实际的解密步骤。通常最容易使用现有的第 3 方资源来提供帮助 - this 之类的东西应该可以工作。所以基本上:
- Base64解码。
- 使用上述库和您的加密密钥解密数据。
- 然后将解密的数据转换为字符串(可能使用 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);
}
请注意,某些设置可能需要稍作调整,但逻辑应该可行。
您的 PHP 代码以 JSON 开头。
它在 JSON 上运行 SSL,然后对结果进行 base64 编码。所以你有
JSON>SSL>base64.
在接收方,您需要:
- Base64 解码接收到的字符串(输出将是二进制数据)
- SSL 解密生成的二进制数据(输出将是 JSON,表示为二进制数据)
- 解析 JSON(JSON序列化需要一个数据对象)
您的 iOS 代码中缺少第 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];
我正在尝试弄清楚如何将加密数据从网页发送到我的 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)
return是这样的:
��.��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
字符串时,它只是returns nil
在我得到 return 一个值之后,我就可以进行实际的解密了。我只是想一步一个脚印。
编辑:重试...
所以,玩弄它,我想我错过了一些重要的东西......
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];
return无.
`NSData *decryptedData = [解密DecryptBytes:decodedMsg]; NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];'也 return 为零。
这是我的日志:
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:
正如人们提到的,您只是缺少实际的解密步骤。通常最容易使用现有的第 3 方资源来提供帮助 - this 之类的东西应该可以工作。所以基本上:
- Base64解码。
- 使用上述库和您的加密密钥解密数据。
- 然后将解密的数据转换为字符串(可能使用 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);
}
请注意,某些设置可能需要稍作调整,但逻辑应该可行。
您的 PHP 代码以 JSON 开头。
它在 JSON 上运行 SSL,然后对结果进行 base64 编码。所以你有
JSON>SSL>base64.
在接收方,您需要:
- Base64 解码接收到的字符串(输出将是二进制数据)
- SSL 解密生成的二进制数据(输出将是 JSON,表示为二进制数据)
- 解析 JSON(JSON序列化需要一个数据对象)
您的 iOS 代码中缺少第 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];