GO实现RSA加密
发布日期:2021-11-18 19:17:19 浏览次数:12 分类:技术文章

本文共 5478 字,大约阅读时间需要 18 分钟。

什么是非对称加密

1976年以前,所有的加密方法都使用对称加密算法:加密和解密使用同一套规则。例如:甲使用密钥 A 加密,将密文传递给乙,乙仍使用密钥 A 解密。如果密钥 A 在甲传递给乙的过程中泄露,或者根据已知的几次密文和明文推导出密钥 A,则甲乙之间的通讯将毫无秘密。

1976年,两位美国计算机学家 Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不传递密钥的情况下,完成解密。这被称为 Diffie-Hellman密钥交换算法 假如甲要和乙通讯,甲使用公钥 A 加密,将密文传递给乙,乙使用私钥 B 解密得到明文。其中公钥在网络上传递,私钥只有乙自己拥有,不在网络上传递,这样即使知道了公钥 A 也无法解密。反过来通讯也一样。只要私钥不泄漏,通信就是安全的,这就是非对称加密算法。

使用场景1

公钥用于上锁(加密)。

私钥用于解锁(解密)。

package mainimport (        "crypto/rand"        "crypto/rsa"        "crypto/x509"        "encoding/pem"        "fmt"        "os")//Genkeys 生成秘钥对func Genkeys() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048) //通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串 x509_Privatekey := x509.MarshalPKCS1PrivateKey(privateKey) //创建一个用来保存私钥的以.pem结尾的文件 fp, _ := os.Create("privateKey.pem") defer fp.Close() //将私钥字符串设置到pem格式块中 pem_block := pem.Block{
Type: "PUBLIC KEY", Bytes: x509_Privatekey, } //转码为pem并输出到文件中 pem.Encode(fp, &pem_block) //处理公钥,公钥包含在私钥中 publickKey := privateKey.PublicKey //接下来的处理方法同私钥 //通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串 x509_PublicKey, _ := x509.MarshalPKIXPublicKey(&publickKey) pem_PublickKey := pem.Block{
Type: "PRIVATE KEY", Bytes: x509_PublicKey, } file, _ := os.Create("publicKey.pem") defer file.Close() //转码为pem并输出到文件中 pem.Encode(file, &pem_PublickKey)}//使用公钥进行加密func RSAencrypt(path string, msg []byte) []byte {
//首先从文件中提取公钥 fp, _ := os.Open(path) defer fp.Close() //测量文件长度以便于保存 fileinfo, _ := fp.Stat() buf := make([]byte, fileinfo.Size()) fp.Read(buf) //下面的操作是与创建秘钥保存时相反的 //pem解码 block, _ := pem.Decode(buf) //x509解码,得到一个interface类型的pub pub, _ := x509.ParsePKIXPublicKey(block.Bytes) //加密操作,需要将接口类型的pub进行类型断言得到公钥类型 cipherText, _ := rsa.EncryptPKCS1v15(rand.Reader, pub.(*rsa.PublicKey), msg) return cipherText}//使用私钥进行解密func RSAdecrypt(path string, cipherText []byte) []byte {
//同加密时,先将私钥从文件中取出,进行二次解码 fp, _ := os.Open(path) defer fp.Close() fileinfo, _ := fp.Stat() buf := make([]byte, fileinfo.Size()) fp.Read(buf) block, _ := pem.Decode(buf) PrivateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes) //二次解码完毕,调用解密函数 afterDecrypter, _ := rsa.DecryptPKCS1v15(rand.Reader, PrivateKey, cipherText) return afterDecrypter}func main() {
content:="今晚打老虎" fmt.Printf("原文: %s\n",content) Genkeys() //生成秘钥对文件 cipher :=RSAencrypt("./PublicKey.pem",[]byte(content)) //加密内容 fmt.Printf("加密后内容: %s\n",base64.StdEncoding.EncodeToString(cipher)) origin:= RSAdecrypt("./PrivateKey.pem",cipher) fmt.Printf("解密后内容: %s\n",string(origin))}

输出

