您如何加密和解密PHP字符串?


225

我的意思是:

Original String + Salt or Key --> Encrypted String
Encrypted String + Salt or Key --> Decrypted (Original String)

也许像这样:

"hello world!" + "ABCD1234" --> Encrypt --> "2a2ffa8f13220befbe30819047e23b2c" (may be, for e.g)
"2a2ffa8f13220befbe30819047e23b2c" --> Decrypt with "ABCD1234" --> "hello world!"
  • 在PHP中,您该怎么做?

尝试使用Crypt_Blowfish,但对我不起作用。


35
@Rogue他不想要哈希,他想要对称加密(例如AES),他只是不知道它叫什么。(现在他做了:))
Patashu

它需要多安全?

3
@夏期剧场,您不对盐进行对称加密,而是使用密钥。密钥必须保密。盐可以是公开的,而不会损害安全性(只要每个人的盐都不同),并且它是哈希密码中使用的术语。
Patashu

2
您需要一个Salt(私有密钥),一个公共密钥以及一个类似于AES-256的加密算法:wpy.me/blog/15-encrypt-and-decrypt-data-in-php-using-aes-256
wappy

8
@CristianFlorea该博客文章的作者使用的术语在对称加密的上下文中根本没有丝毫意义。AES没有公钥,也没有盐。只有一把钥匙;它必须保密。在某些操作模式下,有一个IV不必是秘密的,但IV并不是盐(取决于模式,它可能具有完全不同的要求)并且也不必是秘密的,而实际的加密密钥绝对不能公开。公钥/私钥适用于非对称加密,但与AES无关。
cpast

Answers:


410

在您进一步进行操作之前,请尝试了解加密身份验证之间的区别,以及为什么您可能想要经过身份验证的加密而不是仅加密

要实施经过身份验证的加密,您需要先加密然后再加密MAC。加密和身份验证的顺序非常重要!对这个问题的现有答案之一就是这个错误。就像许多用PHP编写的密码库一样。

您应该避免实施自己的加密技术,而应使用由加密专家编写和审查的安全库。

更新:PHP 7.2现在提供libsodium!为了获得最佳安全性,请更新系统以使用PHP 7.2或更高版本,并且仅遵循此答案中的libsodium建议。

如果您具有PECL访问权限,请使用libsodium(如果要没有PECL的libsodium,请使用sodium_compat);否则...
使用defuse / php-encryption ; 不要使用自己的密码!

上面链接的两个库都可以轻松轻松地将经过身份验证的加密实施到您自己的库中。

如果您仍然想编写和部署自己的密码库,那么与Internet上每位密码专家的传统智慧相反,这些都是您必须采取的步骤。

加密:

  1. 在CTR模式下使用AES加密。您也可以使用GCM(这样就不需要单独的MAC)。此外,ChaCha20和Salsa20(由libsodium提供)是流密码,不需要特殊模式。
  2. 除非您在上面选择了GCM,否则应使用HMAC-SHA-256(或对于流密码为Poly1305,大多数libsodium API会为您执行此操作)对密文进行身份验证。MAC应该包含IV和密文!

解密:

  1. 除非使用Poly1305或GCM,否则请重新计算密文的MAC,并将其与使用发送的MAC进行比较hash_equals()。如果失败,请中止。
  2. 解密消息。

其他设计注意事项:

  1. 永远不要压缩任何东西。密文不可压缩;在加密之前压缩明文会导致信息泄漏(例如TLS上的CRIME和BREACH)。
  2. 确保使用mb_strlen()mb_substr(),使用'8bit'字符集模式以防止出现mbstring.func_overload问题。
  3. IVs应该使用CSPRNG生成;如果您正在使用mcrypt_create_iv()请勿使用MCRYPT_RAND
  4. 除非您使用AEAD构造,否则总是先加密然后再加密MAC!
  5. bin2hex()base64_encode()等等可能会通过缓存时间泄露有关您的加密密钥的信息。尽可能避免使用它们。

即使您遵循此处给出的建议,加密也会出错。始终请加密专家检查您的实施。如果您没有幸与本地大学的密码学学生成为私人朋友,则可以随时尝试使用密码学堆栈交换论坛寻求建议。

