(L'algorithme analysé dans cet article est AES-128-CBC)
Exemple de remplacementL'exemple montrera deux façons d'utiliser mcrypt, principalement enpadding Différent (Rembourrage sera expliqué ci-dessous). Pendant tout le processus de cryptage et de déchiffrement, le code le plus complet implémentera automatiquement le remplissage et la suppression du remplissage, et le code le plus simple ignorera directement le remplissage, mais les deux méthodes peuvent fonctionner normalement dans le développement réel (versions antérieures à 7.1), il est recommandé ; pour ajouter du rembourrage. Veuillez consulter l'exemple spécifique suivant :
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($cipher, $key, $iv); $cipherText256 = mcrypt_generic($cipher, $data); mcrypt_generic_deinit($cipher); return bin2hex($cipherText256);
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; $data = $data . str_repeat("\x00", 16 - (strlen($data) % 16)); // 双引号可以解析asc-ii码\x00 return bin2hex(openssl_encrypt($data, "AES-256-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; // 填充(移除填充反着移除即可) $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $pad = $block - (strlen($data) % $block); if ($pad <= $block) { $char = chr($pad); $data .= str_repeat($char, $pad); } $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($cipher, $key, $iv); $cipherText256 = mcrypt_generic($cipher, $data); mcrypt_generic_deinit($cipher); return bin2hex($cipherText256);
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; return bin2hex(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
remplissage et de l'algorithme.
RemplissageLa raison pour laquelle il y a un remplissage commence par l'algorithme de cryptage. Parce que dans l'algorithme AES-128-CBC, la chaîne à chiffrer sera segmentée en segments tous les 16 octets de longueur et calculée étape par étape, ce qui entraînera le remplissage de segments de moins de 16 octets. Il existe donc deux types d'exemples donnés : l'un consiste à utiliser le remplissage par défaut et l'autre à utiliser un remplissage indépendant. Lors du remplacement d'openssl, comment choisir le schéma de remplissage nécessite une compréhension du remplissage par défaut et autonome de mcrypt et openssl. En fait, il n'est pas complété avec. x00
, on peut trouver à partir du code source qu'une chaîne vide de 16 bits est d'abord demandée, donc chaque octet est x00
lors de l'initialisation. En fait, on peut dire qu'il n'y a pas de remplissage, mais. il s'agit à l'origine de x00
. Utilisez la valeur par défaut. La chaîne cryptée complétée sera sous la forme suivante : x00
redondant doit donc être supprimé lors du déchiffrement. Bien sûr, vous pouvez aussi être paresseux et ne pas supprimer x00
. Parce qu'en php, la chaîne "stringx00" et la chaîne "string" ont les mêmes performances sauf pour la longueur, donc il ne semble y avoir aucune différence. Le code suivant : x00
// 尾部包含若干个`\x00` 均可功输出true if ("string\x00" == "string") { // 用双引号可解析\x00 echo true; }
Après remplissage. Exemple de : (Veuillez faire attention à la longueur de la chaîne, on peut voir que le remplissage avec x00
affectera la longueur) L'algorithme de remplissage doit être effectué comme suit : x00
Supprimer le remplissage
/** * 填充算法 * @param string $source * @return string */ function addPKCS7Padding($source) { $source = trim($source); $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $pad = $block - (strlen($source) % $block); if ($pad <= $block) { $char = chr($pad); $source .= str_repeat($char, $pad); } return $source; }
/** * 移去填充算法 * @param string $source * @return string */ function stripPKSC7Padding($source) { $source = trim($source); $char = substr($source, -1); $num = ord($char); if ($num == 62) return $source; $source = substr($source, 0, -$num); return $source; }
et
, donc directement, utilisez-le simplement. À moins que vous n'ayez besoin d'implémenter le remplissage indépendamment, il n'est pas nécessaire d'envisager le remplissageremplissage indépendant opensslopenssl_encrypt提供了option参数以支持自主填充,但在查阅php源码中openssl的测试用例代码才找到正确用法:
// if we want to manage our own padding $padded_data = $data . str_repeat(' ', 16 - (strlen($data) % 16)); $encrypted = openssl_encrypt($padded_data, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); $output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); var_dump(rtrim($output));
(备注:如上,OPENSSL_ZERO_PADDING
并非是为0填充的意思)
由此,我们就可以解释,在第一个示例中openssl_encrypt之前加入了自主点充\x00
的代码原因了
从以上的加、解密针对填充逻辑不同,针对上文中的示例可以很好地解释:
示例1:
mcrypt加密时未使用填充,故以\x00
进行了填充,所以在替换成openssl,需要自主实现\x00
填充。
示例2:
mcrypt加密时使用了标准的填充,同时openssl的填充方式也为Introduction à lutilisation dopenssl pour remplacer mcrypt dans PHP7.1,故直接使用即可。
分析到这,可以发现,无论是何种填充策略都需注意在加密时加入填充,在解密时则必须要移除填充。至此,上文中示例中的填充相关则分析完成了,接下来我们再看看如何选择替换后的算法。
在以上的示例中,有一个问题在于,mcrypt中的AES-128-CBC算法,在openssl中怎么替换成了AES_256?
关于这一点, 我也未找到合理的解释,查看源码一时半会也没找到原因(能力有限~),但通过以下资料,还是完成了功能
openssl 解密 mcrypt AES 数据不兼容问题
Convert mcrypt_generic to openssl_encrypt Ask Question
若是有同学找到原因,欢迎给我留言,谢谢。
对于使用mcrypt AES 进行加密密的部分,若是在替换过程中问题, 可以从算法替换或填充这两方面着手考虑下。同时还是一必须满足的条件是根据不同的填充方式选择, 替换最重要的就要考虑兼容问题,保证替换后不发生任何改变。 虽然只是只是有细微的差别----尾部几个字符串的不同,但若是在多平台中同时进行修改也是一件麻烦事,但变动越少风险越小。
本文只是针对AES算法进行了简单说明,对于其他算法是否适用还有待研究。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!