RSA加密傳輸代碼示例

RSA加密傳輸代碼示例

涉及敏感數據的傳輸,雙方最好約定使用加密解密。那RSA非對稱加密就大有做爲了。
服務端能夠保留本身的私鑰,發給客戶端對應的公鑰。這樣就能夠互相加解密了。php中rsa加解密實現:php

首先要生成一對公鑰私鑰。前提是linux機器上安裝了openssl命令。html

生成私鑰文件:linux

1openssl genrsa -out rsa_private_key.pem 1024

利用私鑰,生成公鑰:編程

1openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

php代碼案例:json

 1<?php
2ini_set('error_reporting', -1);
3ini_set('display_errors', -1);
4header('Content-Type: text/html; charset=utf-8');
5
6$private_key = file_get_contents("/home/users/xx/test/rsa_private_key.pem");
7$public_key = file_get_contents("/home/users/xx/test/rsa_public_key.pem");
8
9$pi_key = openssl_pkey_get_private($private_key);// 可用返回資源id
10$pu_key = openssl_pkey_get_public($public_key);
11
12// 加密數據
13$data = array(
14    'id' => '1234567890',
15    'name' => '小明',
16    'mobile' => '123456',
17);
18// 轉換爲JSON格式
19$data = json_encode($data);
20
21$encrypted = '';
22$decrypted = '';
23
24
25// 公鑰加密
26openssl_public_encrypt($data, $encrypted, $pu_key);
27// base64傳輸
28$encrypted = base64_encode($encrypted);
29echo $encrypted, "<br/>";
30
31//私鑰解密
32openssl_private_decrypt(base64_decode($encrypted), $decrypted, $pi_key);
33echo $decrypted, "<br/>";
34
35// 打印加密明文
36print_r(json_decode($decrypted, true));
37

公鑰加密(openssl_public_encrypt),私鑰解密(openssl_private_decrypt)。
私鑰加密(openssl_private_encrypt),公鑰解密(openssl_public_decrypt)。編程語言

都是一個道理,代碼相似。RSA加密解密有個填充方式padding的參數,不一樣編程語言之間交互,須要注意這個。函數

1padding can be one of OPENSSL_PKCS1_PADDING, OPENSSL_SSLV23_PADDING, OPENSSL_PKCS1_OAEP_PADDING,OPENSSL_NO_PADDING

大於1024字節加密加密

值得注意的是,若是選擇密鑰是1024bit長的(openssl genrsa -out rsa_private_key.pem 1024),那麼支持加密的明文長度字節最多隻能是1024/8=128bytespa

  • 若是加密的padding填充方式選擇的是OPENSSL_PKCS1_PADDING(這個要佔用11個字節),那麼明文長度最多隻能就是128-11=117字節。若是超出,那麼這些openssl加解密函數會返回falsecode

  • 這時有個解決辦法,把須要加密的源字符串按少於117個長度分開爲幾組,在解密的時候以172個字節分爲幾組。
    其中的『少於117』(只要不大於117便可)和『172』兩個數字是怎麼來的,值得一說。

  • 爲何少於117就行,由於rsa encrypt後的字節長度是固定的,就是密鑰長1024bit/8=128byte。所以只要encrypt不返回false,即只要不大於117個字節,那麼返回加密後的都是128byte

  • 172是由於什麼?由於128個字節base64_encode後的長度固定是172。

  • 這裏順便普及下base64_encodeencode的長度是和原文長度有個計算公式:
    <br />$len2 = $len1%3 &gt;0 ? (floor($len1/3)4 + 4) : ($len14/3);<br />

  • 明文超出長度的代碼(前提是1024bit的密鑰長,OPENSSL_PKCS1_PADDING的填充方式,不然數字要變化)

 1<?php
2$pi_key =  openssl_pkey_get_private($private_key);// 資源類型
3$pu_key = openssl_pkey_get_public($public_key);
4
5$data = array(
6    'username' => '張三1',
7    'mobile' => '13321995977',
8    'info' => '14bMitESqD4PYwODWmy7rrrvyFPEnJJTECLjvKB7IkrVxVDkp1XiJnGKH  
92h5syHQ5qslPSGYJ1M/XkDnGINwaLVHVD3BoKKgKg1bZn7ao5pXT+herqxaVwWs6  
10ga63yVSIC8jcODxiuvxJnUMQRLaqoF6aUb/2VWc2T5MDmxLhAkEA3pwGpvXgLiWL  
113h7QLYZLrLrbFRuRN4CYl4UYaAKokkAvZly04Glle8ycgOc2DzL4eiL4l/+x/gaq  
12deJU/cHLRQJBANOZY0mEoVkwhU4bScSdnfM6usQowYBEwHYY',
13);
14
15$str = json_encode($data);
16$en = encrypt_rsa($str, $pu_key);
17
18$de = decrypt_rsa($en, $pi_key);
19echo $de;
20
21function encrypt_rsa($data, $pu_key){
22    $split = str_split($data, 100);// 1024bit && OPENSSL_PKCS1_PADDING  不大於117便可
23    foreach ($split as $part) {
24        $isOkay = openssl_public_encrypt($part, $en_data, $pu_key);
25        if(!$isOkay){
26            return false;
27        }
28        // echo strlen($en_data),'<br/>';
29        $encode_data .= base64_encode($en_data);
30    }
31    return $encode_data;
32}
33
34function decrypt_rsa($data, $pi_key){
35    $split = str_split($data, 172);// 1024bit  固定172
36    foreach ($split as $part) {
37        $isOkay = openssl_private_decrypt(base64_decode($part), $de_data, $pi_key);// base64在這裏使用,由於172字節是一組,是encode來的
38        if(!$isOkay){
39            return false;
40        }
41        $decode_data .= $de_data;
42    }
43    return $decode_data;
44}
45

相關文章
相關標籤/搜索