PHP AES解密工作加密不

时间:2020-12-11 18:22:35

So, I have 3 Pieces out of 4 working, iOS Encrypt-Decrypt from this Link And I am able to Decrypt the data Encrypted from iOS I am having trouble Encrypting on PHP side. When I do echo Encryption code. PHP prints something like F>HFl8aR what does it mean ?

所以,我有4个工作中的3个,从这个链接iOS加密解密我能够解密从iOS加密的数据我在PHP端加密时遇到了麻烦。当我做回声加密代码。 PHP打印类似F>HFl8aR是什么意思?

SALTKEY = 'a16byteslongkey!';

SALTKEY ='a16byteslongkey!';

Decryption Code: Working

解密代码:工作

     $result =  mcrypt_decrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                               base64_decode($text), 'ecb');
     $pad_char = ord(substr($result, -1));
     return substr($result, 0, strlen($result) - $pad_char);

Encryption Code : Not Working

加密代码:不工作

     $result =  mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                               base64_encode($text), 'ecb');
     $pad_char = ord(substr($result, -1));
     return substr($result, 0, strlen($result) - $pad_char);
  • Results on iOS : Text = "Hello"
    Encryption = "7opqbb7sEVNoXplyQv/X8g=="
    Decryption of (7opqbb7sEVNoXplyQv/X8g==) = "Hello"

    iOS上的结果:Text =“Hello”Encryption =“7opqbb7sEVNoXplyQv / X8g ==”(7opqbb7sEVNoXplyQv / X8g ==)=“Hello”的解密

  • Results on PHP : Text = "7opqbb7sEVNoXplyQv/X8g=="
    Decryption = "Hello"
    Encryption of (Hello) = "_~TPn~p3MF?"

    关于PHP的结果:Text =“7opqbb7sEVNoXplyQv / X8g ==”Decryption =“Hello”加密(Hello)=“_〜TPn~p3MF?”

3 个解决方案

#1


3  

I think its fairly obvious that the IOS encryption is giving a 7-bit result (looks like base64 encoded) while the PHP is giving an 8-bit representation.

我认为很明显,IOS加密提供了7位结果(看起来像base64编码),而PHP提供了8位表示。

You don't seem to have got the hang of reversing the operation.

你似乎没有办法扭转操作。

The decryption is performed by base64_decodeing the input, then applying mcrypt_decrypt. It follows that to perform this in reverse, you'd need to first mcrypt_encrypt, and then base64_encode.

解密是通过base64_decodeing输入,然后应用mcrypt_decrypt来执行的。因此,要反过来执行此操作,您需要首先使用mcrypt_encrypt,然后再使用base64_encode。

i.e.

 $result =  base64_encode(
          mcrypt_encrypt(MCRYPT_RIJNDAEL_128, 
                (SALTKEY . str_repeat(chr(0x00), 16)), 
                $text, 'ecb'));

#2


2  

Your encryption looks very bogus:

您的加密看起来很虚伪:

 $result =  mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                           base64_encode($text), 'ecb');
 $pad_char = ord(substr($result, -1));
 return substr($result, 0, strlen($result) - $pad_char);

You encode the text with base64, then encrypt it, and then and then try to remove padding?

您使用base64对文本进行编码,然后对其进行加密,然后尝试删除填充?

Instead, you have to

相反,你必须

  • add padding (if the encryption function doesn't already do this),
  • 添加填充(如果加密功能尚未执行此操作),

  • encrypt
  • then base-64-encode the result (if you want to have it somehow readable by humans or transmit over a non-binary-safe channel).
  • 然后对结果进行base-64编码(如果你想让它以某种方式被人类读取或通过非二进制安全通道传输)。

This could look like this:

这看起来像这样:

$padded = pad($text);
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                       $padded, 'ecb');
$result = base64_encode($encrypted);

(Have a look at the user-contributed notes at the mcrypt_encrypt documentation for an example on how to create the padding.)

(有关如何创建填充的示例,请查看mcrypt_encrypt文档中的用户提供的说明。)

Of course, there are some more things to remark:

当然,还有一些事情需要注意:

  • Don't ever use ECB-mode, if you don't know anything about cryptography. It is an unsafe mode of operation. Use CBC-mode (with a random initialization vector, which is sent with the data).

    如果您对密码学一无所知,请不要使用ECB模式。这是一种不安全的操作方式。使用CBC模式(带随机初始化向量,随数据一起发送)。

  • You create your key by padding the SALTKEY with zeros. This makes your key in effect weaker than necessary. (Having a key hard-coded in the code is a bad idea anyways.) Supply a full 128-bit key, or derive one from a password using salt and a key derivation function (like PBKDF-2) with a high iteration count.

    您可以通过用零填充SALTKEY来创建密钥。这使得您的密钥效果比必要的要弱。 (在代码中使用密钥进行硬编码无论如何都是一个坏主意。)提供一个完整的128位密钥,或者使用salt和密钥派生函数(如PBKDF-2)从密码中导出一个密钥计数很高的密钥。

  • Your decryption function should also check that the padding is valid (i.e. consists of identical bytes), not simply removing it.

    您的解密函数还应检查填充是否有效(即由相同的字节组成),而不是简单地删除它。

  • You should also use a message authentication code (MAC) with your message, to avoid some chosen-ciphertext attacks which allow decrypting a message.

    您还应该在消息中使用消息身份验证代码(MAC),以避免某些允许解密消息的选择密文攻击。