如果您需要对实现进行专业分析,则始终可以聘请声誉卓著的安全顾问团队来审查您的PHP密码代码(公开:我的雇主)。

重要事项:何时不使用加密

不要加密密码。你想他们,而不是使用这些密码散列算法之一:

切勿将通用哈希函数(MD5,SHA256)用于密码存储。

不要加密URL参数这是工作的错误工具。

带有Libsodium的PHP字符串加密示例

如果您使用的是PHP <7.2或未安装libsodium,则可以使用sodium_compat来完成相同的结果(尽管速度较慢)。

<?php
declare(strict_types=1);

/**
 * Encrypt a message
 * 
 * @param string $message - message to encrypt
 * @param string $key - encryption key
 * @return string
 * @throws RangeException
 */
function safeEncrypt(string $message, string $key): string
{
    if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
        throw new RangeException('Key is not the correct size (must be 32 bytes).');
    }
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

    $cipher = base64_encode(
        $nonce.
        sodium_crypto_secretbox(
            $message,
            $nonce,
            $key
        )
    );
    sodium_memzero($message);
    sodium_memzero($key);
    return $cipher;
}

/**
 * Decrypt a message
 * 
 * @param string $encrypted - message encrypted with safeEncrypt()
 * @param string $key - encryption key
 * @return string
 * @throws Exception
 */
function safeDecrypt(string $encrypted, string $key): string
{   
    $decoded = base64_decode($encrypted);
    $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');

    $plain = sodium_crypto_secretbox_open(
        $ciphertext,
        $nonce,
        $key
    );
    if (!is_string($plain)) {
        throw new Exception('Invalid MAC');
    }
    sodium_memzero($ciphertext);
    sodium_memzero($key);
    return $plain;
}

然后测试一下:

<?php
// This refers to the previous code block.
require "safeCrypto.php"; 

// Do this once then store it somehow:
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
$message = 'We are all living in a yellow submarine';

$ciphertext = safeEncrypt($message, $key);
$plaintext = safeDecrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Halite-使Libsodium更容易

一个我一直在工作的项目是称为加密库岩盐,使libsodium更简单,更直观,其目的。

<?php
use \ParagonIE\Halite\KeyFactory;
use \ParagonIE\Halite\Symmetric\Crypto as SymmetricCrypto;

// Generate a new random symmetric-key encryption key. You're going to want to store this:
$key = new KeyFactory::generateEncryptionKey();
// To save your encryption key:
KeyFactory::save($key, '/path/to/secret.key');
// To load it again:
$loadedkey = KeyFactory::loadEncryptionKey('/path/to/secret.key');

$message = 'We are all living in a yellow submarine';
$ciphertext = SymmetricCrypto::encrypt($message, $key);
$plaintext = SymmetricCrypto::decrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

所有基础加密都由libsodium处理。

defuse / php-encryption的示例

<?php
/**
 * This requires https://github.com/defuse/php-encryption
 * php composer.phar require defuse/php-encryption
 */

use Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;

require "vendor/autoload.php";

// Do this once then store it somehow:
$key = Key::createNewRandomKey();

$message = 'We are all living in a yellow submarine';

$ciphertext = Crypto::encrypt($message, $key);
$plaintext = Crypto::decrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

注意Crypto::encrypt()返回十六进制编码的输出。

加密密钥管理

如果您想使用“密码”,请立即停止。您需要一个随机的128位加密密钥,而不是一个让人难忘的密码。

您可以存储加密密钥以便长期使用,如下所示:

$storeMe = bin2hex($key);

而且,您可以按需检索它,如下所示:

$key = hex2bin($storeMe);

强烈建议您存储一个随机生成的密钥以供长期使用,而不要使用任何形式的密码作为密钥(或派生密钥)。

如果您使用的是Defuse的库:

“但是我真的很想使用密码。”

那是个坏主意,但是好吧,这是安全地做这件事的方法。

首先,生成一个随机密钥并将其存储在常量中。

/**
 * Replace this with your own salt! 
 * Use bin2hex() then add \x before every 2 hex characters, like so:
 */
