Golang与非对称加密
介绍非对称加密的基本原理、公私钥机制,以及在 Go 中的应用。

非对称加密介绍
非对称加密和对称加密不同,主要区别如下
-
使用公钥加密,使用私钥解密
-
公钥和私钥不同
-
公钥可以公布给所有人
-
私钥只有自己保存
-
相比于对称加密,运算速度非常慢
加密过程:明文+公钥——>密文 解密过程:密文+私钥——>明文
非对称加密算法常用于数据加密和身份认证, 常见的非对称加密算法如下
-
RSA: 由RSA公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的
-
DSA(Digital Signature Algorithm): 数字签名算法,是一种标准的
DSS(数字签名标准) -
ECC(Elliptic Curves Cryptography): 椭圆曲线密码编码学
-
ECDSA(Elliptic Curve Digital Signature Algorithm): 基于椭圆曲线的
DSA签名算法
DSA
DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这样,当使用别人 的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却做不到,但是其缺点就是只能用于数字签名,不能用于加密
RSA
在1976年,由于对称加密算法已经不能满足需要,Diffie和Hellman发表了一篇叫《密码学新动向》的文章,介绍了公匙加密的概念,由Rivet、Shamir、Adelman提出了RSA算法
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准
命名:Ron Rivest、Adi Shamir、Leonard Adleman
- 密钥越长,越难破解,目前
768位的密钥还无法破解(至少没人公开宣布),因此可以认为1024位的RSA密钥基本安全,2048位的密钥极其安全 RSA的算法原理主要用到了数论
RSA的加密过程
1、随机选择两个不相等的质数p和q,p=61,q=53
2、计算p和q的乘积,n=3233
3、计算n的欧拉函数∅(n) = (p-1)(q-1),∅(n)=3120
4、随机选择一个整数e,使得1 < e < ∅(n),且e与∅(n)互质,e=17
5、计算e对于∅(n)的模反元素d,即求解e*d + ∅(n)*y =1,d=2753,y=-15
6、将n和e封装成公钥,n和d封装成私钥,公钥=(3233, 17),私钥=(3233, 2753)
调用示例
RSA使用示例代码
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/pem"
"fmt"
)
// 使用对方的公钥的数据, 只有对方的私钥才能解开
func encrypt(plain string, publicKey string) (cipherByte []byte, err error) {
msg := []byte(plain)
// 解码公钥
pubBlock, _ := pem.Decode([]byte(publicKey))
// 读取公钥
pubKeyValue, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)
if err != nil {
panic(err)
}
pub := pubKeyValue.(*rsa.PublicKey)
// 加密数据方法: 不用使用EncryptPKCS1v15方法加密,源码里面推荐使用EncryptOAEP, 因此这里使用安全的方法加密
encryptOAEP, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, pub, msg, nil)
if err != nil {
panic(err)
}
cipherByte = encryptOAEP
return
}
// 使用私钥解密公钥加密的数据
func decrypt(cipherByte []byte, privateKey string) (plainText string, err error) {
// 解析出私钥
priBlock, _ := pem.Decode([]byte(privateKey))
priKey, err := x509.ParsePKCS1PrivateKey(priBlock.Bytes)
if err != nil {
panic(err)
}
// 解密RSA-OAEP方式加密后的内容
decryptOAEP, err := rsa.DecryptOAEP(sha1.New(), rand.Reader, priKey, cipherByte, nil)
if err != nil {
panic(err)
}
plainText = string(decryptOAEP)
return
}
func test() {
msg := "Content bo be encrypted!"
// 获取公钥, 生产环境往往是文件中读取, 这里为了测试方便, 直接生成了.
publicKeyData := `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL
AUeJ6PeW+DAkmJWF6QIDAQAB
-----END PUBLIC KEY-----
`
// 获取私钥
privateKeyData := `-----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-----
`
cipherData, err := encrypt(msg, publicKeyData)
if err != nil {
panic(err)
}
fmt.Printf("encrypt message: %x\n", cipherData)
plainData, err := decrypt(cipherData, privateKeyData)
if err != nil {
panic(err)
}
fmt.Printf("decrypt message:%s\n", plainData)
}
func main() {
test()
}
ECC
ECC又称椭圆曲线加密
ECC(Elliptic Curve Cryptography)椭圆曲线加密算法,相比RSA,ECC可以使用更短的密钥,来实现与RSA相当或更高的安全
定义了椭圆曲线上的加法和二倍运算
椭圆曲线依赖的数学难题是:k为正整数,p是椭圆曲线上的点(称为基点),k*p=Q,已知Q和P,很难计算出k
ECC是建立在基于椭圆曲线的离散对数的难度, 大概过程如下:
给定椭圆曲线上的一个点P,一个整数k,求解Q=kP很容易;给定一个点P、Q,知道Q=kP,求整数k确是一个难题。ECDH即建立在此数学难题之上
今天只有短的RSA钥匙才可能被强力方式解破。到2008