原文: 今晚打老虎加密后内容: Ox4+I2CHgWGtek2Nn3ELUD+xHRwPztlYlEsFK3matx+hs7707c4goZftxcNsW7xKDn8so0IN5py2kxdTdxjyE1X0oyIOGF6eulzUWj7ty6eYFIW4dqT0YGnFJUEU4uOtskQavb4zYACiUp0TGT2PpXfCl12xgsugDIjlOWJ60JyfAsvDl2odsfuCEzyBqlinr+8diIy3yu6XOz10fwVb2QQ8ZgvRjf60siPrwVpkcmnlKemthi5cIMZNUa7UE+qLTzYBI8XaynA3TNc/0JFWKGLdP7Q/owMZWuzwDIIigENs0hBTmYWkHcZypes889Co+EBIrxKiV67fNqb/u0KZJw==解密后内容: 今晚打老虎

使用场景2

私有密钥用于“上锁”(加密得到hash值签名)。

公有密钥用于“解锁”(验证签名)。

package mainimport (        "crypto"        "crypto/rand"        "crypto/rsa"        "crypto/sha256"        "crypto/x509"        "encoding/base64"        "encoding/pem"        "fmt"        "os")//使用私钥签名,path是私钥路径,msg是要签名的信息func RsaSign(path string, msg []byte) []byte {
//签名函数中需要的数据散列值 //首先从文件中提取公钥 fp, _ := os.Open(path) defer fp.Close() fileinfo, _ := fp.Stat() buf := make([]byte, fileinfo.Size()) fp.Read(buf) block, _ := pem.Decode(buf) PrivateKey, _ := x509.ParsePKCS1PrivateKey(block.Bytes) //加密操作,需要将接口类型的pub进行类型断言得到公钥类型 hash := sha256.Sum256(msg) //调用签名函数,填入所需四个参数,得到签名 sign, _ := rsa.SignPKCS1v15(rand.Reader, PrivateKey, crypto.SHA256, hash[:]) return sign}func VerifySign(path string, signText []byte, plainText []byte) bool {
//首先从文件中提取公钥 fp, _ := os.Open(path) defer fp.Close() //测量文件长度以便于保存 fileinfo, _ := fp.Stat() buf := make([]byte, fileinfo.Size()) fp.Read(buf) //下面的操作是与创建秘钥保存时相反的 //pem解码 block, _ := pem.Decode(buf) //x509解码,得到一个interface类型的pub pub, _ := x509.ParsePKIXPublicKey(block.Bytes) //签名函数中需要的数据散列值 hash := sha256.Sum256(plainText) //验证签名 err := rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA256, hash[:], signText) if err != nil {
return false } else {
return true }}func main() {
content:="I am Enzo" fmt.Printf("原文: %s\n",content) hash:=RsaSign("./PrivateKey.pem",[]byte(content)) fmt.Printf("RSA签名: %s \n",base64.StdEncoding.EncodeToString(hash)) result:=VerifySign("./publicKey.pem",hash,[]byte(content)) fmt.Printf("验证结果: %v \n",result)}输出:原文: I am EnzoRSA签名: JHWw6t6ZRItPwQkWk/DuhQVqhFXa+AgpJoZlDhfNmJrviw9JGlMoDGzaGHKp88T9kO6MiLJjK62EsZ8bHRfEr6vs/b0yU8v7Cj6VCpirHWQ/H1+K5Y4+Yfw5hFmd26bch43tCo6z+NaakRl2Nwu32zqaDTdLoNt68Ia81YUM6i3Nl/5mH89cuklizTezpvyUmrucXrajEBD6KSqmm4Ggxw5tVJBl5H6I9eb2xRBJcrZk2x2MRH4H+neXKQsAImmI2pyseikklu9ImV9cX87gBPFgV6s7xHOhFwn5JWgxspcFLexA+Y7pBZYJwPlFq8aaXbV2VvEPWT0qY/c85DTppg== 验证结果: true

转载地址:https://blog.csdn.net/weixin_39172380/article/details/97249497 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:golang实现AES对称加密
下一篇:AIX文件系统扩容和切换启动盘

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年03月31日 07时43分07秒