2017-08-01 46 views
-1

我需要转换在我们的服务器端加密/解密方法如下,请检查下面的代码AESCrypt加密/解密从PHP到iOS

------------------------------------------------------------------------------------------------------------------------------------- 
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
$key = "a16byteslongkey!"; 
$plaintext = "iphone"; 
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv); 


$ciphertext = base64_encode($ciphertext); 
echo "ciphertext: ".$ciphertext."<br/>"; 

$ciphertextinput = base64_decode($ciphertext); 
$cipherdetext = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertextinput, MCRYPT_MODE_CBC, $iv); 
echo "decryptText:".$cipherdetext."<br/>"; 

我使用AES 256加密尝试,但它提供了不同的结果,

加密

- (NSData *)AES256EncryptWithKey:(NSString *)key { 
// 'key' should be 32 bytes for AES256, will be null-padded otherwise 
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) 
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

// fetch key data 
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

NSUInteger dataLength = [self length]; 

//See the doc: For block ciphers, the output size will always be less than or 
//equal to the input size plus the size of one block. 
//That's why we need to add the size of one block here 
size_t bufferSize = dataLength + kCCBlockSizeAES128; 
void *buffer = malloc(bufferSize); 

size_t numBytesEncrypted = 0; 
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
             keyPtr, kCCKeySizeAES256, 
             NULL /* initialization vector (optional) */, 
             [self bytes], dataLength, /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesEncrypted); 
if (cryptStatus == kCCSuccess) { 
    //the returned NSData takes ownership of the buffer and will free it on deallocation 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
} 

free(buffer); //free the buffer; 
return nil;} 

解密

- (NSData *)AES256DecryptWithKey:(NSString *)key { 
// 'key' should be 32 bytes for AES256, will be null-padded otherwise 
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) 
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

// fetch key data 
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

char ivPtr = ""; 

NSUInteger dataLength = [self length]; 


//See the doc: For block ciphers, the output size will always be less than or 
//equal to the input size plus the size of one block. 
//That's why we need to add the size of one block here 
size_t bufferSize = dataLength + kCCBlockSizeAES128; 
void *buffer = malloc(bufferSize); 

size_t numBytesDecrypted = 0; 
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
             keyPtr, kCCKeySizeAES256, 
             NULL /* initialization vector (optional) */, 
             [self bytes], dataLength, /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesDecrypted); 

if (cryptStatus == kCCSuccess) { 
    //the returned NSData takes ownership of the buffer and will free it on deallocation 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; 
} 

free(buffer); //free the buffer; 
return nil;} 

OriginalText:iphone

密文:SXNepKfh0IrlDDdkq4EdmQ ==

请告诉我错在这里,请给从PHP解密加密文本的一些建议。如何从base 64编码字符串得到确切的“iphone”字符串SXNepKfh0IrlDDdkq4EdmQ ==

另外,请让我知道如何在AES加密中使用ECB模式。

谢谢!

+0

作为一个** **测试**在没有**'kCCOptionPKCS7Padding'的情况下在iOS **中解密,以十六进制记录结果(将其添加到问题中),查看最后一个字节,如果解密是正确的。注意:Base64非常适合**计算机**,但不适用于人,因为它使用十六进制表示字节。 – zaph

+0

这个问题需要一个[MCVE]完整的测试值输入和输出在十六进制适当的地方。 – zaph

回答

1

问题:

`mcrypt的使用非标准空数据填充,iOS的代码使用PKCS#7填充。

的修复,三种选择:

  1. 使用PKCS#7填充,mcrypt的7填充添加PKCS#加密之前和解密之后将其删除。 (推荐)

  • 用NULL填充,公共的密码不指定kCCOptionPKCS7Padding,空填充加密之前添加和解密之后除去。 (不推荐)
  • 它最好不要用的mcrypt,它是放弃的,并没有在年被更新,并且不支持标准PKCS#7 (néePKCS#5)填充,只有非标准的null填充甚至不能用于二进制数据。 mcrypt有许多优秀的bugs追溯到2003年。不推荐使用mcrypt扩展名将在PHP 7.2中删除。请考虑使用defuseRNCryptor,他们提供了一个完整的解决方案,并且正在维护和正确。
  • +0

    好的,谢谢!将尝试所有三个选项。我相信,RNCryptor现在是最好的。 – Gopik

    +0

    使用null填充,对于Common Crypto,不指定kCCOptionPKCS7Padding,在加密之前添加null填充并在解密后删除。 (不推荐) - 所以我们需要在CCCrypt中传递nil而不是kCCOptionPKCS7Padding选项? 它崩溃的应用程序,似乎输入密钥长度错误。 ***由于未捕获的异常'InputAlignmentException'而终止应用程序,原因是:'输入大小未正确对齐。' – Gopik

    +0

    密钥必须完全是AES大小,128,192或256位,并且对于必须指定大小的Common Crypto。在你的代码中你有'kCCKeySizeAES256'是的关键是''a16byteslongkey!'',它是16字节/ 128位,两者不匹配。 **添加测试值:在十六进制输入和输出二进制,而不是Base64 **,你必须做你的一部分。 – zaph