Xcode AES 加密/解密 - php 兼容性问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15752959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 03:06:38  来源:igfitidea点击:

Xcode AES encrypt / decrypt - php compatibilty issues

phpiosxcodeaesrijndael

提问by BechD

I am trying to encrypt a string in Xcode and decrypt it with PHP or encrypt with PHP and decrypt with Xcode.

我正在尝试在 Xcode 中加密一个字符串并使用 PHP 对其进行解密,或者使用 PHP 进行加密并使用 Xcode 进行解密。

So first of all I am trying to get the same AES encryptionresult.

所以首先我试图得到相同的AES encryption结果。

Here is my Xcode file (I've put everything in a single file for simplicity):

这是我的 Xcode 文件(为了简单起见,我将所有内容都放在一个文件中):

#import "t.h"
#import <CommonCrypto/CommonCryptor.h>

@interface NSData(AES)
- (NSData*)AES256EncryptWithKey:(NSString*)key;
- (NSData*)AES256DecryptWithKey:(NSString*)key;
@end

@implementation NSData (AES)

- (NSData*)AES256EncryptWithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES256];

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding];

NSString *iv = @"1234567812345678";
char ivPtr[kCCKeySizeAES128];

[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSASCIIStringEncoding];    

NSUInteger dataLength = [self length];

size_t bufferSize           = dataLength + kCCBlockSizeAES128;
void* buffer                = malloc(bufferSize);

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

if (cryptStatus == kCCSuccess)
{
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

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

- (NSData*)AES256DecryptWithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES256];  

NSString *iv = @"1234567812345678";
char ivPtr[kCCKeySizeAES128];

[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSASCIIStringEncoding];


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

NSUInteger dataLength = [self length];

size_t bufferSize           = dataLength + kCCBlockSizeAES128;
void* buffer                = malloc(bufferSize);

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

if (cryptStatus == kCCSuccess)
{
    return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}

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

@end



@interface t ()
@end

@implementation t

- (void)viewDidLoad
{
[super viewDidLoad];


NSString *key = @"12345678123456781234567812345678";

NSData *plaintext =  [[@"aaa0000000000000" dataUsingEncoding:NSASCIIStringEncoding] AES256EncryptWithKey: key];

label1.text = [[NSString alloc] initWithData:plaintext encoding:NSASCIIStringEncoding];


}

@end

And now the PHP code:

现在是 PHP 代码:

<?php

$key256 = "12345678123456781234567812345678";
$iv128 = "1234567812345678";
$text = "aaa";

$blocksize = 16;
$len = strlen($text);
$pad = $blocksize - ($len % $blocksize);

$text .= str_repeat("0", $pad);

$cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key256, $text, MCRYPT_MODE_CBC, $iv128);

echo $cipher;

?>

The Xcode encrypted string and the php encrypted string are different.

Xcode 加密的字符串和php 加密的字符串是不同的。

PHP: a5¢D[Iüf#h?(?

PHP: a5¢D[Iüf#h?(?

Xcode: ?#yZPbEs?D6?

代码: ?#yZPbEs?D6?

What can I do to make it work? Am I doing something wrong?

我该怎么做才能让它发挥作用?难道我做错了什么?

I will further explain what the code does and how it is structured so you can easier understand the problem (correct me if I am wrong):

我将进一步解释代码的作用及其结构,以便您更容易理解问题(如果我错了,请纠正我):

  1. Both PHP and Xcode use CBC for AES encryption so I guess there is no problem there.

  2. As you can see I am just trying to get the same result - security does not matter here - so I used no padding - the text is exactly 128 bits in length (16 characters).

  3. The key is 256 bits (32 characters).

  4. The Initialization Vector is 128 bits (16 characters).

  1. PHP 和 Xcode 都使用 CBC 进行 AES 加密,所以我想那里没有问题。

  2. 正如您所看到的,我只是想获得相同的结果 - 安全性在这里无关紧要 - 所以我没有使用填充 - 文本长度正好是 128 位(16 个字符)。

  3. 密钥是 256 位(32 个字符)。

  4. 初始化向量是 128 位(16 个字符)。

Thank you very much.

非常感谢。

Any help is appreciated!

任何帮助表示赞赏!

回答by BechD

Finally got it! (after asking Apple about it)

终于拿到了!(在询问苹果之后)

Apparently getting getCString from NSString is wrong because the routine tries to null terminate the string and a 32-byte buffer is not big enough to terminate a 32-chars string.

显然,从 NSString 获取 getCString 是错误的,因为例程尝试空终止字符串,而 32 字节缓冲区不足以终止 32 字符字符串。

The correct way to get the key or IV would be:

获取密钥或 IV 的正确方法是:

[key cStringUsingEncoding:NSASCIIStringEncoding];

回答by Lefteris

Change:

改变:

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding];

to

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

I believe this is an encoding issue

我相信这是一个编码问题

回答by jovanjovanovic

When using this code from the very beginning of the page, I am able to encrypt only 16 characters of text. Actually I am able to encrypt any size of text, but when I decrypt that encrypted NSData, I get only 16 characters or 128bits.

从页面开头使用此代码时,我只能加密 16 个文本字符。实际上我可以加密任何大小的文本,但是当我解密加密的 NSData 时,我只能得到 16 个字符或 128 位。

Does this has something to do with IV? Is this code made to encrypt ONLY 128bits and if I have bigger size of the text, I need to provide (for better security) new IV and encrypt second block?

这和IV有关系吗?这段代码是否仅用于加密 128 位,如果我有更大的文本大小,我需要提供(为了更好的安全性)新的 IV 并加密第二个块?