define('MY_PBKDF2_SALT', "\x2d\xb7\x68\x1a\x28\x15\xbe\x06\x33\xa0\x7e\x0e\x8f\x79\xd5\xdf");

请注意,您要添加额外的工作,并且可以仅使用此常量作为键并为自己节省很多心痛!

然后,使用PBKDF2(像这样)从您的密码中得出合适的加密密钥,而不是直接使用您的密码进行加密。

/**
 * Get an AES key from a static password and a secret salt
 * 
 * @param string $password Your weak password here
 * @param int $keysize Number of bytes in encryption key
 */
function getKeyFromPassword($password, $keysize = 16)
{
    return hash_pbkdf2(
        'sha256',
        $password,
        MY_PBKDF2_SALT,
        100000, // Number of iterations
        $keysize,
        true
    );
}

不要只使用16个字符的密码。您的加密密钥将被可笑地破坏。


3
不要对密码进行加密,对其进行散列并通过对其进行password_hash()检查password_verify()
Scott Arciszewski 2015年

2
“永远不要压缩任何东西。” 您的意思是像HTTP,spdy等协议一样吗?在TLS之前?专制主义者的建议多少?
Tiberiu-Ionuț Stan 2016年

1
@ScottArciszewski我喜欢您对键的评论“ //是否以某种方式将其存储一次:” ..以某种方式,大声笑:))那么如何将此键(作为对象)存储为硬编码的纯字符串呢?我需要密钥本身,作为字符串。我能以某种方式从这个物体上得到吗?谢谢
安德鲁

2
谢谢,我只修改了一行内容,以使您的钠盐示例正常工作:function getKeyFromPassword($password, $keysize = \Sodium\CRYPTO_SECRETBOX_KEYBYTES)
Alexey Ozerov,2016年

1
哇!+1表示不加密URL参数。我真的很喜欢你的文章提供:paragonie.com/blog/2015/09/...
Lynnell灵光内里

73

我参加聚会很晚,但是在寻找正确的方法时,我碰到了这个页面,它是Google搜索结果中排名最高的之一,因此,我想就这个问题分享我的看法,我认为这是撰写本文时(2017年初)为最新。从PHP 7.1.0开始,mcrypt_decryptand mcrypt_encrypt将被弃用,因此构建将来的证明代码应使用openssl_encryptopenssl_decrypt

您可以执行以下操作:

$string_to_encrypt="Test";
$password="password";
$encrypted_string=openssl_encrypt($string_to_encrypt,"AES-128-ECB",$password);
$decrypted_string=openssl_decrypt($encrypted_string,"AES-128-ECB",$password);

重要提示:这使用的ECB模式不安全。如果您想要一个简单的解决方案而又不参加密码学工程学的速成课程,请不要自己编写,而只需使用一个库即可。

您还可以根据安全需要使用其他任何削片机方法。要查找可用的削片机方法,请参见openssl_get_cipher_methods函数。


10
谢谢,我很惊讶这个简单明了的答案没有得到更多的支持。当我想要加密/解密一个简单的字符串时,我宁愿不阅读有关最佳答案的长达10页的讨论。
劳伦特

4
这不是一个安全的答案。不应使用ECB模式。如果您想要一个“简单明了的答案”,只需使用一个库
Scott Arciszewski

2
@ScottArciszewski,是的,我承认我在寻找一些简单的代码时讲得太快了。从那以后,我添加了一个IV并在自己的代码中使用了CBC,这对于我的使用已经足够了。
laurent

阅读并重新考虑。使用CBC模式,攻击者可以完全更改消息。如果消息是文件,则攻击者可以翻转位并弹出calc.exe。未经身份验证的加密的风险非常严重。
Scott Arciszewski

7
这完全取决于用例!在某些情况下,这是非常好的情况。例如,我想在页面之间传递GET参数,prod_id=123但是我只是不想让每个人都可读123,但是即使他们可以读取它,也不会有问题。能够将123替换为自定义值的攻击者不会造成任何危害,他/她将只能获取任何其他产品的详细信息,但是Joe Average User不会提供有关如何获取有关详细信息的线索。例如产品124。对于这样的情况,这是一个完美的解决方案,对于安全性而言,这是不可行的!
Emil Borconi '17

