PHP普通人的加密?

PHP encryption for the common man?

在 PHP 中加密和解密数据的一对好的通用函数是什么?

假设:

当有人说 "I just want to encrypt some data" 并且你想告诉他们在实施某事之前进行研究并了解此类决定的后果时,但他们有截止日期,所以你无论如何都必须提供一个片段:)

对我来说,md5()是最好的选择。

http://php.net/manual/en/function.md5.php

我已经通过网络成功使用了这两个自定义函数 url 比如一些敏感信息的参数..你可以看看它是否符合你的需要:)

这可以很容易地仅用于后端或任何你喜欢的,

https://gist.github.com/mkdizajn/88a528f2a9ecee880c2e#file-php-encode_decode-helper-function-php

$key = 'your password for encryption';
function hideinfo( $key, $string ){ return rawurlencode( base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key))))); }
function showinfo( $key, $string ){ return rawurldecode( rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode(rawurldecode($string)), MCRYPT_MODE_CBC, md5(md5($key))), "[=10=]")); }

我一直在传递给这个函数数组,比如:

print_r( my_array(), true ) 并使用了各种字符编码,效果也很好,

hth, k

这是我刚写的一对快速函数(实际上是三个)应该符合您的规范:

// Simple PHP encryption code by Ilmari Karonen, v1.0
// http://whosebug.com/a/30239440
// This code is released into the public domain; use it any way you want.

$enc_algo = 'rijndael-128';   // Rijndael-128/256 = AES-256
$key_len = 32; $iv_len = 16;  // key and IV lengths for AES-256
$enc_mode = 'ctr';  // CTR and OFB modes don't need padding

$hash_algo = 'sha256';  // for HMAC; must output at least $key_len bytes
$nonce_len = 16;  // length of random nonce; arbitrary, 16 bytes = 128 bits

function encrypt( $key, $plaintext, $metadata = "" ) {
    global $enc_algo, $enc_mode, $key_len, $iv_len, $hash_algo, $nonce_len;
    // derive two subkeys from the original key
    $mac_key = hash_hmac( $hash_algo, 'mac', $key, true );
    $enc_key = hash_hmac( $hash_algo, 'enc', $key, true );
    $enc_key = substr( $enc_key, 0, $key_len );

    // derive a "synthetic IV" from the nonce, plaintext and metadata
    $temp = $nonce = ( $nonce_len > 0 ? mcrypt_create_iv( $nonce_len ) : "" );
    $temp .= hash_hmac( $hash_algo, $plaintext, $mac_key, true );
    $temp .= hash_hmac( $hash_algo, $metadata, $mac_key, true );
    $mac = hash_hmac( $hash_algo, $temp, $mac_key, true );
    $siv = substr( $mac, 0, $iv_len );

    // encrypt the message
    $enc = mcrypt_encrypt( $enc_algo, $enc_key, $plaintext, $enc_mode, $siv );
    return base64_encode( $siv . $nonce . $enc );
}

function decrypt( $key, $ciphertext, $metadata = "" ) {
    global $enc_algo, $enc_mode, $key_len, $iv_len, $hash_algo, $nonce_len;
    // derive two subkeys from the original key
    $mac_key = hash_hmac( $hash_algo, 'mac', $key, true );
    $enc_key = hash_hmac( $hash_algo, 'enc', $key, true );
    $enc_key = substr( $enc_key, 0, $key_len );

    // unpack MAC, nonce and encrypted message from the ciphertext
    $enc = base64_decode( $ciphertext );
    $siv = substr( $enc, 0, $iv_len );
    $nonce = substr( $enc, $iv_len, $nonce_len );
    $enc = substr( $enc, $iv_len + $nonce_len );

    // decrypt message
    $plaintext = mcrypt_decrypt( $enc_algo, $enc_key, $enc, $enc_mode, $siv );

    // verify MAC, return null if message is invalid
    $temp = $nonce;
    $temp .= hash_hmac( $hash_algo, $plaintext, $mac_key, true );
    $temp .= hash_hmac( $hash_algo, $metadata, $mac_key, true );
    $mac = hash_hmac( $hash_algo, $temp, $mac_key, true );
    if( $siv !== substr( $mac, 0, $iv_len ) ) return null;

    return $plaintext;
}

