在PHP中使用RSA加密和解密文本

2020/12/31 02:41 · php ·  · 0评论

PHP 5.3是否有任何类可提供RSA加密/解密而无需填充?

我有私钥和公钥,p,q和模数。

您可以使用phpseclib,这是一个纯PHP RSA实现

<?php
include('Crypt/RSA.php');

$privatekey = file_get_contents('private.key');

$rsa = new Crypt_RSA();
$rsa->loadKey($privatekey);

$plaintext = new Math_BigInteger('aaaaaa');
echo $rsa->_exponentiate($plaintext)->toBytes();
?>

安全警告:此代码段易受Bleichenbacher 1998年的padding oracle攻击请参阅此答案以获得更好的安全性。

class MyEncryption
{

    public $pubkey = '...public key here...';
    public $privkey = '...private key here...';

    public function encrypt($data)
    {
        if (openssl_public_encrypt($data, $encrypted, $this->pubkey))
            $data = base64_encode($encrypted);
        else
            throw new Exception('Unable to encrypt data. Perhaps it is bigger than the key size?');

        return $data;
    }

    public function decrypt($data)
    {
        if (openssl_private_decrypt(base64_decode($data), $decrypted, $this->privkey))
            $data = $decrypted;
        else
            $data = '';

        return $data;
    }
}

2017年(或之后)编写的任何旨在合并严重加密的应用程序都不应再使用RSA。PHP公钥加密更好的选择

人们决定使用RSA加密时会犯两个大错误:

  1. 开发人员选择了错误的填充模式
  2. 由于RSA本身不能加密很长的字符串,因此开发人员经常将字符串分成小块,并分别加密每个块。有点像ECB模式

最佳选择:sodium_crypto_box_seal()(libsodium)

$keypair = sodium_crypto_box_keypair();
$publicKey = sodium_crypto_box_publickey($keypair);
// ...
$encrypted = sodium_crypto_box_seal(
    $plaintextMessage,
    $publicKey
);
// ...
$decrypted = sodium_crypto_box_seal_open(
    $encrypted,
    $keypair
);

简单安全。Libsodium将在PHP 7.2中提供,或者可通过PECL获得早期版本的PHP。如果您需要纯PHP的polyfill,请获取paragonie / sodium_compat

坦率地说:正确使用RSA

在2017年使用RSA的唯一原因是:“我被禁止安装PECL扩展,因此不能使用libsodium,并且由于某种原因也不能使用paragonie / sodium_compat。”

您的协议应如下所示:

  1. 生成一个随机的AES密钥。
  2. 使用AEAD加密模式,或者使用CBC然后使用HMAC-SHA256,使用AES密钥对您的纯文本消息进行加密。
  3. 使用RSAES-OAEP + MGF1-SHA256用RSA公钥加密AES密钥(第1步)
  4. 连接您的RSA加密的AES密钥(步骤3)和AES加密的消息(步骤2)。

无需自己执行此操作,请查看EasyRSA

进一步阅读:在PHP中正确执行RSA

如果您使用的是PHP> = 7.2,请考虑使用内置的钠核心扩展进行加密。

它是现代且更安全的。您可以在这里找到更多信息-http: //php.net/manual/en/intro.sodium.php在这里-https://paragonie.com/book/pecl-libsodium/read/00-intro.md

示例PHP 7.2钠加密类-

<?php

/**
 * Simple sodium crypto class for PHP >= 7.2
 * @author MRK
 */
class crypto {

    /**
     * 
     * @return type
     */
    static public function create_encryption_key() {
        return base64_encode(sodium_crypto_secretbox_keygen());
    }

    /**
     * Encrypt a message
     * 
     * @param string $message - message to encrypt
     * @param string $key - encryption key created using create_encryption_key()
     * @return string
     */
    static function encrypt($message, $key) {
        $key_decoded = base64_decode($key);
        $nonce = random_bytes(
                SODIUM_CRYPTO_SECRETBOX_NONCEBYTES
        );

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

    /**
     * Decrypt a message
     * @param string $encrypted - message encrypted with safeEncrypt()
     * @param string $key - key used for encryption
     * @return string
     */
    static function decrypt($encrypted, $key) {
        $decoded = base64_decode($encrypted);
        $key_decoded = base64_decode($key);
        if ($decoded === false) {
            throw new Exception('Decryption error : the encoding failed');
        }
        if (mb_strlen($decoded, '8bit') < (SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + SODIUM_CRYPTO_SECRETBOX_MACBYTES)) {
            throw new Exception('Decryption error : the message was truncated');
        }
        $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_decoded
        );
        if ($plain === false) {
            throw new Exception('Decryption error : the message was tampered with in transit');
        }
        sodium_memzero($ciphertext);
        sodium_memzero($key_decoded);
        return $plain;
    }

}

