PHP基于openssl的RSA加密解密
(我也学那些人,也来贴代码了……)
因为某IOS应用后台中要使用RSA加密,所以自己完成了下面这个RSA加密的过程。要用到PHP的openssl扩展。
首先在Linux下面用openssl命令生成私钥,利用私钥生成公钥。私钥为1024位。
1 2 |
openssl genrsa -out rsa_private_key.pem 1024 openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem |
加密过程主要就是将明文以117长度分割(因为1024位密钥最大只能加密长度为117的字符串),将他们连接起来,最后base64加密,便于网络传输。这里使用了url安全的base64加密,就是把+/两个符号替换成-_ ,尾部的=去掉,解密的时候再替换回来。因为传输过程中+会被转换成空格。
解密过程是先base64解密出来再分组进行RSA解密,最后连接起来字符串就是了。昨天晚上因为搞错一处的变量名,和服务器私钥加密后在客户端还是私钥解密,这两个问题搞到1点多也没发现,还是今天弄好的……
这个类主要是在构造的时候选择是用公钥还是私钥,因为考虑到服务器只用到了私钥所以就这么实现的,不知道好不好。
下面放码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
class RSAUtils { const USE_PRIVATE_KEY = TRUE; const USE_PUBLIC_KEY = FALSE; private static $private_key_str = '-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQC2U8/A8zuX+EHIK/iTk3V6iHEA+XkksFAdgq0vIlqMOTtwTSG3 j9UtOWO4qU+NiUBoDtW9cXH6zs37ZDSc1Cerfb2IpsA2+hXeGgFw6cGN1Y06GSWP pHnstUIUY8NK7S7BtGocXs3znqJwv5fMAFWthHE6jeFuJq25xd7j45tO1wIDAQAB AoGAWYpVeAO724ku/RgjDo6XXiLNpFXgGZWA8s0vMfukDkM5HpCyo0w+u+P4RkLX 78Fc4P2QGGYzPKH9ZJ00fWRvSiPVFlnjnSvBZaK712VRwEBDs4UU7vk0L4I2ctum pfbNv1e8Q36jSQeWCJFybyP5hxBgJ8tU77p75HuD4ytNjOECQQDY8cvSVR9oYXQj N+69jGxMrK44By283ML/Yk3966C0NiVxQTTiIfAYz2aePWh07hI/VLElf21cfNHX 8kU+n1KnAkEA1yaieGgTt2sNCUS7J2sF2sWly5dtHGEtEFn0wMbUT8UHBnc/3WcH /nJPPzJP1MyO/2ifnpNfiOI1jq4SY8mYUQJAU9DXVmPcxo8gN5scec8O6HCuvqbH XPhNvi1UxI2MgROKU79FlzhVcsBufSRsfwCbvCwUZNBeiCURTcUkS5VycQJAD9fe evNfEFCnwxj2ly6AXd3UGavq8v4M7XlSVqfNlpoxrD43y7v8kLYmM8cmrcrqdNBl gK3liRTvULRs0kBUIQJANNRH5PYcdaqSOKLa8ycOSdhV2kX6frSradgTzGcYPA0V KTKVldQO4YQEmiVIdi3IEAQ45DUAL/xRiDDjpR2Wbw== -----END RSA PRIVATE KEY-----'; private static $public_key_str = '-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2U8/A8zuX+EHIK/iTk3V6iHEA +XkksFAdgq0vIlqMOTtwTSG3j9UtOWO4qU+NiUBoDtW9cXH6zs37ZDSc1Cerfb2I psA2+hXeGgFw6cGN1Y06GSWPpHnstUIUY8NK7S7BtGocXs3znqJwv5fMAFWthHE6 jeFuJq25xd7j45tO1wIDAQAB -----END PUBLIC KEY-----'; private static $private_key; private static $public_key; private $use_private; /** * 构造方法 * @param $use_private boolean 是否使用私钥 * 否则使用公钥 */ function __construct($use_private = self::USE_PRIVATE_KEY) { if($use_private) { if(self::$private_key === NULL) self::$private_key = openssl_pkey_get_private(self::$private_key_str); } elseif(self::$public_key === NULL) self::$public_key = openssl_pkey_get_public(self::$public_key_str); $this->use_private = $use_private; } /** * RSA加密 * @param $plaintext string 明文 * @return string 密文 */ function encrypt($plaintext) { $pack = ''; foreach(str_split($plaintext, 117) as $str) { $crypted = ''; if($this->use_private) openssl_private_encrypt($str, $crypted, self::$private_key); else openssl_public_encrypt($str, $crypted, self::$public_key); $pack .= $crypted; } $pack = $this->base64url_encode($pack); return $pack; } /** * RSA解密 * @param $ciphertext string 密文 * @return string 明文 */ function decrypt($ciphertext) { $ciphertext = $this->base64url_decode($ciphertext); $text = ''; foreach (str_split($ciphertext, 128) as $str) { $decrypted = ''; if($this->use_private) openssl_private_decrypt($str, $decrypted, self::$private_key); else openssl_public_decrypt($str, $decrypted, self::$public_key); $text .= $decrypted; } return $text; } /** * URL安全的base64加密 * @param $data string 明文 * @return string 密文 */ function base64url_encode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } /** * URL安全的base64解密 * @param $data string 密文 * @return string 明文 */ function base64url_decode($data) { return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); } } |
下面写个小demo来测试这个类。
1 2 3 4 5 6 7 8 9 10 11 |
include('RSAUtils.php'); $data = 'Mr. Liu has been married for more than a decade, but lives apart from his wife and does not want to be unfaithful, so he spent almost a pay on a high-end lifelike sex doll that is proving popular with the discerning Chinese male with disposable income. (Cover photo: AFP) Most popular styles back in stock! Featured in Playboy, GQ & Hypebeast!'; $public_rsa = new RSAUtils(FALSE); $private_rsa = new RSAUtils(); $en = $public_rsa->encrypt($data); echo "encrypt: " . $en . "\n"; $de = $private_rsa->decrypt($en); echo "decrypt: " . $de . "\n"; |
(千万不要在意上面那段文字呦。。。)