RSA加密——go语言版

  • 源起
  • 公钥和私钥格式关系
    • 公钥
    • 私钥
  • go语言生成公私钥
  • go加载私钥
    • pkcs1
    • pkcs8
  • go加载公钥
  • go进行rsa加密和验签
  • openssl生成的公私钥
  • 去掉私钥的密码
  • openssl公钥和openssh公钥互转
  • 参考

源起

在做rsa加密验签的过程中遇到了一些问题,在对整个rsa体系不够了解的情况下花了很多的时间去尝试,但总是各种不通、各种头疼。

在尝试和搜索方案的过程中,不断的发现原来平时对rsa的了解是如此的少,rsa的体系是如此的庞大和庞杂。

不知道大家对rsa的了解程度如何,作为一个几年经验的后端程序员来说,对加密的大致体系有所了解,知道简单异或、md5、对称、非对称、用过几种对称加密算法。非对称加密在做支付对接的时候也有所接触。对rsa加密的原理有所了解,知道如何配置ssh免密、如何配置git的ssh、如何配置nginx的单向、双向ssl证书。

然而,这些只是外围知识而已!!!

当然,由于不是密码学专业,也不是安全方向,这里不对非对称加密的体系和算法进行分析,我个人也没有去学习和分析。这里仅包含在处理问题和后续梳理过程中涉及的知识要点。

公钥和私钥格式关系

这个格式关系很重要。对于理解秘钥加载的步骤,对于拿到手上的各种样式的秘钥的理解能有一个心理准备,有一个总体的可能性判断。

公钥

一般来说,我们遇到的公钥是PEM格式,PEM格式是对DER格式公钥的一种封装,封装的内容包括以下几块:

块名称 块内容示例
-----BEGIN PUBLIC KEY-----
公钥 base64.encode(public_key_string)
-----END PUBLIC KEY-----

以下是一个PEM格式公钥的示例:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA+xGZ/wcz9ugFpP07Nspo6U17l0YhFiFpxxU4pTk3Lifz9R3zsIsu
ERwta7+fWIfxOo208ett/jhskiVodSEt3QBGh4XBipyWopKwZ93HHaDVZAALi/2A
+xTBtWdEo7XGUujKDvC2/aZKukfjpOiUI8AhLAfjmlcD/UZ1QPh0mHsglRNCmpCw
mwSXA9VNmhz+PiB+Dml4WWnKW/VHo2ujTXxq7+efMU4H2fny3Se3KYOsFPFGZ1TN
QSYlFuShWrHPtiLmUdPoP6CV2mML1tk+l7DIIqXrQhLUKDACeM5roMx0kLhUWB8P
+0uj1CNlNN4JRZlC7xFfqiMbFRU9Z4N6YwIDAQAB
-----END RSA PUBLIC KEY-----

HEX是十六进制编码格式,用的比较少,以下是一个十六进制格式的公钥示例:

00 00 00 07 73 73 68 2d 72 73 61 00 00 00 01 25 00 00 01 00 7f 9c 09
8e 8d 39 9e cc d5 03 29 8b c4 78 84 5f d9 89 f0 33 df ee 50 6d 5d d0
16 2c 73 cf ed 46 dc 7e 44 68 bb 37 69 54 6e 9e f6 f0 c5 c6 c1 d9 cb
f6 87 78 70 8b 73 93 2f f3 55 d2 d9 13 67 32 70 e6 b5 f3 10 4a f5 c3
96 99 c2 92 d0 0f 05 60 1c 44 41 62 7f ab d6 15 52 06 5b 14 a7 d8 19
a1 90 c6 c1 11 f8 0d 30 fd f5 fc 00 bb a4 ef c9 2d 3f 7d 4a eb d2 dc
42 0c 48 b2 5e eb 37 3c 6c a0 e4 0a 27 f0 88 c4 e1 8c 33 17 33 61 38
84 a0 bb d0 85 aa 45 40 cb 37 14 bf 7a 76 27 4a af f4 1b ad f0 75 59
3e ac df cd fc 48 46 97 7e 06 6f 2d e7 f5 60 1d b1 99 f8 5b 4f d3 97
14 4d c5 5e f8 76 50 f0 5f 37 e7 df 13 b8 a2 6b 24 1f ff 65 d1 fb c8
f8 37 86 d6 df 40 e2 3e d3 90 2c 65 2b 1f 5c b9 5f fa e9 35 93 65 59
6d be 8c 62 31 a9 9b 60 5a 0e e5 4f 2d e6 5f 2e 71 f3 7e 92 8f fe 8b

ssh生成的公钥,有自己的格式,由3部分组成“ssh-rsa”字符+公钥+备注。以下是一个ssh公钥的示例:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3O26p3AlNy5JalOon2E2q62fygTBQZkVv4LJP1v7UxMH8pMNbsP1YG2keMotLtakHiqfHDd/s6eUDQYxU2nVdwruwPmP65mfhD0xTXsFFOdn+B80EVQdkm12h9Mcd9pVzMTplvB9v2j/8RX8UH45KsCgB5GcZJwdexJWys64Q+5eP386xZ7ow3XkKDS+XCEQTZaz+vN97aOQontwp+Dj0lB0VKhpnCWI5cadFRCNVitWaLLK6STRrYKV9CTUWOIuIV+2EC85UGIGmD3M+z6S3RZepoOZPDCRgaXdiNNsAAWa2ULZ9Wep9Qtly0NEsQ9EHrmeHadnDaWQy9w/KLsYj 362493050@qq.com

