Heim >Backend-Entwicklung >PHP-Tutorial >Einführung in die Verwendung von OpenSSL als Ersatz für Mcrypt in PHP7.1
In der PHP-Entwicklung kann die Verwendung von mcrypt-bezogenen Funktionen problemlos AES-Verschlüsselungs- und -Entschlüsselungsvorgänge durchführen, aber die mcrypt-Erweiterung wird in PHP7.1 aufgegeben, sodass Sie eine andere finden müssen Art der Erkenntnis. Das Ersetzen von mcrypt durch openssl wird bereits im Migrationshandbuch erwähnt, es wird jedoch kein konkretes Beispiel gegeben. Es gibt online viele Beispiele, die die meisten Szenarien ersetzen können, aber die Details werden nicht erklärt. Ebenso kann die einfache Verwendung von Online-Beispielen in bestimmten Codeszenarien zu Kompatibilitätsproblemen vor und nach dem Ersetzen des Codes führen. Lassen Sie uns weiter unten über die spezifischen Codes und Gründe sprechen.
Zuerst geben wir den Ersatzcode direkt an und analysieren dann das Problem anhand des Codes. (Der in diesem Artikel analysierte Algorithmus ist AES-128-CBC)
Das Beispiel zeigt zwei Möglichkeiten der Verwendung von mcrypt, hauptsächlich beim Padding Unterschiedlich (Polsterung wird weiter unten erklärt). Während des gesamten Verschlüsselungs- und Entschlüsselungsprozesses implementiert ein vollständigerer Code das Füllen und Entfernen des Füllens automatisch, und ein einfacherer Code ignoriert das Füllen direkt, aber beide Methoden können in der tatsächlichen Entwicklung normal ausgeführt werden (Versionen vor 7.1). Es wird empfohlen um Polsterung hinzuzufügen. Bitte sehen Sie sich das folgende konkrete Beispiel an:
mcrypt verwendet kein Padding
mcrypt-Verschlüsselung:
$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);
Öffnet SSL-Verschlüsselungscode mit der gleichen Funktion:
$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));
mcrypt verwendet Auffüllung
mcrypt-Verschlüsselung:
$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);
OpenSSL-Verschlüsselungscode für die gleiche Funktion:
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; return bin2hex(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
Die obigen Beispiele können erfolgreich ausgeführt werden, wobei das erste Beispiel ( (kein Padding verwendet, aber mit Padding in OpenSSL) und im zweiten Beispiel (mit Padding, ohne Padding in OpenSSL) ist die Ausgabe vor und nach dem Ersetzen dieselbe und es gibt keine Kompatibilitätsprobleme. Sie können verschiedene Ersatzlösungen basierend auf den unterschiedlichen Füllmethoden des Codes auswählen, es gibt jedoch drei Details, die erklärt werden müssen
Warum gibt es eine Polsterung?
Warum unterscheiden sich die Namen der Algorithmen, nachdem sie durch openssl ersetzt wurden?
Im Folgenden finden Sie eine detaillierte Analyse der Füllung und des Algorithmus.
Warum es Padding gibt, beginnt mit dem Verschlüsselungsalgorithmus. Denn im AES-128-CBC-Algorithmus wird die zu verschlüsselnde Zeichenfolge alle 16 Bytes in Segmente segmentiert und Schritt für Schritt berechnet, was dazu führt, dass Segmente mit weniger als 16 Bytes gefüllt werden. Daher gibt es zwei Arten von Beispielen: Zum einen wird die Standardfüllung verwendet, zum anderen wird die unabhängige Füllung verwendet. Beim Ersetzen von OpenSSL erfordert die Auswahl des Auffüllschemas Kenntnisse über die standardmäßige und autonome Auffüllung von mcrypt und OpenSSL.
mcrypt-Standardauffüllung
Im Quellcode von PHP ist zu sehen, dass die Standardauffüllung mit x00
erfolgt. Tatsächlich ist sie nicht mit aufgefüllt x00
Aus dem Quellcode geht hervor, dass zuerst eine 16-Bit-Leerzeichenfolge angewendet wird, sodass jedes Byte während der Initialisierung x00
ist. Tatsächlich kann man sagen, dass es keine Auffüllung gibt, aber Es ist ursprünglich x00
. Verwenden Sie die Standardeinstellung. Die aufgefüllte verschlüsselte Zeichenfolge hat die folgende Form:
, daher muss das überflüssige x00
beim Entschlüsseln entfernt werden. Natürlich können Sie auch faul sein und x00
nicht entfernen. Da in PHP die Zeichenfolge „stringx00“ und die Zeichenfolge „string“ bis auf die Länge die gleiche Leistung haben, scheint es keinen Unterschied zu geben. Der folgende Code:
// 尾部包含若干个`\x00` 均可功输出true if ("string\x00" == "string") { // 用双引号可解析\x00 echo true; }
x00
Ausgefülltes Beispiel (Bitte Beachten Sie die Länge der Zeichenfolge. Es ist ersichtlich, dass sich das Auffüllen mit x00
auf die Länge auswirkt Algorithmus Es muss gemäß dem folgenden Algorithmus ausgeführt werden:
/** * 填充算法 * @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; }Nach dem Hinzufügen der Auffüllung hat die Zeichenfolge tatsächlich die folgende Form:
Auffüllung entfernen
/** * 移去填充算法 * @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; }
Es ist zu beachten, dass Auffüllen und Auffüllen-Entfernen in
undintegriert sind. also direkt Verwenden Sie es einfach. Sofern Sie das Füllen nicht unabhängig implementieren müssen, müssen Sie nicht über das Füllen nachdenken
openssl-unabhängiges Füllen openssl_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的填充方式也为Einführung in die Verwendung von OpenSSL als Ersatz für Mcrypt in PHP7.1,故直接使用即可。
分析到这,可以发现,无论是何种填充策略都需注意在加密时加入填充,在解密时则必须要移除填充。至此,上文中示例中的填充相关则分析完成了,接下来我们再看看如何选择替换后的算法。
在以上的示例中,有一个问题在于,mcrypt中的AES-128-CBC算法,在openssl中怎么替换成了AES_256?
关于这一点, 我也未找到合理的解释,查看源码一时半会也没找到原因(能力有限~),但通过以下资料,还是完成了功能
openssl 解密 mcrypt AES 数据不兼容问题
Convert mcrypt_generic to openssl_encrypt Ask Question
若是有同学找到原因,欢迎给我留言,谢谢。
对于使用mcrypt AES 进行加密密的部分,若是在替换过程中问题, 可以从算法替换或填充这两方面着手考虑下。同时还是一必须满足的条件是根据不同的填充方式选择, 替换最重要的就要考虑兼容问题,保证替换后不发生任何改变。 虽然只是只是有细微的差别----尾部几个字符串的不同,但若是在多平台中同时进行修改也是一件麻烦事,但变动越少风险越小。
本文只是针对AES算法进行了简单说明,对于其他算法是否适用还有待研究。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
Das obige ist der detaillierte Inhalt vonEinführung in die Verwendung von OpenSSL als Ersatz für Mcrypt in PHP7.1. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!