1. 程式人生 > >php RSA加解密

php RSA加解密

nim ring efi 區別 iam 功能 1=1 ted 發送

相關介紹

RSA算法屬於非對稱加密算法,非對稱加密算法需要兩個秘鑰:公開密鑰(publickey)和私有秘鑰(privatekey).公開密鑰和私有秘鑰是一對,

如果公開密鑰對數據進行加密,只有用對應的私有秘鑰才能解密;

如果私有秘鑰對數據進行加密那麽只有用對應的公開密鑰才能解密.

因為加密解密使用的是兩個不同的秘鑰,所以這種算法叫做非對稱加密算法.簡單的說就是公鑰加密私鑰解密,私鑰加密公鑰解密.

需要註意的地方

1.RSA 加密或簽名後的結果是不可讀的二進制,使用時經常會轉為 BASE64 碼再傳輸

2.RSA 加密時,對要加密數據的大小有限制,最大不大於密鑰長度。例如在使用 1024 bit 的密鑰時(秘鑰生成可以自行百度),最大可以加密 1024/8=128 Bytes 的數據。數據大於 128 Bytes 時,需要對數據進行分組加密(如果數據超限,加解密時會失敗,openssl 函數會返回 false),分組加密後的加密串拼接成一個字符串後發送給客戶端。

為了保證每次加密的結果都不同,RSA 加密時會在待加密數據後拼接一個隨機字符串,再進行加密。不同的填充方式 Padding 表示這個字符串的不同長度,在對超限數據進行分組後,會按照這個 Padding 指定的長度填入隨機字符串。例如如果 Padding 填充方式使用默認的 OPENSSL_PKCS1_PADDING(需要占用 11 個字節用於填充),那麽明文長度最多只能就是 128-11=117 Bytes。

接收方解密時也需要分組。將加密後的原始二進制數據(對於經過 BASE64 的數據,需要解碼),每 128 Bytes 分為一組,然後再進行解密。解密後,根據 Padding 的長度丟棄隨機字符串,把得到的原字符串拼接起來,就得到原始報文。

3.openssl_public_encrypt函數 php的默認填充和無填充是有區別的,如果只是php和php對接則不需要關註這個問題,如果是php跟c或java,需要選擇無填充然後自行加入填充

4.需要將php的openssl模塊打開或安裝(win上是打開,linux上是安裝,具體自行百度)

為了方便我這裏提供一組1024位的公私鑰簽名:

/*********************測試公鑰*******************************
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmkANmC849IOntYQQdSgLvMMGm

8V/u838ATHaoZwvweoYyd+/7Wx+bx5bdktJb46YbqS1vz3VRdXsyJIWhpNcmtKhY
inwcl83aLtzJeKsznppqMyAIseaKIeAm6tT8uttNkr2zOymL/PbMpByTQeEFlyy1
poLBwrol0F4USc+owwIDAQAB
-----END PUBLIC KEY-----
*************************************************************
************************測試私鑰*****************************
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKaQA2YLzj0g6e1h
BB1KAu8wwabxX+7zfwBMdqhnC/B6hjJ37/tbH5vHlt2S0lvjphupLW/PdVF1ezIk
haGk1ya0qFiKfByXzdou3Ml4qzOemmozIAix5ooh4Cbq1Py6202SvbM7KYv89syk
HJNB4QWXLLWmgsHCuiXQXhRJz6jDAgMBAAECgYAIF5cSriAm+CJlVgFNKvtZg5Tk
93UhttLEwPJC3D7IQCuk6A7Qt2yhtOCvgyKVNEotrdp3RCz++CY0GXIkmE2bj7i0
fv5vT3kWvO9nImGhTBH6QlFDxc9+p3ukwsonnCshkSV9gmH5NB/yFoH1m8tck2Gm
BXDj+bBGUoKGWtQ7gQJBANR/jd5ZKf6unLsgpFUS/kNBgUa+EhVg2tfr9OMioWDv
MSqzG/sARQ2AbO00ytpkbAKxxKkObPYsn47MWsf5970CQQDIqRiGmCY5QDAaejW4
HbOcsSovoxTqu1scGc3Qd6GYvLHujKDoubZdXCVOYQUMEnCD5j7kdNxPbVzdzXll
9+p/AkEAu/34iXwCbgEWQWp4V5dNAD0kXGxs3SLpmNpztLn/YR1bNvZry5wKew5h
z1zEFX+AGsYgQJu1g/goVJGvwnj/VQJAOe6f9xPsTTEb8jkAU2S323BG1rQFsPNg
jY9hnWM8k2U/FbkiJ66eWPvmhWd7Vo3oUBxkYf7fMEtJuXu+JdNarwJAAwJK0YmO
LxP4U+gTrj7y/j/feArDqBukSngcDFnAKu1hsc68FJ/vT5iOC6S7YpRJkp8egj5o
pCcWaTO3GgC5Kg==
-----END PRIVATE KEY-----

下面使用的相關函數功能介紹:

openssl_pkey_get_public() 從證書中提取公鑰
openssl_pkey_get_private() 從證書中提取私鑰
openssl_public_encrypt() 公鑰加密
openssl_private_decrypt() 私鑰解密
openssl_private_encrypt() 私鑰加密
openssl_public_decrypt() 公鑰解密
base64_encode() 使用base64對數據重新編碼
base64_decode() 將base64的數據解碼

好了,準備工作到此結束。下面進行具體的codeing:

第一步:將公私鑰簽名定義為常量

define(‘RSA_PUBLIC‘, ‘-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmkANmC849IOntYQQdSgLvMMGm
8V/u838ATHaoZwvweoYyd+/7Wx+bx5bdktJb46YbqS1vz3VRdXsyJIWhpNcmtKhY
inwcl83aLtzJeKsznppqMyAIseaKIeAm6tT8uttNkr2zOymL/PbMpByTQeEFlyy1
poLBwrol0F4USc+owwIDAQAB
-----END PUBLIC KEY-----);

define(‘RSA_PRIVATE‘,‘-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKaQA2YLzj0g6e1h
BB1KAu8wwabxX+7zfwBMdqhnC/B6hjJ37/tbH5vHlt2S0lvjphupLW/PdVF1ezIk
haGk1ya0qFiKfByXzdou3Ml4qzOemmozIAix5ooh4Cbq1Py6202SvbM7KYv89syk
HJNB4QWXLLWmgsHCuiXQXhRJz6jDAgMBAAECgYAIF5cSriAm+CJlVgFNKvtZg5Tk
93UhttLEwPJC3D7IQCuk6A7Qt2yhtOCvgyKVNEotrdp3RCz++CY0GXIkmE2bj7i0
fv5vT3kWvO9nImGhTBH6QlFDxc9+p3ukwsonnCshkSV9gmH5NB/yFoH1m8tck2Gm
BXDj+bBGUoKGWtQ7gQJBANR/jd5ZKf6unLsgpFUS/kNBgUa+EhVg2tfr9OMioWDv
MSqzG/sARQ2AbO00ytpkbAKxxKkObPYsn47MWsf5970CQQDIqRiGmCY5QDAaejW4
HbOcsSovoxTqu1scGc3Qd6GYvLHujKDoubZdXCVOYQUMEnCD5j7kdNxPbVzdzXll
9+p/AkEAu/34iXwCbgEWQWp4V5dNAD0kXGxs3SLpmNpztLn/YR1bNvZry5wKew5h
z1zEFX+AGsYgQJu1g/goVJGvwnj/VQJAOe6f9xPsTTEb8jkAU2S323BG1rQFsPNg
jY9hnWM8k2U/FbkiJ66eWPvmhWd7Vo3oUBxkYf7fMEtJuXu+JdNarwJAAwJK0YmO
LxP4U+gTrj7y/j/feArDqBukSngcDFnAKu1hsc68FJ/vT5iOC6S7YpRJkp8egj5o
pCcWaTO3GgC5Kg==
-----END PRIVATE KEY-----‘);

第二步:進行公鑰加密

//公鑰加密 
$public_key = openssl_pkey_get_public(RSA_PUBLIC); 
if(!$public_key){
    die(‘公鑰不可用‘);
}
//第一個參數是待加密的數據只能是string,第二個參數是加密後的數據,第三個參數是openssl_pkey_get_public返回的資源類型,第四個參數是填充方式
$return_en = openssl_public_encrypt("hello world", $crypted, $public_key);
if(!$return_en){
    return(‘加密失敗,請檢查RSA秘鑰‘);
}
$eb64_cry = base64_encode($crypted);
echo "公鑰加密數據:".$eb64_cry;
echo "<hr>";

第三步:測試使用私鑰進行解密

//私鑰解密
$private_key = openssl_pkey_get_private(RSA_PRIVATE);
if(!$private_key){
    die(‘私鑰不可用‘);
}
$return_de = openssl_private_decrypt(base64_decode($eb64_cry), $decrypted, $private_key);
if(!$return_de){
    return(‘解密失敗,請檢查RSA秘鑰‘);
}
echo "私鑰解密數據:".$decrypted;
echo "<hr>";

跑一下可以看到結果:

技術分享圖片

私鑰加密,公鑰解密的方式:

//私鑰加密
$private_key = openssl_pkey_get_private(RSA_PRIVATE);
if(!$private_key){
    die(‘私鑰不可用‘);
}
$return_en = openssl_private_encrypt("hello world222222", $crypted, $private_key);
if(!$return_en){
    return(‘加密失敗,請檢查RSA秘鑰‘);
}
$eb64_cry = base64_encode($crypted);
echo "私鑰加密數據".$eb64_cry;
echo "<hr>";

//公鑰解密
$public_key = openssl_pkey_get_public(RSA_PUBLIC);
if(!$public_key){
    die(‘公鑰不可用‘);
}
$return_de = openssl_public_decrypt(base64_decode($eb64_cry), $decrypted, $public_key);
if(!$return_de){
    return(‘解密失敗,請檢查RSA秘鑰‘);
}
echo "公鑰解密數據:".$decrypted;
echo "<hr>";

跑一下可以看到結果:

技術分享圖片

以上為使用php的默認填充方式加解密,請知悉

php RSA加解密