#3


1  

see my post here: PHP iOS AES Encryption

在这里看到我的帖子:PHP iOS AES加密

I keep reposting this as I see the same question over and over.

我一直在重复这个问题,因为我一遍又一遍地看到同样的问题。


I just got through this same sort of project. I used the library you referenced in "also considered..."

我刚刚完成了同样的项目。我使用了你在“也考虑过......”中引用的库。

Here is some example code to decrypt with php:

这是一些用php解密的示例代码:

$iv2 = '';
for($i=0;$i<16;$i++){
    $iv2 .= "\0";   
}
$plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_text, MCRYPT_MODE_CBC, $iv2);
var_dump($plain_text_CBC);

Make sure your keys are both 256-bit (32 characters, I have not yet had any encoding issues, but if you do, remember that you are encrypting bytes, not characters). Note that 128 in MCRYPT_RIJNDAEL_128 is the block size and not the key size, while in the method AES256DecryptWithKey, 256 is a reference to the key size, while the block size is 128. AES256DecryptWithKey runs in CBC mode, but has a null initialization vector (iv).

确保你的密钥都是256位(32个字符,我还没有任何编码问题,但如果你这样做,请记住你正在加密字节,而不是字符)。请注意,MCRYPT_RIJNDAEL_128中的128是块大小而不是密钥大小,而在方法AES256DecryptWithKey中,256是对密钥大小的引用,而块大小是128. AES256DecryptWithKey在CBC模式下运行,但具有空初始化向量( ⅳ)。

CBC means that each block depends on the last block, and so it uses a pre-set, usually random, "block -1" called the IV

CBC意味着每个块依赖于最后一个块,因此它使用预设的,通常是随机的,“块-1”,称为IV

ECB means that each block is encrypted in the same way, hence it reveals when two blocks in the same message are the same. The library mentioned does not use it, so I mentioned it just for contrast.

ECB意味着每个块以相同的方式加密,因此它揭示了同一消息中的两个块是否相同。提到的图书馆没有使用它,所以我提到它只是为了对比。

The use of a zero iv (0000000000000000 in bytes) is considered insecure, but it does provide you with some additional security (but one might still be able to tell if the fist 16 characters of your plain text were the same each time). To fix this you would have to create an NSData *iv variable for the IV and modify the CCcrypt argument of NSData+AESCrypt.m to add [iv bytes] for the iv parameter (I have not yet tested this code), and you would need to store this iv and pass it to the php along with you message. But first I would test and have everything working with a zero iv.

使用零iv(0000000000000000,以字节为单位)被认为是不安全的,但它确实为您提供了一些额外的安全性(但是仍然可以判断您的纯文本的前16个字符是否每次都相同)。要解决这个问题,你必须为IV创建一个NSData * iv变量,并修改NSData + AESCrypt.m的CCcrypt参数,为iv参数添加[iv bytes](我还没有测试过这段代码),你会需要存储此iv并将其与您的消息一起传递给php。但首先,我会测试并使所有工作与零iv。

#1


3  

I think its fairly obvious that the IOS encryption is giving a 7-bit result (looks like base64 encoded) while the PHP is giving an 8-bit representation.

我认为很明显,IOS加密提供了7位结果(看起来像base64编码),而PHP提供了8位表示。

You don't seem to have got the hang of reversing the operation.

你似乎没有办法扭转操作。

The decryption is performed by base64_decodeing the input, then applying mcrypt_decrypt. It follows that to perform this in reverse, you'd need to first mcrypt_encrypt, and then base64_encode.

解密是通过base64_decodeing输入,然后应用mcrypt_decrypt来执行的。因此,要反过来执行此操作,您需要首先使用mcrypt_encrypt,然后再使用base64_encode。

i.e.

 $result =  base64_encode(
          mcrypt_encrypt(MCRYPT_RIJNDAEL_128, 
                (SALTKEY . str_repeat(chr(0x00), 16)), 
                $text, 'ecb'));

#2


2  

Your encryption looks very bogus:

您的加密看起来很虚伪:

 $result =  mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                           base64_encode($text), 'ecb');
 $pad_char = ord(substr($result, -1));
 return substr($result, 0, strlen($result) - $pad_char);

You encode the text with base64, then encrypt it, and then and then try to remove padding?

您使用base64对文本进行编码,然后对其进行加密,然后尝试删除填充?

Instead, you have to