43

不该做什么

警告:
此答案使用ECB。ECB不是加密模式,它只是一个构建块。如此答案所示,使用ECB并不能真正安全地加密字符串。不要在代码中使用ECB。请参阅Scott的答案,以获得一个好的解决方案。

我自己弄的。实际上,我在Google上找到了一些答案,并做了一些修改。但是结果是完全不安全的。

<?php
define("ENCRYPTION_KEY", "!@#$%^&*");
$string = "This is the original data string!";

echo $encrypted = encrypt($string, ENCRYPTION_KEY);
echo "<br />";
echo $decrypted = decrypt($encrypted, ENCRYPTION_KEY);

/**
 * Returns an encrypted & utf8-encoded
 */
function encrypt($pure_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
    return $encrypted_string;
}

/**
 * Returns decrypted original string
 */
function decrypt($encrypted_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv);
    return $decrypted_string;
}
?>

8
您可以使用“ MCRYPT_MODE_CBC”代替“ MCRYPT_MODE_ECB”来确保更高的安全性。
Parixit 2013年

10
Ramesh,这是因为您正在获取原始的加密数据。您可以使用base64获得更好的加密数据版本,如下所示:base64_encode(encrypt($string))-解密:decrypt(base64_decode($encrypted))
mendezcode 2014年

82
警告:这是不安全的。ECB模式不应该用于字符串,ECB不接受IV,未经身份验证,它使用旧密码(河豚)代替AES,密钥不是二进制等。SO社区应该真正停止支持加密/解密只是“起作用”,并开始认可已知的安全答案。如果您不确定,请不要投票。
Maarten Bodewes,2015年

3
我已经通过mcrypt_encrypt替换示例代码来做到这一点:php.net/manual/en/function.mcrypt-encrypt.php。请注意,现在复查它可能在结尾处应该带有rtrimfor字符"\0"
Maarten Bodewes,2015年

4
正确的答案是使用defuse / php-encryption之类的东西,而不是编写自己的mcrypt代码。
Scott Arciszewski,2015年

18

对于Laravel框架

如果您使用的是Laravel框架,那么使用内部函数进行加密和解密会更加容易。

$string = 'Some text to be encrypted';
$encrypted = \Illuminate\Support\Facades\Crypt::encrypt($string);
$decrypted_string = \Illuminate\Support\Facades\Crypt::decrypt($encrypted);

var_dump($string);
var_dump($encrypted);
var_dump($decrypted_string);

注意:确保在config / app.php文件的key选项中设置一个16、24或32个字符的随机字符串。否则,加密的值将不安全。


1
当然,它可能易于使用。但是安全吗?如何解决stackoverflow.com/a/30159120/781723中的问题?它使用经过身份验证的加密吗?它是否避免了旁通道漏洞并确保进行恒定时间相等性检查?它使用真正的随机密钥而不是密码/密码吗?是否使用适当的操作模式?它会正确生成随机IV吗?
DW

10

更新

PHP 7就绪版本。它使用PHP OpenSSL库中的openssl_encrypt函数。

class Openssl_EncryptDecrypt {
    function encrypt ($pure_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $ciphertext_raw = openssl_encrypt($pure_string, $cipher, $encryption_key, $options, $iv);
        $hmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        return $iv.$hmac.$ciphertext_raw;
    }
    function decrypt ($encrypted_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = substr($encrypted_string, 0, $ivlen);
        $hmac = substr($encrypted_string, $ivlen, $sha2len);
        $ciphertext_raw = substr($encrypted_string, $ivlen+$sha2len);
        $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $encryption_key, $options, $iv);
        $calcmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        if(function_exists('hash_equals')) {
            if (hash_equals($hmac, $calcmac)) return $original_plaintext;
        } else {
            if ($this->hash_equals_custom($hmac, $calcmac)) return $original_plaintext;
        }
    }
    /**
     * (Optional)
     * hash_equals() function polyfilling.
     * PHP 5.6+ timing attack safe comparison
     */
    function hash_equals_custom($knownString, $userString) {
        if (function_exists('mb_strlen')) {
            $kLen = mb_strlen($knownString, '8bit');
            $uLen = mb_strlen($userString, '8bit');
        } else {
            $kLen = strlen($knownString);
            $uLen = strlen($userString);
        }
        if ($kLen !== $uLen) {
            return false;
        }
        $result = 0;
        for ($i = 0; $i < $kLen; $i++) {
            $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
        }
        return 0 === $result;
    }
}

