RSA Encryption and Decryption Method of PHP and Application of Development Interface

  • 2021-09-11 19:46:09
  • OfStack

Network security is very important, especially to ensure data security. Many programmers who write interfaces directly transmit data in plaintext, which is very unprofessional in my opinion. I advocate that the data through the interface should be encrypted and decrypted before use.

This article mainly introduces the use of PHP development interface, data to achieve RSA encryption and decryption after use, example analysis of PHP custom RSA class encryption and decryption skills, very practical value, the need for friends can refer to the next.

Brief introduction to RSA

RSA encryption algorithm is the most commonly used asymmetric encryption algorithm, and CFCA cannot be separated from it in certificate services. But many novices don't know much about it. The following is only a brief introduction. RSA is the first perfect public key algorithm, which can be used for both encryption and digital signature. RSA is named after its three inventors, Ron Rivest, Adi Shamir and Leonard Adleman. This algorithm has withstood many years of in-depth cryptanalysis. Although cryptanalysts can neither prove nor deny the security of RSA, it just shows that this algorithm has certain credibility, and it has become the most popular public key algorithm at present. The security of RSA is based on the difficulty of large number decomposition. Its public and private keys are functions of a pair of large prime numbers (100 to 200 decimal numbers or greater). The difficulty of recovering plaintext from a public key and ciphertext is equivalent to decomposing the product of two large prime numbers (which is recognized as a mathematical problem).

The following are concrete classes and examples:


<?php 
 
/** 
 * RSA Algorithm class  
 *  Signature and ciphertext encoding: base64 String /106 Binary string /2 Binary string stream  
 *  Filling mode : PKCS1Padding (Encryption and Decryption) /NOPadding (Decryption)  
 * 
 * Notice:Only accepts a single block. Block size is equal to the RSA key size! 
 *  If the key length is 1024 bit The data must be less than 128 Bytes, plus PKCS1Padding Intrinsic 11 Byte information, so the plaintext needs to be less than 117 Byte  
 * 
 * @author: ZHIHUA_WEI 
 * @version: 1.0.0 
 * @date: 2017/06/30 
 */ 
class RSA 
{ 
  private $pubKey = null; 
  private $priKey = null; 
 
  /** 
   *  Constructor  
   * 
   * @param string  Public key file (passed in during verification and encryption)  
   * @param string  Private key file (passed in when signing and decrypting)  
   */ 
  public function __construct($public_key_file = '', $private_key_file = '') 
  { 
    if ($public_key_file) { 
      $this->_getPublicKey($public_key_file); 
    } 
    if ($private_key_file) { 
      $this->_getPrivateKey($private_key_file); 
    } 
  } 
 
  //  Private method  
  /** 
   *  Custom error handling  
   */ 
  private function _error($msg) 
  { 
    die('RSA Error:' . $msg); //TODO 
  } 
 
  /** 
   *  Detect fill type  
   *  Encryption only supports PKCS1_PADDING 
   *  Decryption support PKCS1_PADDING And NO_PADDING 
   * 
   * @param int  Fill mode  
   * @param string  Encryption en/ Decryption de 
   * @return bool 
   */ 
  private function _checkPadding($padding, $type) 
  { 
    if ($type == 'en') { 
      switch ($padding) { 
        case OPENSSL_PKCS1_PADDING: 
          $ret = true; 
          break; 
        default: 
          $ret = false; 
      } 
    } else { 
      switch ($padding) { 
        case OPENSSL_PKCS1_PADDING: 
        case OPENSSL_NO_PADDING: 
          $ret = true; 
          break; 
        default: 
          $ret = false; 
      } 
    } 
    return $ret; 
  } 
 
  private function _encode($data, $code) 
  { 
    switch (strtolower($code)) { 
      case 'base64': 
        $data = base64_encode('' . $data); 
        break; 
      case 'hex': 
        $data = bin2hex($data); 
        break; 
      case 'bin': 
      default: 
    } 
    return $data; 
  } 
 
  private function _decode($data, $code) 
  { 
    switch (strtolower($code)) { 
      case 'base64': 
        $data = base64_decode($data); 
        break; 
      case 'hex': 
        $data = $this->_hex2bin($data); 
        break; 
      case 'bin': 
      default: 
    } 
    return $data; 
  } 
 
  private function _getPublicKey($file) 
  { 
    $key_content = $this->_readFile($file); 
    if ($key_content) { 
      $this->pubKey = openssl_get_publickey($key_content); 
    } 
  } 
 
