目录git
对称密码的缺点算法
RSA概述安全
RSA密钥对生成算法网络
RSA加解密过程dom
RSA小结ide
RSA的Go实现函数
encoding/pem包测试
crypto/x509包编码
crypto/rsa包加密
生成RSA密钥对
加解密
截图
参考
保密通讯进入计算机网络时代,传统密码体制逐渐暴露其固有的弱点,体如今密钥分发。经过前面的对称密码文章,能够看到须要双方知道密钥。问题在于我要给你发送秘密信息,没有安全的通道,发送信息前须要找到安全的通道告诉你密钥,而后再在不安全通道进行通讯。问题是我既然找到了安全的通道,直接发送消息不就好了吗? 固然,古代大部分是在线下约定好的,相似《悬崖之上》的密码本。
对称密码解决了密钥分发问题,能够在不安全通道发送密钥。固然,对称密码还有数字签名问题,后面数字签名相关的文章再说。
RSA概述W.Diffie和Hellman发表了著名的文章《密码学的新方向》首次提出了公钥密码算法的思想。
公钥密码体制为密码学的发展提供了新的理论和技术思想,一方面公钥密码算法是创建在数学函数基础上的,而不是创建在字符或位方式的操做上的;另外一方面公钥密码算法是以非对称的形式使用加密密钥和解密密钥,这两个密钥的使用对密钥管理、认证等都有着深入的实际意义。能够说,公钥密码体制的出如今密码学发展史上是一次质的飞跃。
1978年,Rivest,Shamir和Adleman提出的RSA算法体现了公钥算法的思想,被认为是第一个安全的、实用的公钥密码算法。
RSA的理论基础是数论的欧拉定理,它的安全性依赖于大整数的素因子分解的困难性。
RSA密钥对生成算法注:p和q保密。e和n为公钥,d为私钥。
RSA加解密过程加密算法:c=E(m)=(mod n)
解密算法:m=D(c)=(mod n)
func Decode(data []byte) (p *Block, rest []byte)
Decode函数会从输入里查找到下一个PEM格式的块(证书、私钥等)。它返回解码获得的Block和剩余未解码的数据。若是未发现PEM数据,返回(nil, data)。
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte
MarshalPKCS1PrivateKey将rsa私钥序列化为ASN.1 PKCS#1 DER编码。
func MarshalPKIXPublicKey(pub interface{}) ([]byte, error)
MarshalPKIXPublicKey将公钥序列化为PKIX格式DER编码。
func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error)
ParsePKIXPublicKey解析一个DER编码的公钥。这些公钥通常在以"BEGIN PUBLIC KEY"出现的PEM块中。
func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
ParsePKCS1PrivateKey解析ASN.1 PKCS#1 DER编码的rsa私钥。
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error)
EncryptPKCS1v15使用PKCS#1 v1.5规定的填充方案和RSA算法加密msg。信息不能超过((公共模数的长度)-11)字节。注意:使用本函数加密明文(而不是会话密钥)是危险的,请尽可能在新协议中使用RSA OAEP。
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error)
DecryptPKCS1v15使用PKCS#1 v1.5规定的填充方案和RSA算法解密密文。若是random不是nil,函数会注意规避时间侧信道***。
func GenerateRsaKey(keySize int, dirPath string) error { privateKey,err := rsa.GenerateKey(rand.Reader,keySize) if err != nil{ _, file, line, _ := runtime.Caller(0) return util.Error(file,line+1,err.Error()) } // x509 derText :=x509.MarshalPKCS1PrivateKey(privateKey) // pem Block block := &pem.Block{ Type:"rsa private key", Bytes:derText, } // just joint, caller must let dirPath right file,err := os.Create(dirPath+"private.pem") defer file.Close() if err != nil{ _, file, line, _ := runtime.Caller(0) return util.Error(file,line+1,err.Error()) } err = pem.Encode(file,block) if err != nil{ _, file, line, _ := runtime.Caller(0) return util.Error(file,line+1,err.Error()) } // get PublicKey from privateKey publicKey := privateKey.PublicKey derStream,err := x509.MarshalPKIXPublicKey(&publicKey) if err != nil{ _, file, line, _ := runtime.Caller(0) return util.Error(file,line+1,err.Error()) } block = &pem.Block{ Type:"rsa public key", Bytes:derStream, } file,err = os.Create(dirPath+"public.pem") if err != nil{ _, file, line, _ := runtime.Caller(0) return util.Error(file,line+1,err.Error()) } err = pem.Encode(file, block) if err != nil{ _, file, line, _ := runtime.Caller(0) return util.Error(file,line+1,err.Error()) } return nil }
加密
func RsaEncrypt(plainText []byte,filePath string) ([]byte, error) { // get pem.Block block,err := util.GetKey(filePath) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,err.Error()) } // X509 publicInterface,err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,err.Error()) } publicKey,flag := publicInterface.(*rsa.PublicKey) if flag == false{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.RsatransError) } // encrypt cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,err.Error()) } return cipherText,nil }
解密
func RsaDecrypt(cipherText []byte,filePath string) (plainText []byte,err error) { // get pem.Block block,err := util.GetKey(filePath) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,err.Error()) } // get privateKey privateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes) defer func() { if err2 := recover();err2 != nil{ _, file, line, _ := runtime.Caller(0) err = util.Error(file,line,errors.RsaNilError) } }() // get plainText use privateKey plainText, err3 := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText) if err3 != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,err3.Error()) } return plainText,err }
测试代码
func TestRsa(t *testing.T) { // 生成密钥对 err := GenerateRsaKey(1024, "./") if err!=nil{ fmt.Println(err) } // 测试加密 plainText := []byte("hi, I'm lady_killer9") cipherText,err := RsaEncrypt(plainText,"./public.pem") if err!=nil{ fmt.Println(err) } fmt.Printf("加密后为:%s\n",cipherText) // 测试解密 plainText,err = RsaDecrypt(cipherText,"./private.pem") if err!=nil{ fmt.Println(err) } fmt.Printf("解密后为:%s\n",plainText) }
源代码地址:https://gitee.com/frankyu365/gocrypto
目前是v1.0.5-alpha版本,测试中,碰见了个空指针panic,不太肯定直接recover的思路是否正确。
参考《现代密码学教程 谷利泽,杨义先等》
Go标准库-crypto/rsa
Go标准库-crypto/x509
Go标准库-encoding/pem