define('ENCRYPTION_KEY', '__^%&Q@$&*!@#$%^&*^__');
$string = "This is the original string!";

$OpensslEncryption = new Openssl_EncryptDecrypt;
$encrypted = $OpensslEncryption->encrypt($string, ENCRYPTION_KEY);
$decrypted = $OpensslEncryption->decrypt($encrypted, ENCRYPTION_KEY);

1
这是更好,更安全的版本。谢谢,它也按预期工作。

1
如何创建以及在哪里保存加密密钥?
user2800464

7

历史注释:这是在PHP4时编写的。这就是我们现在所说的“旧版代码”。

我出于历史目的留了这个答案-但是现在不赞成使用某些方法,不建议使用DES加密方法,等等。

我没有更新此代码有两个原因:1)我不再使用PHP手动处理加密方法,并且2)此代码仍达到了预期的目的:演示最小的,简单的加密方式工作原理在PHP中。

如果您找到一种类似的简化的“用于虚拟变量的PHP加密”类型的源,可以使人们使用10到20行或更少的代码行,请在注释中告诉我。

除此之外,请欣赏这个早期PHP4极简加密答案的经典片段。


理想情况下,您具有-或可以访问-mcrypt PHP库,因为它当然很流行并且非常有用,可以执行各种任务。以下是各种加密方法和一些示例代码的摘要PHP中的加密技术

//Listing 3: Encrypting Data Using the mcrypt_ecb Function 

<?php 
echo("<h3> Symmetric Encryption </h3>"); 
$key_value = "KEYVALUE"; 
$plain_text = "PLAINTEXT"; 
$encrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $plain_text, MCRYPT_ENCRYPT); 
echo ("<p><b> Text after encryption : </b>"); 
echo ( $encrypted_text ); 
$decrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $encrypted_text, MCRYPT_DECRYPT); 
echo ("<p><b> Text after decryption : </b>"); 
echo ( $decrypted_text ); 
?> 

一些警告:

1)当单向哈希将起作用时,切勿使用可逆或“对称”加密。

2)如果数据确实是敏感数据,例如信用卡号或社会保险号,请停止;您需要的不仅仅是任何简单的代码块都可以提供的,而是需要为此目的而设计的加密库以及大量时间来研究必要的方法。此外,软件加密可能不到敏感数据安全性的10%。这就像重新安装核电站一样-接受这种任务既危险又困难,并且在这种情况下是您所不知道的。财务处罚可能是巨大的,因此最好使用服务并将责任转嫁给他们。

3)此处列出的任何一种易于实施的加密都可以合理地保护您要保留的轻度重要信息,以防它们被窥探或在意外/故意泄漏的情况下限制暴露。但是,将密钥看作是如何在Web服务器上以纯文本格式存储的,如果他们可以获取数据,则可以获取解密密钥。

尽其所能,玩得开心:)


9
EW,DES。AES在哪里?
Patashu

2
谢谢!但是有些问题。我得到了M�������f=�_=奇怪的字符作为加密字符。我不能得到简单的字符吗?像:2a2ffa8f13220befbe30819047e23b2c。另外,我不能更改$key_value(固定为8 ???)的LENGTH和输出的LENGTH $encrypted_text吗?(是32或64长还是更长?)
夏期剧场

3
@夏期剧场加密的结果是二进制数据。如果您需要让它易于阅读,请在其上使用base64或十六进制编码。“我不能更改键值的长度吗?” 不同的对称加密算法对密钥值有不同的要求。“和输出的长度...”加密文本的长度必须至少与原始文本一样长,否则,没有足够的信息来重新创建原始文本。(这是Pigeonhole原理的应用。)顺便说一句,您应该使用AES而不是DES。DES容易损坏,不再安全。
Patashu