相反,你必须

  • add padding (if the encryption function doesn't already do this),
  • 添加填充(如果加密功能尚未执行此操作),

  • encrypt
  • then base-64-encode the result (if you want to have it somehow readable by humans or transmit over a non-binary-safe channel).
  • 然后对结果进行base-64编码(如果你想让它以某种方式被人类读取或通过非二进制安全通道传输)。

This could look like this:

这看起来像这样:

$padded = pad($text);
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                       $padded, 'ecb');
$result = base64_encode($encrypted);

(Have a look at the user-contributed notes at the mcrypt_encrypt documentation for an example on how to create the padding.)

(有关如何创建填充的示例,请查看mcrypt_encrypt文档中的用户提供的说明。)

Of course, there are some more things to remark:

当然,还有一些事情需要注意:

  • Don't ever use ECB-mode, if you don't know anything about cryptography. It is an unsafe mode of operation. Use CBC-mode (with a random initialization vector, which is sent with the data).

    如果您对密码学一无所知,请不要使用ECB模式。这是一种不安全的操作方式。使用CBC模式(带随机初始化向量,随数据一起发送)。

  • You create your key by padding the SALTKEY with zeros. This makes your key in effect weaker than necessary. (Having a key hard-coded in the code is a bad idea anyways.) Supply a full 128-bit key, or derive one from a password using salt and a key derivation function (like PBKDF-2) with a high iteration count.

    您可以通过用零填充SALTKEY来创建密钥。这使得您的密钥效果比必要的要弱。 (在代码中使用密钥进行硬编码无论如何都是一个坏主意。)提供一个完整的128位密钥,或者使用salt和密钥派生函数(如PBKDF-2)从密码中导出一个密钥计数很高的密钥。

  • Your decryption function should also check that the padding is valid (i.e. consists of identical bytes), not simply removing it.

    您的解密函数还应检查填充是否有效(即由相同的字节组成),而不是简单地删除它。

  • You should also use a message authentication code (MAC) with your message, to avoid some chosen-ciphertext attacks which allow decrypting a message.

    您还应该在消息中使用消息身份验证代码(MAC),以避免某些允许解密消息的选择密文攻击。

#3


1  

see my post here: PHP iOS AES Encryption

在这里看到我的帖子:PHP iOS AES加密

I keep reposting this as I see the same question over and over.

我一直在重复这个问题,因为我一遍又一遍地看到同样的问题。


I just got through this same sort of project. I used the library you referenced in "also considered..."

我刚刚完成了同样的项目。我使用了你在“也考虑过......”中引用的库。

Here is some example code to decrypt with php:

这是一些用php解密的示例代码:

$iv2 = '';
for($i=0;$i<16;$i++){
    $iv2 .= "\0";   
}
$plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_text, MCRYPT_MODE_CBC, $iv2);
var_dump($plain_text_CBC);

Make sure your keys are both 256-bit (32 characters, I have not yet had any encoding issues, but if you do, remember that you are encrypting bytes, not characters). Note that 128 in MCRYPT_RIJNDAEL_128 is the block size and not the key size, while in the method AES256DecryptWithKey, 256 is a reference to the key size, while the block size is 128. AES256DecryptWithKey runs in CBC mode, but has a null initialization vector (iv).

确保你的密钥都是256位(32个字符,我还没有任何编码问题,但如果你这样做,请记住你正在加密字节,而不是字符)。请注意,MCRYPT_RIJNDAEL_128中的128是块大小而不是密钥大小,而在方法AES256DecryptWithKey中,256是对密钥大小的引用,而块大小是128. AES256DecryptWithKey在CBC模式下运行,但具有空初始化向量( ⅳ)。

CBC means that each block depends on the last block, and so it uses a pre-set, usually random, "block -1" called the IV

CBC意味着每个块依赖于最后一个块,因此它使用预设的,通常是随机的,“块-1”,称为IV

ECB means that each block is encrypted in the same way, hence it reveals when two blocks in the same message are the same. The library mentioned does not use it, so I mentioned it just for contrast.

ECB意味着每个块以相同的方式加密,因此它揭示了同一消息中的两个块是否相同。提到的图书馆没有使用它,所以我提到它只是为了对比。

The use of a zero iv (0000000000000000 in bytes) is considered insecure, but it does provide you with some additional security (but one might still be able to tell if the fist 16 characters of your plain text were the same each time). To fix this you would have to create an NSData *iv variable for the IV and modify the CCcrypt argument of NSData+AESCrypt.m to add [iv bytes] for the iv parameter (I have not yet tested this code), and you would need to store this iv and pass it to the php along with you message. But first I would test and have everything working with a zero iv.

使用零iv(0000000000000000,以字节为单位)被认为是不安全的,但它确实为您提供了一些额外的安全性(但是仍然可以判断您的纯文本的前16个字符是否每次都相同)。要解决这个问题,你必须为IV创建一个NSData * iv变量,并修改NSData + AESCrypt.m的CCcrypt参数,为iv参数添加[iv bytes](我还没有测试过这段代码),你会需要存储此iv并将其与您的消息一起传递给php。但首先,我会测试并使所有工作与零iv。