// extra function for password-based encryption
function password2key( $password, $count = 100000, $salt = "" ) {
    global $hash_algo;
    return hash_pbkdf2( $hash_algo, $password, $salt, $count, 0, true );
}

这是一个简单的测试用例/用法示例:

$key = password2key( 'password' );
echo "key (in hex): "; var_dump( bin2hex( $key ) );

$enc = encrypt( $key, 'a quick brown fox jumps over the lazy dog' );
echo "encrypted: "; var_dump( $enc );

$dec = decrypt( $key, $enc );
echo "decrypted: "; var_dump( $dec );

# try to modify one bit of the encrypted message, see if decryption fails
$fake_enc = base64_decode( $enc );
$fake_enc = substr( $fake_enc, 0, -1 ) . ( substr( $fake_enc, -1 ) ^ "[=11=]1" );
$fake_enc = base64_encode( $fake_enc );
$dec = decrypt( $key, $fake_enc );
echo "tampered message: "; var_dump( $dec );

# decoding with wrong metadata should also fail
$dec = decrypt( $key, $enc, 'wrong' );
echo "wrong metadata: "; var_dump( $dec );

上面的代码实现了一个自定义 authenticated encryption mode based on the AES-256 cipher in CTR mode1, combined with HMAC-SHA-256 for message authentication. It uses the Mcrypt and Hash 模块,我相信它们应该都相当普遍。

界面特意保持尽可能简单:

  • encrypt( $key, $message ) 使用给定的密钥加密消息,returns 生成 Base64 编码的密文。
  • decrypt( $key, $ciphertext ) 使用相同的密钥解密 encrypt() 的输出,returns 明文消息,或者 null 如果消息验证失败(这可能意味着消息已被篡改,或密钥不正确)。

这两个函数还可以采用可选的 $metadata 参数 2 用于 "associated data",例如发送者/接收者 ID 或其他消息 headers .简而言之,如果传递给 decrypt() 的元数据字符串与传递给 encrypt() 的元数据字符串不匹配,则假定消息已被篡改(例如,被攻击者试图修改 headers),验证将失败。

底部的额外辅助函数 password2key() 只是对 Mcrypt 的 PBKDF2. If you "key" is not a random string with high entropy, you should call password2key() to derive the actual encryption key from it. The $count parameter controls the slowness of the derivation process, and should be set as high as you reasonably can; the default value of 100,000 provides a little over 16 bits worth of extra resistance against brute force attacks 实现的简单包装。


我用来组合组件的具体方法大致基于 SIV construction by Rogaway and Shrimpton, but using HMAC instead of their CMAC* algorithm. Note that this is not a classical Encrypt-then-MAC scheme, but rather an Encrypt-and-MAC 方法;虽然 E&M 没有与 EtM 相同类型的通用安全证明,但我相信这个实例化应该仍然是安全的,因为与安全哈希函数一起使用的 HMAC 被认为是 privacy-preserving(即它不会泄露关于明文)。

这种SIV-like构造的优点是它减少了对nonce的依赖,从而减少了对系统RNG的依赖;即使 nonce 并不总是唯一的,"synthetic IV" 也几乎可以肯定是唯一的(除非明文也恰好相同)。因此,即使使用 no nonce(即即使 $nonce_len = 0),该方案仍然只泄漏关于明文的最少信息(本质上,它们的长度,以及两个明文是否是完全相同的)。唯一的随机数通过确保即使是相同的明文也以不同方式加密来消除第二次泄漏。

上面的代码还有其他设计方式,可以提高鲁棒性以提高效率。例如,虽然将 $key 直接提供给 HMAC 和 AES 可能 是安全的,但我明确地从中派生了单独的 quasi-independent 子密钥。这样做的一个好处是,除了有一点额外的信心,即没有基于密钥重用的不可预见的攻击之外,输入密钥可以具有任意格式;它不必是随机的 32 字节二进制字符串,就像原始 AES 密钥一样。


1) PHP Mcrypt接口doesn't seem to have a constant for CTR mode,但底层Mcrypt库应该支持它。如果您没有,出于某种原因,请尝试将 $enc_mode = 'nofb'; 设置为 OFB 模式。

2) 上面给出的代码只采用一个元数据字符串,但如果需要,将其修改为采用多个字符串会很简单。