php基于OpenSSL函数对RSA签名的加密解密

  • 2021年6月10日
  • 技术
准备:

首先需要php开启openssl扩展和生成秘钥。

这里没有用函数生成秘钥,直接使用的工具更加方便(函数的话使用openssl_sign和openssl_verify函数);生成秘钥工具使用的是支付宝的RSA签名验签工具。

RSA签名验签工具地址:https://opendocs.alipay.com/open/291/105971

生成秘钥文件

按图中选项生成秘钥文件,保存至对应的文件:

私钥文件格式:

-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJs5xLh3Lt0IT16G8QQd29U9POlDBc/QFv2XkBE9EltwtBnKq75jy+dikPl+5axHKsQcOXnk0FIQerGKWWwbPvVQ4EU7MkORK2KOyhvV44fY6QB8mVsEJN04ptlpFcrKIQ0mNtulCzgAeJoUK27dxhUdLJK7ze2QWs2jEGPrz7utAgMBAAECgYBSr/hCB4MYTVfyU9HJzpoPQprS61gKNqA4oGcnN7Ays5vM7XCFcCXrcU8nCNkR56s5YoufiisKvCqPrtIpy23CbdJcxjJvmGtWh+7hFOR4G8jAttIPAxMxYjjcNq9BhKIWcrrRlk6SHamowHCz2W8c3p8cXtpbdUTg8rhCYNdFxQJBAMs1XJ/mATJTjsPZaAT2/3Em5gZTTyVZDn7qb0eitDX+lUaqEbfGHxIILDEZTmLrHwXqTEPC8roZwjd3CEArnlsCQQDDjT/3ku+CaIVm1ds/OM16y6eO3rRfbc2lAQaPY4a29EytIHMgQS+S46BnIFJBPaGJaSlwJ5c1Bb3ZISnMaDyXAkBdaSQw5Jv8NGjWIqQsVBZMP2NR2Q3yzyNYuA97UJGimGqqVxdZ8RrrQRJ/Z3CfDBHwuClipMTLQ3gB4xfJ18MtAkBNhSUig8EmtUCM76ImgeITF8CoxmhCnEi1bJ6pIQ86X8Y1q3N4Cd9OH6Zqu0lgS4pJ6sJej5NFla0Y8iibu4apAkAd1NYXY9v6wFcZJEPg6giSUkZPKW4fbUwZrRUvVMcW98uGncWfLbaKQ8NY3CL0m7qu8BJ9nQxsDZlzVC+mwxuY
-----END PRIVATE KEY-----

公钥文件格式:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbOcS4dy7dCE9ehvEEHdvVPTzpQwXP0Bb9l5ARPRJbcLQZyqu+Y8vnYpD5fuWsRyrEHDl55NBSEHqxillsGz71UOBFOzJDkStijsob1eOH2OkAfJlbBCTdOKbZaRXKyiENJjbbpQs4AHiaFCtu3cYVHSySu83tkFrNoxBj68+7rQIDAQAB
-----END PUBLIC KEY-----
加密解密类
<?php
class RSAUtils {
	private   $privateKey;
	private   $publicKey;

	public function __construct() {
		$this->privateKey = openssl_pkey_get_private( file_get_contents( './private.pem' ) );
		$this->publicKey  = openssl_pkey_get_public( file_get_contents( './public.pem' ) );
		@( $this->privateKey && $this->publicKey ) or die( '密钥或者公钥不可用' );
	}

	//私钥加密,需要公钥解密
	public function PrivateEncrypt( $str ) {
		$crypto = '';
		foreach ( str_split( $str, 117 ) as $chunk ) {
			$encryptData = '';
			openssl_private_encrypt( $chunk, $encryptData, $this->privateKey );
			$crypto .= $encryptData;
		}
		//加密后的内容会乱码,最好转码
		return base64_encode($crypto);
	}

	//公钥解密私钥加密后的内容
	public function PublicDecrypt( $str ) {
		$crypto = '';
		foreach ( str_split( base64_decode( $str ), 128 ) as $chunk ) {
			$decryptData = '';
			openssl_public_decrypt( $chunk, $decryptData, $this->publicKey );
			$crypto .= $decryptData;
		}

		return $crypto;
	}

	//公钥加密,需要私钥解密
	public function PublicEncrypt( $str ) {
		$crypto = '';
		foreach ( str_split( $str, 117 ) as $chunk ) {
			$encryptData = '';
			openssl_public_encrypt( $chunk, $encryptData, $this->publicKey );
			$crypto .= $encryptData;
		}
        //加密后的内容会乱码,最好转码
		return base64_encode($crypto);
	}

	//私钥解密公钥加密后的内容
	public function PrivateDecrypt( $str ) {
		$crypto = '';
		foreach ( str_split( base64_decode( $str ), 128 ) as $chunk ) {
			$decryptData = '';
			openssl_private_decrypt( $chunk, $decryptData, $this->privateKey );
			$crypto .= $decryptData;
		}

		return $crypto;
	}
}

注意:公钥加密的内容只能用私钥解,反之私钥加密的只能公钥解

另外,公钥加密私钥解密是非对称加解密,意思是每次加密同一内容的结果会不一样,这篇文章有详细讲到:https://blog.csdn.net/guyongqiangx/article/details/74930951

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注