使用openssl_private_decrypt进行解密不会起作用,因为文本正在存储撇号

时间:2010-11-10 19:35:12

标签: php mysql openssl encryption

我将敏感信息以'text'字段格式存储在mysql数据库中,该格式使用openssl_public加密加密,并使用openssl_private_decrypt进行解密。

然而,我面临的问题是,当我尝试使用我的php脚本来“解码”文本时,返回的值中有几个撇号和引号,因此无法进行解密。任何想法如何解决这个问题?

注意:我最初尝试将我的信息存储在字段类型'varbinary'中,但每次都解密失败。

在审查了一些之后,我想也许php和mysql很难处理所有信息(~800条记录),因为有时候字段是空白的,其他字段不是。如果我逐个存储,它可以解决零问题,但是当尝试运行foreach循环时,它几乎总是会导致错误。有任何想法吗?要编码的脚本如下:

<?php

$publickey = file_get_contents("certificate.pem");

function encrypt($text) 
    { 
        return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
    } 


    try {
        $db = new PDO('mysql:host=localhost;dbname=DBNAME', 'USER', 'PW');
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->beginTransaction();

        $start = microtime(true);

        $stmt = $db->prepare("SELECT ID, ITEM1_old, ITEM2_old  FROM tablename");

        $stmt->execute();

        $rows = $stmt->fetchAll();

        foreach($rows as $row) {

            $id = $row['0'];
            $item1 = $row['1'];
            $item2 = $row['2'];

            define('SALT', $id);

            $item1_enc = encrypt($item1);
            $item2_enc = encrypt($item2);

            openssl_public_encrypt($item1_enc, $item1_ssl_enc, $publickey);
            openssl_public_encrypt($item2_enc, $item2_ssl_enc, $publickey);

            $stmt2 = $db->prepare("UPDATE tablename SET ITEM1_new=?, ITEM2_new=? WHERE ID=?");
            $stmt2->execute(array($item1_ssl_enc, $item2_ssl_enc, $id));

        }   

        $db->commit();
        $db->NULL;

        $elapsed = microtime(true) - $start;
        echo "Finished.<br />Elapsed time: ".$elapsed;
    }

    catch (PDOException $e)
    {
        $db->rollback();
        echo "There was a system error.".$e->getMessage();          
    }
?>

1 个答案:

答案 0 :(得分:1)

问题是密码在块中加密,如果纯文本与密码的块大小不匹配,它将被填充。这是正常和正确的,您需要在加密之前将长度字段打包到数据中。

$plaintext  = 'text to encrypt';
$plaintext  = pack('V', strlen($plaintext)) . $plaintext;
$ciphertext = encrypt($plaintext);

然后返回输出:

$plaintext = decrypt($ciphertext);
$header    = unpack('Vsize', $plaintext);
$plaintext = substr($plaintext, 4, $header['size'] + 4);

此外,如果您的有效负载超过一百字节或更少,您不应使用RSA加密整个有效负载,您应该生成随机密钥,使用密钥加密有效负载,然后加密密钥与您的公共/私钥。 RSA不是为加密大型有效载荷而设计的,它旨在共享一个秘密来初始化一个更快的对称密码,如Blowfish。

例如

/* Generate the random key */
$key = '';
for($i = 0; $i < 255; ++$i)
  $key .= chr(mt_rand(0, 255));
$key = sha1($key);

/* Pack & encrypt the payload with the key */
$plaintext  = pack('V', strlen($plaintext)) . $plaintext;
$ciphertext = encrypt($plaintext, $key);

/* Encrypt the key with the public key */
$key     = public_encrypt($key);
$payload = pack('V', strlen($key)) . $key . $ciphertext;

解密

  1. 解压缩有效负载密钥长度
  2. 使用公钥解密加密密钥
  3. 使用解密密钥解密密文。