私钥

私钥常遇到的是pkcs1和pkcs8两种标准,有时候还会遇到加密后的私钥,需要用密码加载或者去掉秘钥后再使用。后续会说到格式转换和去掉私钥密码的方法。

go语言生成公私钥

由于不同语言对rsa公私钥支持程度不同,所以很可能遇到在java项目用的很好的秘钥,在go语言没有办法用。但是又不确定是秘钥的问题,还是代码写法的问题。这时候如果能够生成一套所使用语言支持的秘钥对,对解决问题和建立信心都有很大帮助。

func GenRsaKey(bits int) error {// 生成私钥文件privateKey, err := rsa.GenerateKey(rand.Reader, bits)if err != nil {return err}derStream := x509.MarshalPKCS1PrivateKey(privateKey)block := &pem.Block{Type:  "RSA PRIVATE KEY",Bytes: derStream,}file, err := os.Create("private.pem")if err != nil {return err}err = pem.Encode(file, block)if err != nil {return err}// 生成公钥文件publicKey := &privateKey.PublicKeyderPkix, err := x509.MarshalPKIXPublicKey(publicKey)if err != nil {return err}block = &pem.Block{Type:  "PUBLIC KEY",Bytes: derPkix,}file, err = os.Create("public.pem")if err != nil {return err}err = pem.Encode(file, block)if err != nil {return err}return nil
}

go加载私钥

pkcs1

package mainimport ("fmt""crypto/x509""encoding/pem""crypto/rsa")func main () {privateKey := `your key`blockPri, _ := pem.Decode([]byte(privateKey))if blockPri == nil {fmt.Println("err1")return}       priKey, err := x509.ParsePKCS1PrivateKey([]byte(blockPri.Bytes))if err != nil {fmt.Println(err)fmt.Println("err2")return }fmt.Println("ok")fmt.Println(priKey)}

pkcs8

package mainimport ("fmt""crypto/x509""encoding/pem""crypto/rsa")func main () {privateKey := `your key`blockPri, _ := pem.Decode([]byte(privateKey))if blockPri == nil {fmt.Println("err1")return}prkI, err := x509.ParsePKCS8PrivateKey([]byte(blockPri.Bytes))if err != nil {fmt.Println(err)fmt.Println("err2")return }priKey := prkI.(*rsa.PrivateKey)fmt.Println("ok")fmt.Println(priKey)}

go加载公钥

 blockPub, _ := pem.Decode([]byte(publicKey))if blockPub == nil {fmt.Println("err1")return}pubKey, err := x509.ParsePKIXPublicKey(publicKey)if err != nil {fmt.Println(err)fmt.Println("err2")return }fmt.Println("ok")fmt.Println(pubKey)

go进行rsa加密和验签

以下是hash摘要方式的rsa加密验签,也可以使用md5摘要方式的rsa加密:

//your_private_key和your_public_key都是上述《go加载rsa公、私钥》部分创建的结构体类型
func Sign(src []byte, hash crypto.Hash) ([]byte, error) {h := hash.New()h.Write(src)hashed := h.Sum(nil)return rsa.SignPKCS1v15(rand.Reader, your_private_key, hash, hashed)
}func Verify(src []byte, sign []byte, hash crypto.Hash) error {h := hash.New()h.Write(src)hashed := h.Sum(nil)return rsa.VerifyPKCS1v15(your_public_key, hash, hashoed, sign)
}

这里说一下为什么要先摘要,再加密和验签,这里主要考虑的是性能,因为用rsa加密方式对性能的损耗比较大,如果待加密字串长的话,加密过程对性能的影响更大。所以,一般会先对字符串进行hash或者md5摘要。

openssl生成的公私钥

//生成私钥,默认生成的是pkcs1格式私钥
genrsa -out rsa_private_key.pem 1024
//转成pkcs8格式
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
//生成公钥
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

去掉私钥的密码

//执行会后,会要求你输入私钥使用的密码
openssl rsa -in my_private_key.pem -out new_private_key.pem

openssl公钥和openssh公钥互转

两者的私钥是同样的格式,但是两者的公钥是不同的格式,所以转换的基础就是私钥。通过私钥生成另一种格式的公钥。

比如,如果已经有了openssl生成的私钥,可以用如下命令生成openssh的公钥:

ssh-keygen  -y -f openssh_private.pem > public_key.pub

~~~~~~~~~~~~~~~~~~~~~~~~~ 福利分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~
-长期内推-:头条、快手、美团、阿里、陌陌、当当。有需要的朋友可以发邮件到我的邮箱xiaofan860412@163.com。

参考

