目次
AES 概述
填充算法
NUL("\0") 填充算法
Mcrypt
OpenSSL
加解密实例
ホームページ バックエンド開発 PHPチュートリアル Mcrypt を PHP から OpenSSL 暗号化アルゴリズムに移行するための詳細な紹介 (コード例)

Mcrypt を PHP から OpenSSL 暗号化アルゴリズムに移行するための詳細な紹介 (コード例)

Mar 04, 2019 pm 02:26 PM
aes mcrypt openssl php

本篇文章给大家带来的内容是关于php迁移Mcrypt至OpenSSL加密算法的详细介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

对称加解密算法中,当前最为安全的是 AES 加密算法(以前应该是是 DES 加密算法),PHP 提供了两个可以用于 AES 加密算法的函数簇:Mcrypt 和 OpenSSL。

其中 Mcrypt 在 PHP 7.1.0 中被 Deprecated,在 PHP 7.2.0 中被移除,所以即可起你应该使用 OpenSSL 来实现 AES 的数据加解密。

在一些场景下,我们不能保证两套通信系统都使用了相函数簇去实现加密算法,可能 siteA 使用了最新的 OpenSSL 来实现了 AES 加密,但作为第三方服务的 siteB 可能仍在使用 Mcrypt 算法,这就要求我们必须清楚 Mcrypt 同 OpenSSL 之间的差异,以便保证数据加解密的一致性。

下文中我们将分别使用 Mcrypt 和 OpenSSL 来实现 AES-128/192/256-CBC 加解密,二者同步加解密的要点为:

1、使用何种填充算法。Mcrypt 自动使用 NUL("\\0"),OpenSSL 自动使用 PKCS7。
2、否对数据做了base64编码处理。Mcrypt 默认不使用 base64 编码(虽然我们很建议使用),OpenSSL 默认使用 base64编码。

协同好以上两点,就可以让 Mcrypt 和 OpenSSL 之间一致性的对数据进行加解密。

AES 概述

AES 是当前最为常用的安全对称加密算法,关于对称加密这里就不在阐述了。

AES 有三种算法,主要是对数据块的大小存在区别:
AES-128:需要提供 16 位的密钥 key
AES-192:需要提供 24 位的密钥 key
AES-256:需要提供 32 位的密钥 key

填充算法

AES 是按数据块大小(128/192/256)对待加密内容进行分块处理的,会经常出现最后一段数据长度不足的场景,这时就需要填充数据长度到加密算法对应的数据块大小。

主要的填充算法有填充 NUL("0") 和 PKCS7,Mcrypt 默认使用的 NUL("0") 填充算法,当前已不被推荐,OpenSSL 则默认模式使用 PKCS7 对数据进行填充并对加密后的数据进行了 base64encode 编码,所以建议开发中使用 PKCS7 对待加密数据进行填充,已保证通用性(alipay sdk 中虽然使用了 Mcrypt 加密簇,但使用 PKCS7 算法对数据进行了填充,这样在一定程度上亲和了 OpenSSL 加密算法)。

NUL("\0") 填充算法

Mcrypt 的默认填充算法。NUL 即为 Ascii 表的编号为 0 的元素,即空元素,转移字符是 "\0",PHP 的 pack 打包函数在 'a' 模式下就是以 NUL 字符对内容进行填充的,当然,使用 "\0" 手动拼接也是可以的。

/**
 * NUL("\0")填充算法
 * @param string $source
 * @return string
 */
function addZeroPadding($source, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC)
{
    $source = trim($source);
    // openssl 并没有提供加密cipher对应的数据块大小的api这点比较坑
    $block = mcrypt_get_block_size($cipher, $mode);
    $pad   = $block - (strlen($source) % $block);
    if ($pad <= $block) {
        // $source .= str_repeat("\0", $pad);//KISS写法
        // pack 方法 a 模式使用 NUL("\0") 对内容进行填充  A 模式则使用空白字符填充
        $source .= pack("a{$pad}", ""); //高端写法
    }
    return $source;
}

/**
 * NUL("\0")填充算法移除
 * @param string $source
 * @return string
 */
function stripZeroPadding($source)
{
    return rtrim($source, "\0");
}
ログイン後にコピー

PKCS7 填充算法

OpenSSL的默认填充算法。下面我们给出 PKCS7 填充算法 PHP 的实现:

/**
 * PKCS7填充算法
 * @param string $source
 * @return string
 */
function addPKCS7Padding($source, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC)
{
    $source = trim($source);
    $block  = mcrypt_get_block_size($cipher, $mode);
    $pad    = $block - (strlen($source) % $block);
    if ($pad <= $block) {
        $char = chr($pad);
        $source .= str_repeat($char, $pad);
    }
    return $source;
}

/**
 * 移去PKCS7填充算法
 * @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;
}
ログイン後にコピー

Mcrypt

默认使用 NUL("\0") 自动对待加密数据进行填充以对齐加密算法数据块长度。

获取 mcrypt 支持的算法,这里我们只关注 AES 算法。

$cipher_list = mcrypt_list_algorithms();
print_r($cipher_list);

//  加密算法名称  对应的 常量标识
// 'rijndael-128' == MCRYPT_RIJNDAEL_128
// 'rijndael-192' == MCRYPT_RIJNDAEL_192
// 'rijndael-256' == MCRYPT_RIJNDAEL_256
ログイン後にコピー

注意:mcrypt 虽然支持 AES 三种算法,但除 MCRYPT_RIJNDAEL_128 外,MCRYPT_RIJNDAEL_192/256 并未遵循 AES-192/256 标准进行加解密的算法,即如果你同其他系统通信(java/.net),使用 MCRYPT_RIJNDAEL_192/256 可能无法被其他严格按照 AES-192/256 标准的系统正确的数据解密。官方文档页面中也有人在 User Contributed Notes 中提及。这里给出如何使用 mcrpyt 做标注的 AES-128/192/256 加解密

AES-128-CBC = mcrpyt(cipher MCRYPT_RIJNDAEL_128 + key 16位 + iv 16 位 + mode MCRYPT_MODE_CBC)
AES-192-CBC = mcrpyt(cipher MCRYPT_RIJNDAEL_128 + key 24位 + iv 16 位 + mode MCRYPT_MODE_CBC)
AES-256-CBC = mcrpyt(cipher MCRYPT_RIJNDAEL_128 + key 32位 + iv 16 位 + mode MCRYPT_MODE_CBC)

即算法统一使用 MCRYPT_RIJNDAEL_128,并通过 key 的位数 来选定是以何种 AES 标准做的加密,iv 是建议添加且建议固定为16位(OpenSSL的 AES加密 iv 始终为 16 位,便于统一对齐),mode 选用的 CBC 模式。

mcrypt 在对数据进行加密处理时,如果发现数据长度与使用的加密算法的数据块长度未对齐,则会自动使用 "\0" 对待加密数据进行填充,但 "\0" 填充模式已不再被推荐,为了与其他系统有更好的兼容性,建议大家手动对数据进行 PKCS7 填充。

OpenSSL

openssl 簇加密方法更为简单明确,mcrypt 还要将加密算法分为 cipher + mode 去指定,openssl 则只需要直接指定 method 为 AES-128-CBC,AES-192-CBC,AES-256-CBC 即可。且提供了三种数据处理模式,即 默认模式 0 / OPENSSL_RAW_DATA/ OPENSSL_ZERO_PADDING。

openssl 默认的数据填充方式是 PKCS7,为兼容 mcrpty 也提供处理 "0" 填充的数据的模式,具体为下: 

//我们只看部分参数 还有一些默认参数没列出
// 加密
openssl_encrypt(string $data, string $method, string $key, int $options = 0, string $iv = "")
// 解密
openssl_decrypt(string $data, string $method, string $key, int $options = 0, string $iv = "")
ログイン後にコピー

options 参数即为重要,它是兼容 mcrpty 算法的关键:

options = 0: 默认模式,自动对明文进行 pkcs7 padding,且数据做 base64 编码处理。
options = 1: OPENSSL_RAW_DATA,自动对明文进行 pkcs7 padding, 且数据未经 base64 编码处理。
options = 2: OPENSSL_ZERO_PADDING,要求待加密的数据长度已按 "0" 填充与加密算法数据块长度对齐,即同 mcrpty 默认填充的方式一致,且对数据做 base64 编码处理。注意,此模式下 openssl 要求待加密数据已按 "0" 填充好,其并不会自动帮你填充数据,如果未填充对齐,则会报错。

故可以得出 mcrpty簇 与 openssl簇 的兼容条件如下:

1、如果 A 系统使用了 mcrypt 的默认的 "\0" 自动填充算法进行了数据加密,那 B 系统使用 openssl 进行解密时,需要选择 OPENSSL_ZERO_PADDING 模式。这里同时要特别注意,OPENSSL_ZERO_PADDING 模式是认为数据是做了 base64 编码处理的,如果 A 系统 mcrpty 没有对数据做 base64_encode 处理,则 B 解密数据时还需要将数据 base64_encode 后再传递给 openssl_decrypt。
2、如果 A 系统手动使用了 PKCS7 对待加密数据做了处理,那 B 系统只需根据 A 系统是否对数据做了 base64 编码处理选择 0或 OPENSSL_ZERO_PADDING 模式即可。如果对 A 使用了 base64 编码,则 B 使用 0 模式;如果 A 没有使用 base64 编码,则使用 OPENSSL_RAW_DATA 模式。

加解密实例

建议将源码复制到本地运行,根据运行结果更好理解。

ログイン後にコピー

总结要点

1、二者使用的何种填充算法。
2、二者对数据是否有 base64 编码要求。
3、mcrypt 需固定使用 MCRYPT_RIJNDAEL_128,并通过调整 key 的长度 16, 24,32 来实现 ase-128/192/256 加密算法。同时二者 IV 长度都应该是。

以上がMcrypt を PHP から OpenSSL 暗号化アルゴリズムに移行するための詳細な紹介 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

今まで知らなかったことを後悔している 7 つの PHP 関数 今まで知らなかったことを後悔している 7 つの PHP 関数 Nov 13, 2024 am 09:42 AM

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? Apr 03, 2025 am 12:03 AM

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。

See all articles