  private function _getPrivateKey($file) 
  { 
    $key_content = $this->_readFile($file); 
    if ($key_content) { 
      $this->priKey = openssl_get_privatekey($key_content); 
    } 
  } 
 
  private function _readFile($file) 
  { 
    $ret = false; 
    if (!file_exists($file)) { 
      $this->_error("The file {$file} is not exists"); 
    } else { 
      $ret = file_get_contents($file); 
    } 
    return $ret; 
  } 
 
  private function _hex2bin($hex = false) 
  { 
    $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false; 
    return $ret; 
  } 
 
  /** 
   *  Generate signature  
   * 
   * @param string  Signature material  
   * @param string  Signature encoding ( base64/hex/bin )  
   * @return  Signature value  
   */ 
  public function sign($data, $code = 'base64') 
  { 
    $ret = false; 
    if (openssl_sign($data, $ret, $this->priKey)) { 
      $ret = $this->_encode($ret, $code); 
    } 
    return $ret; 
  } 
 
  /** 
   *  Verify signature  
   * 
   * @param string  Signature material  
   * @param string  Signature value  
   * @param string  Signature encoding ( base64/hex/bin )  
   * @return bool 
   */ 
  public function verify($data, $sign, $code = 'base64') 
  { 
    $ret = false; 
    $sign = $this->_decode($sign, $code); 
    if ($sign !== false) { 
      switch (openssl_verify($data, $sign, $this->pubKey)) { 
        case 1: 
          $ret = true; 
          break; 
        case 0: 
        case -1: 
        default: 
          $ret = false; 
      } 
    } 
    return $ret; 
  } 
 
  /** 
   *  Encryption  
   * 
   * @param string  Cleartext  
   * @param string  Ciphertext encoding ( base64/hex/bin )  
   * @param int  Filling mode (seemingly php Have bug So currently only supports OPENSSL_PKCS1_PADDING )  
   * @return string  Ciphertext  
   */ 
  public function encrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING) 
  { 
    $ret = false; 
    if (!$this->_checkPadding($padding, 'en')) $this->_error('padding error'); 
    if (openssl_public_encrypt($data, $result, $this->pubKey, $padding)) { 
      $ret = $this->_encode($result, $code); 
    } 
    return $ret; 
  } 
 
  /** 
   *  Decryption  
   * 
   * @param string  Ciphertext  
   * @param string  Ciphertext encoding ( base64/hex/bin )  
   * @param int  Fill mode ( OPENSSL_PKCS1_PADDING / OPENSSL_NO_PADDING )  
   * @param bool  Whether to flip plaintext ( When passing Microsoft CryptoAPI-generated RSA cyphertext, revert the bytes in the block )  
   * @return string  Cleartext  
   */ 
  public function decrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING, $rev = false) 
  { 
    $ret = false; 
    $data = $this->_decode($data, $code); 
    if (!$this->_checkPadding($padding, 'de')) $this->_error('padding error'); 
    if ($data !== false) { 
      if (openssl_private_decrypt($data, $result, $this->priKey, $padding)) { 
        $ret = $rev ? rtrim(strrev($result), "\0") : '' . $result; 
      } 
    } 
    return $ret; 
  } 
} 

This is the concrete RSA class


<?php 
/** 
 * Author: Wei ZhiHua 
 * Date: 2017/6/30 0030 
 * Time:  Morning  10:15 
 */ 
header('Content-Type:text/html;Charset=utf-8;'); 
include "RSA.php"; 
echo '<pre>'; 
 
$pubfile = 'D:\WWW\test\rsa_public_key.pem'; 
$prifile = 'D:\WWW\test\rsa_private_key.pem'; 
$rsa = new RSA($pubfile, $prifile); 
$rst = array( 
  'ret' => 200, 
  'code' => 1, 
  'data' => array(1, 2, 3, 4, 5, 6), 
  'msg' => "success", 
); 
$ex = json_encode($rst); 
// Encryption  
$ret_e = $rsa->encrypt($ex); 
// Decryption  
$ret_d = $rsa->decrypt($ret_e); 
echo $ret_e; 
echo '<pre>'; 
echo $ret_d; 
echo '<pre>';  
$a = 'test'; 
// Signature  
$x = $rsa->sign($a); 
// Validation  
$y = $rsa->verify($a, $x); 
var_dump($x, $y); 
exit; 


Related articles: