摘要:安全總是很重要的,各個語言對于通用的加密算法都會有實現。對于和加密算法本身,請查閱相關資料在中,很多功能經常是一個函數解決而中的卻不是。該文討論加密解密。一概要這是一個非對稱加密算法,一般通過公鑰加密,私鑰解密。
安全總是很重要的,各個語言對于通用的加密算法都會有實現。前段時間,用Go實現了RSA和DES的加密解密,在這分享一下。(對于RSA和DES加密算法本身,請查閱相關資料)
在PHP中,很多功能經常是一個函數解決;而Go中的卻不是。本文會通過PHP加密,Go解密;Go加密,PHP解密來學習Go的RSA和DES相關的API。
該文討論Go RSA加密解密。所有操作在linux下完成。
一、概要這是一個非對稱加密算法,一般通過公鑰加密,私鑰解密。
在加解密過程中,使用openssl生產密鑰。執(zhí)行如下操作:
1)創(chuàng)建私鑰:
openssl genrsa -out private.pem 1024 //密鑰長度,1024覺得不夠安全的話可以用2048,但是代價也相應增大
2)創(chuàng)建公鑰:
openssl rsa -in private.pem -pubout -out public.pem
這樣便生產了密鑰。
一般地,各個語言也會提供API,用于生成密鑰。在Go中,可以查看encoding/pem包和crypto/x509包。具體怎么產生,可查看《GO加密解密RSA番外篇:生成RSA密鑰》。
加密解密這塊,涉及到很多標準,個人建議需要的時候臨時學習一下。
二、Go RSA加密解密1、rsa加解密,必然會去查crypto/ras這個包
Package rsa implements RSA encryption as specified in PKCS#1.
這是該包的說明:實現RSA加密技術,基于PKCS#1規(guī)范。
對于什么是PKCS#1,可以查閱相關資料。PKCS(公鑰密碼標準),而#1就是RSA的標準??梢圆榭矗篜KCS系列簡介
從該包中函數的名稱,可以看到有兩對加解密的函數。
EncryptOAEP和DecryptOAEP EncryptPKCS1v15和DecryptPKCS1v15
這稱作加密方案,詳細可以查看,PKCS #1 v2.1 RSA 算法標準
可見,當與其他語言交互時,需要確定好使用哪種方案。
PublicKey和PrivateKey兩個類型分別代表公鑰和私鑰,關于這兩個類型中成員該怎么設置,這涉及到RSA加密算法,本文中,這兩個類型的實例通過解析文章開頭生成的密鑰得到。
2、解析密鑰得到PublicKey和PrivateKey的實例
這個過程,我也是花了好些時間(主要對各種加密的各種東東不熟):怎么將openssl生成的密鑰文件解析到公鑰和私鑰實例呢?
在encoding/pem包中,看到了—–BEGIN Type—–這樣的字樣,這正好和openssl生成的密鑰形式差不多,那就試試。
在該包中,一個block代表的是PEM編碼的結構,關于PEM,請查閱相關資料。我們要解析密鑰,當然用Decode方法:
func Decode(data []byte) (p *Block, rest []byte)
這樣便得到了一個Block的實例(指針)。
解析來看crypto/x509。為什么是x509呢?這又涉及到一堆概念。先不管這些,我也是看encoding和crypto這兩個包的子包摸索出來的。
在x509包中,有一個函數:
func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error)
從該函數的說明:ParsePKIXPublicKey parses a DER encoded public key. These values are typically found in PEM blocks with “BEGIN PUBLIC KEY”??梢娺@就是解析PublicKey的。另外,這里說到了PEM,可以上面的encoding/pem對了。(PKIX是啥東東,查看這里 )
而解析私鑰的,有好幾個方法,從上面的介紹,我們知道,RSA是PKCS#1,剛好有一個方法:
func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
返回的就是rsa.PrivateKey。
3、解密解密實現
通過上面的介紹,Go中RSA的解密解密實現就不難了。代碼如下:
// 加密
func RsaEncrypt(origData []byte) ([]byte, error) { block, _ := pem.Decode(publicKey) if block == nil { return nil, errors.New("public key error") } pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } pub := pubInterface.(*rsa.PublicKey) return rsa.EncryptPKCS1v15(rand.Reader, pub, origData) }
// 解密
func RsaDecrypt(ciphertext []byte) ([]byte, error) { block, _ := pem.Decode(privateKey) if block == nil { return nil, errors.New("private key error!") } priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, err } return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext) }
其中,publicKey和privateKey是openssl生成的密鑰,我生成的如下:
// 公鑰和私鑰可以從文件中讀取
var privateKey = []byte(` -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y 7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7 Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1 XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB /jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40 IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG 4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9 DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8 9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O -----END RSA PRIVATE KEY----- `) var publicKey = []byte(` -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL AUeJ6PeW+DAkmJWF6QIDAQAB -----END PUBLIC KEY----- `)
4、使用例子
package main import ( "fmt" ) func main() { data, err := RsaEncrypt([]byte("[email protected]/mrkt")) if err != nil { panic(err) } origData, err := RsaDecrypt(data) if err != nil { panic(err) } fmt.Println(string(origData)) }
該例子是加密完[email protected]/mrkt后立馬解密
三、跨語言加解密語言內部正常,還得看看和其他語言是否一致,即:其他語言加密,Go語言得正確解密;Go語言加密,其他語言正確解密
1、PHP RSA加解密
這里,我選擇PHP,使用的是openssl擴展。PHP中加解密很簡單,如下兩個方法(這里只考慮用公鑰加密,私鑰解密):
bool openssl_public_encrypt ( string $data , string &$crypted , mixed
$key [, int $padding = OPENSSL_PKCS1_PADDING ] ) bool
openssl_private_decrypt ( string $data , string &$decrypted , mixed
$key [, int $padding = OPENSSL_PKCS1_PADDING ] )
最后一個參數是加密方案(補齊方式)。由于Go中使用的是PKCS1而不是OAEP,所以,使用默認值即可。
PHP代碼如下:
$privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y
7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7
Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB
AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM
ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1
XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB
/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40
IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG
4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9
DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8
9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw
DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO
AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O
-----END RSA PRIVATE KEY-----"; $publicKey = "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL
AUeJ6PeW+DAkmJWF6QIDAQAB
-----END PUBLIC KEY-----";
function rsaEncrypt($data) { global $publicKey; openssl_public_encrypt($data, $crypted, $publicKey); return $crypted; } function rsaDecrypt($data) { global $privateKey; openssl_private_decrypt($data, $decrypted, $privateKey); return $decrypted; } function main() { $crypted = rsaEncrypt("[email protected]/mrk"); $decrypted = rsaDecrypt($crypted); echo "encrypt and decrypt:" . $decrypted; }
main();
這里也是用PHP加解密[email protected]/mrkt
2、Go和PHP一起工作
這里要注意的一點是,由于加密后是字節(jié)流,直接輸出查看會亂碼,因此,為了便于語言直接加解密,這里將加密之后的數據進行base64編碼。
3、使用
示例中,php和Go版本都支持-d參數傳入加密好的字符串,將其解密;不傳時,會輸出加密好并base64編碼的串,可用于其他語言解密。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/21836.html
摘要:大家好,我是永強,就是老李之前經常給你們說的區(qū)塊鏈大神大學肄業(yè)卻依然大公司主程一波兒流只生活在老李口中尚未真實露面的騙錢高手老王的左膀右臂趙永強。 大家好,我是永強,就是老李之前經常給你們說的區(qū)塊鏈大神、大學肄業(yè)卻依然大公司iOS主程一波兒流、只生活在老李口中尚未真實露面的騙錢高手、老王的左膀右臂 ——— 趙永強。我和尼古拉斯趙四之間并沒有什么強關聯,我只是單方面認識他而已。 之前老李...
摘要:項目地址前后端交互時為了保證信息安全可使用方式加密信息,在數據量大的時候可采用結合方式。由于加密和解密使用同樣規(guī)則簡稱密鑰,這被稱為對稱加密算法。從那時直到現在,算法一直是最廣為使用的非對稱加密算法。 RSA-JS-PHP 項目地址rsa-js-php 前后端交互時為了保證信息安全可使用RSA方式加密信息,在數據量大的時候可采用DES+RSA結合方式。DEMO演示地址 一點歷史 1...
摘要:目的服務端和移動端雙向加密解密共有七個文件其中包括三個類文件對稱加密解密類服務端公鑰私鑰非對稱加密解密類客戶端公鑰私鑰非對稱加密解密類四個過程文件其中文件中有注釋和數據第一步客戶端和服務端交換密鑰明文第二步客戶端發(fā)起帶參數請求加密后第三 目的:服務端和移動端雙向加密解密 共有七個文件 其中包括三個類文件 lib_aes.php aes對稱加密解密類 server_rsa_crypt....
閱讀 3108·2021-11-25 09:43
閱讀 1702·2021-11-24 11:15
閱讀 2419·2021-11-22 15:25
閱讀 3593·2021-11-11 16:55
閱讀 3294·2021-11-04 16:10
閱讀 2829·2021-09-14 18:02
閱讀 1734·2021-09-10 10:50
閱讀 1124·2019-08-29 15:39