8
从PHP 5.5.0开始,不再建议使用mcrypt_ecb。强烈建议不要使用此功能。php.net/manual/en/function.mcrypt-ecb.php
哈菲兹

1
@BrianDHall仍然无法投票的原因是因为ECB模式不安全(使用CBC,CTR,GCM或Poly1305),DES较弱(您需要AES MCRYPT_RIJNDAEL_128),并且密文应进行身份验证(hash_hmac(),已验证与hash_equals())。
Scott Arciszewski 2015年

7

如果您不想使用库(应该使用),则可以使用如下所示的东西(PHP 7):

function sign($message, $key) {
    return hash_hmac('sha256', $message, $key) . $message;
}

function verify($bundle, $key) {
    return hash_equals(
      hash_hmac('sha256', mb_substr($bundle, 64, null, '8bit'), $key),
      mb_substr($bundle, 0, 64, '8bit')
    );
}

function getKey($password, $keysize = 16) {
    return hash_pbkdf2('sha256',$password,'some_token',100000,$keysize,true);
}

function encrypt($message, $password) {
    $iv = random_bytes(16);
    $key = getKey($password);
    $result = sign(openssl_encrypt($message,'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv), $key);
    return bin2hex($iv).bin2hex($result);
}

function decrypt($hash, $password) {
    $iv = hex2bin(substr($hash, 0, 32));
    $data = hex2bin(substr($hash, 32));
    $key = getKey($password);
    if (!verify($data, $key)) {
      return null;
    }
    return openssl_decrypt(mb_substr($data, 64, null, '8bit'),'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv);
}

$string_to_encrypt='John Smith';
$password='password';
$encrypted_string=encrypt($string_to_encrypt, $password);
$decrypted_string=decrypt($encrypted_string, $password);

这可以代替stackoverflow.com/a/16606352/126833吗?在主机升级到PHP 7.2之前,我一直使用前者。
anjanesh

@anjanesh,您将无法使用此密码解密旧数据(不同的算法+此
密码

2
就您而言,这应该可以:define("ENCRYPTION_KEY", "123456*"); $string = "This is the original data string!"; $encrypted = openssl_encrypt($string, 'BF-ECB', ENCRYPTION_KEY); $decrypted = openssl_decrypt($encrypted,'BF-ECB',ENCRYPTION_KEY);
Ascon

这是超级!
anjanesh

2

这些是使用AES256 CBC用PHP加密/解密字符串的紧凑方法:

function encryptString($plaintext, $password, $encoding = null) {
    $iv = openssl_random_pseudo_bytes(16);
    $ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, $iv);
    $hmac = hash_hmac('sha256', $ciphertext.$iv, hash('sha256', $password, true), true);
    return $encoding == "hex" ? bin2hex($iv.$hmac.$ciphertext) : ($encoding == "base64" ? base64_encode($iv.$hmac.$ciphertext) : $iv.$hmac.$ciphertext);
}

function decryptString($ciphertext, $password, $encoding = null) {
    $ciphertext = $encoding == "hex" ? hex2bin($ciphertext) : ($encoding == "base64" ? base64_decode($ciphertext) : $ciphertext);
    if (!hash_equals(hash_hmac('sha256', substr($ciphertext, 48).substr($ciphertext, 0, 16), hash('sha256', $password, true), true), substr($ciphertext, 16, 32))) return null;
    return openssl_decrypt(substr($ciphertext, 48), "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, substr($ciphertext, 0, 16));
}

用法:

$enc = encryptString("mysecretText", "myPassword");
$dec = decryptString($enc, "myPassword");

0

下面的代码在php中适用于所有带有特殊字符的字符串

   // Encrypt text --

    $token = "9611222007552";

      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);  
      $enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));  
      $crypted_token = openssl_encrypt($token, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
    echo    $crypted_token;
    //unset($token, $cipher_method, $enc_key, $enc_iv);

    // Decrypt text  -- 

    list($crypted_token, $enc_iv) = explode("::", $crypted_token);  
      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);
      $token = openssl_decrypt($crypted_token, $cipher_method, $enc_key, 0, hex2bin($enc_iv));
    echo   $token;
    //unset($crypted_token, $cipher_method, $enc_key, $enc_iv);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.