您现在的位置是:首页 > 技术教程 正文

【PHP】对称加密算法 AES-256-GCM 代码示例

admin 阅读: 2024-03-17
后台-插件-广告管理-内容页头部广告(手机)

前言

下面介绍在PHP代码中,如何对数据进行 AES-256-GCM 加密和解密。我们可以使用 openssl 和 sodium 扩展来实现加密,它们都支持 AES-256-GCM 算法,下面将给出两种扩展的代码示例。

注:在对称加密算法中,除了应用广泛的 AES 以外,还有一种名为 ChaCha20-Poly1305 的新式加密算法,它的性能比 AES 更好(如果CPU支持AES指令硬件加速,则AES性能更好),安全性也不输AES。sodium 扩展支持 ChaCha20-Poly1305。

环境

PHP 7.3

一、使用openssl扩展

<?php function aes256gcm_encrypt(string $data, string $keygen, string $aad = ''): array { $cipher = 'aes-256-gcm'; $ivLen = openssl_cipher_iv_length($cipher); $iv = random_bytes($ivLen); // 12字节的iv $encrypt = openssl_encrypt($data, $cipher, $keygen, OPENSSL_RAW_DATA, $iv,$tag, $aad); return [ 'iv' => base64_encode($iv), 'tag' => base64_encode($tag), 'aad' => base64_encode($aad), 'cipher_text' => base64_encode($encrypt), ]; } function aes256gcm_decrypt(array $secretData, string $keygen) { $iv = base64_decode($secretData['iv']); $tag = base64_decode($secretData['tag']); $aad = base64_decode($secretData['aad']); $cipherText = base64_decode($secretData['cipher_text']); $cipher = 'aes-256-gcm'; return openssl_decrypt($cipherText, $cipher, $keygen, OPENSSL_RAW_DATA, $iv, $tag, $aad); } function main() { // AES-256-GCM需要32字节的密钥 $keygen = bin2hex(random_bytes(16)); // 加密 $data = 'Hello World!'; $secretData = aes256gcm_encrypt($data, $keygen, 'foobar'); // 解密 $plainText = aes256gcm_decrypt($secretData, $keygen); echo "原文:$data\n"; echo "密文数据:" . json_encode($secretData) . "\n"; echo "解密后:$plainText\n"; } main();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

二、使用 sodium 扩展

<?php function aes256gcm_encrypt(string $data, string $keygen, string $aad = ''): array { $iv = random_bytes(SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES); $encrypt = sodium_crypto_aead_aes256gcm_encrypt($data, $aad, $iv, $keygen); // 包含密文、tag return [ 'iv' => sodium_bin2base64($iv, SODIUM_BASE64_VARIANT_ORIGINAL), 'aad' => sodium_bin2base64($aad, SODIUM_BASE64_VARIANT_ORIGINAL), 'cipher_text' => sodium_bin2base64($encrypt, SODIUM_BASE64_VARIANT_ORIGINAL), ]; } function aes256gcm_decrypt(array $secretData, string $keygen) { $iv = sodium_base642bin($secretData['iv'], SODIUM_BASE64_VARIANT_ORIGINAL); $aad = sodium_base642bin($secretData['aad'], SODIUM_BASE64_VARIANT_ORIGINAL); $cipherText = sodium_base642bin($secretData['cipher_text'], SODIUM_BASE64_VARIANT_ORIGINAL); return sodium_crypto_aead_aes256gcm_decrypt($cipherText, $aad, $iv, $keygen); } function main() { if (!sodium_crypto_aead_aes256gcm_is_available()) { exit('Not support AES-256-GCM'); } // 生成AES-256-GCM的密钥 $keygen = sodium_crypto_aead_aes256gcm_keygen(); // 加密 $data = 'Hello World!'; $secretData = aes256gcm_encrypt($data, $keygen, 'foobar'); // 解密 $plainText = aes256gcm_decrypt($secretData, $keygen); echo "原文:$data\n"; echo "密文数据:" . json_encode($secretData) . "\n"; echo "解密后:$plainText\n"; } main();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

AAD参数(Additional Authenticated Data)

在上面的代码示例中,可以看到在加密的时候有一个$aad参数,如果在加密的时候使用了这个参数,那么在解密时也需要使用同样的AAD值才能成功解密。

什么时候会需要用到AAD呢?下面举个例子:
用户Alice在CSDN博客上写了一篇私密文章,CSDN使用 AES-256-GCM 加密了这篇文章,然后存储到了数据库里,AAD的取值是Alice的用户ID。

后续如果Alice去查看这篇文章,CSDN会使用Alice的用户ID(AAD值)去解密,因为解密的AAD值与加密的AAD值相同,所以可以成功解密。

然后有一个黑客Bob,他也向CSDN发出解密这篇文章的请求,CSDN就会使用Bob的用户ID作为AAD去解密这篇文章,但因为AAD值错误,肯定是解密不了的,所以这时候AAD的作用就体现了出来。

参阅

  • https://cloud.google.com/kms/docs/additional-authenticated-data?hl=zh-cn
标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索