样品用法-

<?php 

$key = crypto::create_encryption_key();

$string = 'Sri Lanka is a beautiful country !';

echo $enc = crypto::encrypt($string, $key); 
echo crypto::decrypt($enc, $key);

是。看看http://jerrywickey.com/test/testJerrysLibrary.php

它提供了PHP中RSA加密和解密以及javascript中RSA加密的示例代码示例。

如果要加密文本而不是仅以10为基数的数字,则还需要基到基的转换。那就是将文本转换成很大的数字。文本实际上只是以63为基数书写。26个小写字母加26个大写字母+ 10个数字+空格字符。下面的代码也是如此。

$ GETn参数是一个文件名,其中包含用于加密功能的密钥。如果您不明白,请询问。我会帮忙的。

我昨天实际上发布了整个加密库,但是Brad Larson一个mod杀死了它,并说这种东西并不是Stack Overflow真正的目的。但是您仍然可以在上面的链接中找到所有代码示例和整个函数库,以对AJAX进行客户端/服务器加密解密。

function RSAencrypt( $num, $GETn){
    if ( file_exists( 'temp/bigprimes'.hash( 'sha256', $GETn).'.php')){
        $t= explode( '>,', file_get_contents('temp/bigprimes'.hash( 'sha256', $GETn).'.php'));
        return JL_powmod( $num, $t[4], $t[10]); 
    }else{
        return false;
    }
}

function RSAdecrypt( $num, $GETn){
    if ( file_exists( 'temp/bigprimes'.hash( 'sha256', $GETn).'.php')){
        $t= explode( '>,', file_get_contents('temp/bigprimes'.hash( 'sha256', $GETn).'.php'));
        return JL_powmod( $num, $t[8], $t[10]);     
    }else{
        return false;
    }
}

function JL_powmod( $num, $pow, $mod) {
    if ( function_exists('bcpowmod')) {
        return bcpowmod( $num, $pow, $mod);
    }
    $result= '1';
    do {
        if ( !bccomp( bcmod( $pow, '2'), '1')) {
            $result = bcmod( bcmul( $result, $num), $mod);
        }
       $num = bcmod( bcpow( $num, '2'), $mod);

       $pow = bcdiv( $pow, '2');
    } while ( bccomp( $pow, '0'));
    return $result;
}

function baseToBase ($message, $fromBase, $toBase){
    $from= strlen( $fromBase);
    $b[$from]= $fromBase; 
    $to= strlen( $toBase);
    $b[$to]= $toBase; 

    $result= substr( $b[$to], 0, 1);

    $f= substr( $b[$to], 1, 1);

    $tf= digit( $from, $b[$to]);

    for ($i=strlen($message)-1; $i>=0; $i--){
        $result= badd( $result, bmul( digit( strpos( $b[$from], substr( $message, $i, 1)), $b[$to]), $f, $b[$to]), $b[$to]);
        $f= bmul($f, $tf, $b[$to]);
    }
    return $result;
} 

function digit( $from, $bto){   
    $to= strlen( $bto);
    $b[$to]= $bto; 

    $t[0]= intval( $from);
    $i= 0;
    while ( $t[$i] >= intval( $to)){
        if ( !isset( $t[$i+1])){ 
            $t[$i+1]= 0;
        }
        while ( $t[$i] >= intval( $to)){
            $t[$i]= $t[$i] - intval( $to);
            $t[$i+1]++;
        }
        $i++;
    }

    $res= '';
    for ( $i=count( $t)-1; $i>=0; $i--){ 
        $res.= substr( $b[$to], $t[$i], 1);
    }
    return $res;
}   

