解密算法:m=D©=(mod n)
RSA小结
- 第一个实用的公开密钥算法。
- 目前使用最多的一种公钥密码算法。
- RSA的理论基础是数论的欧拉定理。
- RSA的安全性依赖于大数的素因子分解的困难性。
- 密码分析者既不能证明也不能否定RSA的安全性。
- 既能用于加密也能用于数字签名。
- 目前密钥长度1024位是安全的。
RSA的Go实现
encoding/pem包
func Decode(data []byte) (p *Block, rest []byte)
Decode函数会从输入里查找到下一个PEM格式的块(证书、私钥等)。它返回解码得到的Block和剩余未解码的数据。如果未发现PEM数据,返回(nil, data)。
crypto/x509包
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私钥。
crypto/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,函数会注意规避时间侧信道攻击。
生成RSA密钥对
- 使用rsa.GenerateKey生成私钥
- 使用x509.MarshalPKCS1PrivateKey序列化私钥为derText
- 使用pem.Block转为Block
- 使用pem.Encode写入文件
- 从私钥中获取公钥
- 使用x509.MarshalPKIXPublicKey序列化公钥为derStream
- 使用pem.Block转为Block
- 使用pem.Encode写入文件
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
}
加解密
加密
- 获取公钥
- 使用x509.ParsePKIXPublicKey解析公钥
- 使用rsa.EncryptPKCS1v15加密
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
}
解密
- 获取私钥
- 使用x509.ParsePKCS1PrivateKey解析私钥
- 使用rsa.DecryptPKCS1v15解密
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)
}
截图
源代码地址:FrankYu/gocrypto
目前是v1.0.5-alpha版本,测试中,遇见了个空指针panic,不太确定直接recover的思路是否正确。
参考
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
8643236)]
[外链图片转存中…(img-3FhomfEk-1715488643236)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!