本文参考了下列文章,有的代码片段直接取自文章:

  1. Golang加密系列之RSA
  2. GO加密解密RSA番外篇:生成RSA密钥
  3. GO加密解密之RSA
  4. PKCS标准
  5. openssl数字证书常见格式与协议介绍
  6. Generating an SSH Key Pair
  7. Generate Private key with OpenSSL and Public key ssh-keygen for SSH
  8. Converting keys between openssl and openssh
  9. How are the files in ~/.ssh related to the theory?
  10. OpenSSH RSA Public Key format
  11. openssl 生成公私钥对
  12. 去掉ssh key的密码

RSA加密——go语言版相关推荐

  1. rsa加密c语言源码库,RSA加密算法源代码C语言实现.doc-资源下载在线文库www.lddoc.cn...

    RSA加密算法_源代码__C语言实现.doc RSA 算法 1978 年就出现了这种算法,它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作,也很流行.算法的名字以发明者的名字命名Ro ...

  2. go java rsa_RSA加密——go语言版-Go语言中文社区

    源起 在做rsa加密验签的过程中遇到了一些问题,在对整个rsa体系不够了解的情况下花了很多的时间去尝试,但总是各种不通.各种头疼. 在尝试和搜索方案的过程中,不断的发现原来平时对rsa的了解是如此的少 ...

  3. 电报加密C语言版(字符串整体后移一位的方法)

    题目 1042: [编程入门]电报加密 时间限制: 1Sec 内存限制: 128MB 题目描述 输入一行电报文字,将字母变成其下一字母(如'a'变成'b'--'z'变成'a'其它字符不变). 输入格式 ...

  4. rsa加解密算法报告c语言,RSA加密解密算法c语言程序Word版

    <RSA加密解密算法c语言程序Word版>由会员分享,可在线阅读,更多相关<RSA加密解密算法c语言程序Word版(5页珍藏版)>请在人人文库网上搜索. 1.传播优秀Word版 ...

  5. 跨语言平台的RSA加密、解密、签名、验证算法的实现

      在网上可以找到各种各样的RSA实现代码,原理都是RSA算法的基本原理,但是在处理数据块划分.填充等问题上都是形形色色的,本文旨在探讨.实现遵循RFC 2313 PKCS#1 v1.5标准的一种跨语 ...

  6. php rsa加密实例,关于PHP语言的RSA加密实例讲解

    本文主要向大家介绍了关于PHP语言的RSA加密实例讲解,通过具体的内容向大家展示,希望对大家学习php语言有所帮助. 这几天做了一些接口的对接需要用到RSA加密,百度一番发现原来有个openssl_p ...

  7. MacOS下使用C语言基于openssl库进行RSA加密解密

    MacOS下使用C语言基于openssl库进行RSA加密解密 1 安装openssl并生成密钥 首先当然要安装openssl(这里记得看一下安装路径,应该是/usr/local/Cellar/open ...

  8. GO语言实现RSA 加密和解密的实现

    RSA 加密和解密的实现 openssl生成私钥 openssl genrsa -out rsa_private_key.pem 1024 openssl生成公钥 openssl rsa -in rs ...

  9. 一个简单地C语言程序展示RSA加密原理

    #include<stdio.h> #include<stdlib.h> #include<time.h> #include<math.h>//质数判定 ...

最新文章

  1. 爬虫之lxml模块中etree.tostring函数的使用
  2. linux定义别名出错,Linux自定义别名alias重启失效问题
  3. tf.where() 详解
  4. vim 有用命令-20190217
  5. One-Stage Visual Grounding论文汇总
  6. sybase数据库脱机,无法联机问题处理
  7. linux磁盘管fdisk,Linux 磁盘分区工具和挂载,fdisk管理分区详解
  8. Java程序员校招蚂蚁金服,大专生出身,做Java程序员真的没有春天吗
  9. HDU-1069 Monkey and Banana 动态规划
  10. word课程表设置符号与编号_小学生课程表word模板 小学生使用WORD.doc
  11. PPT设置自动保存时间 mac_如何让你的PPT变得高大上?
  12. mini6410 LED驱动程序及LED测试程序的设计
  13. 超人游戏_将障碍画在背景中用pygame.mask.from_threshold实现超人和不同颜色障碍精准碰撞检测
  14. 用 regedit 命令把注册表 .reg 文件导入注册表- -
  15. main flag redefined: graceful
  16. Excel办公中的应用(中秋快乐学习)(注意:全部为英文符号)
  17. python start方法_进程方法 run和start的区别
  18. mysql数据库基操所遇问题及相关知识及命令记录
  19. iOS系统的各种设备识别码
  20. Android kotlin run函数学习

热门文章

  1. 关于typescript 报错问题
  2. Python爬虫入门教程【3】:美空网数据爬取
  3. StrongSwan虚拟测试环境搭建
  4. codeforces1469E. A Bit Similar
  5. LLE降维——代码实现
  6. 计算G711语音的打包长度和RTP里timestamp的增长量
  7. C++ STL之 queue和deque用法详解
  8. 七牛云「云上法庭」:免去来回奔波苦,公平正义不掉线
  9. java如何将英文日期转成中文_中文字符串日期改成英文的日期格式
  10. python不适合大型项目_在大型项目上,Python 是个烂语言吗? |