function badd( $n1, $n2, $nbase){
    $base= strlen( $nbase);
    $b[$base]= $nbase; 

    while ( strlen( $n1) < strlen( $n2)){
        $n1= substr( $b[$base], 0, 1) . $n1;
    }
    while ( strlen( $n1) > strlen( $n2)){
        $n2= substr( $b[$base], 0, 1) . $n2;
    }
    $n1= substr( $b[$base], 0, 1) . $n1;    
    $n2= substr( $b[$base], 0, 1) . $n2;
    $m1= array();
    for ( $i=0; $i<strlen( $n1); $i++){
        $m1[$i]= strpos( $b[$base], substr( $n1, (strlen( $n1)-$i-1), 1));
    }   
    $res= array();
    $m2= array();
    for ($i=0; $i<strlen( $n1); $i++){
        $m2[$i]= strpos( $b[$base], substr( $n2, (strlen( $n1)-$i-1), 1));
        $res[$i]= 0;
    }           
    for ($i=0; $i<strlen( $n1)  ; $i++){
        $res[$i]= $m1[$i] + $m2[$i] + $res[$i];
        if ($res[$i] >= $base){
            $res[$i]= $res[$i] - $base;
            $res[$i+1]++;
        }
    }
    $o= '';
    for ($i=0; $i<strlen( $n1); $i++){
        $o= substr( $b[$base], $res[$i], 1).$o;
    }   
    $t= false;
    $o= '';
    for ($i=strlen( $n1)-1; $i>=0; $i--){
        if ($res[$i] > 0 || $t){    
            $o.= substr( $b[$base], $res[$i], 1);
            $t= true;
        }
    }
    return $o;
}
function bmul( $n1, $n2, $nbase){
    $base= strlen( $nbase);
    $b[$base]= $nbase; 

    $m1= array();
    for ($i=0; $i<strlen( $n1); $i++){
        $m1[$i]= strpos( $b[$base], substr($n1, (strlen( $n1)-$i-1), 1));
    }   
    $m2= array();
    for ($i=0; $i<strlen( $n2); $i++){
        $m2[$i]= strpos( $b[$base], substr($n2, (strlen( $n2)-$i-1), 1));
    }           
    $res= array();
    for ($i=0; $i<strlen( $n1)+strlen( $n2)+2; $i++){
        $res[$i]= 0;
    }
    for ($i=0; $i<strlen( $n1)  ; $i++){
        for ($j=0; $j<strlen( $n2)  ; $j++){
            $res[$i+$j]= ($m1[$i] * $m2[$j]) + $res[$i+$j];
            while ( $res[$i+$j] >= $base){
                $res[$i+$j]= $res[$i+$j] - $base;
                $res[$i+$j+1]++;
            }
        }
    }
    $t= false;
    $o= '';
    for ($i=count( $res)-1; $i>=0; $i--){
        if ($res[$i]>0 || $t){  
            $o.= substr( $b[$base], $res[$i], 1);
            $t= true;
        }
    }
    return $o;
}

我很难解密用python加密的长字符串。这是python加密功能:

def RSA_encrypt(public_key, msg, chunk_size=214):
    """
    Encrypt the message by the provided RSA public key.

    :param public_key: RSA public key in PEM format.
    :type public_key: binary
    :param msg: message that to be encrypted
    :type msg: string
    :param chunk_size: the chunk size used for PKCS1_OAEP decryption, it is determined by \
    the private key length used in bytes - 42 bytes.
    :type chunk_size: int
    :return: Base 64 encryption of the encrypted message
    :rtype: binray
    """
    rsa_key = RSA.importKey(public_key)
    rsa_key = PKCS1_OAEP.new(rsa_key)

    encrypted = b''
    offset = 0
    end_loop = False

    while not end_loop:
        chunk = msg[offset:offset + chunk_size]

        if len(chunk) % chunk_size != 0:
            chunk += " " * (chunk_size - len(chunk))
            end_loop = True

        encrypted += rsa_key.encrypt(chunk.encode())
        offset += chunk_size

    return base64.b64encode(encrypted)

PHP中的解密:

/**
 * @param  base64_encoded string holds the encrypted message.
 * @param  Resource your private key loaded using openssl_pkey_get_private
 * @param  integer Chunking by bytes to feed to the decryptor algorithm.
 * @return String decrypted message.
 */
public function RSADecyrpt($encrypted_msg, $ppk, $chunk_size=256){
    if(is_null($ppk))
        throw new Exception("Returned message is encrypted while you did not provide private key!");
    $encrypted_msg = base64_decode($encrypted_msg);

    $offset = 0;
    $chunk_size = 256;

    $decrypted = "";
    while($offset < strlen($encrypted_msg)){
        $decrypted_chunk = "";
        $chunk = substr($encrypted_msg, $offset, $chunk_size);

        if(openssl_private_decrypt($chunk, $decrypted_chunk, $ppk, OPENSSL_PKCS1_OAEP_PADDING))
            $decrypted .= $decrypted_chunk;
        else 
            throw new exception("Problem decrypting the message");
        $offset += $chunk_size;
    }
    return $decrypted;
}
本文地址:http://php.askforanswer.com/zaiphpzhongshiyongrsajiamihejiemiwenben.html
文章标签: ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!