go包:crypto-rsa非对称加密

1. 维基百科释义

RSA加密算法是一种非对称加密算法在公开密钥加密电子商业中被广泛使用。RSA是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和[伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的。当时他们三人都在[麻省理工学院工作。RSA 就是他们三人姓氏开头字母拼在一起组成的。

2.生成密钥

RSA私钥存在PKCS1PKCS8两种格式,通过openssl生成的私钥格式为PKCS1,公钥格式为PKCS8

2.1 使用openssl命令

1.生成私钥(PKCS1格式)
# 生成私钥
➜ openssl genrsa -out private_ssl.pem 1024
Generating RSA private key, 1024 bit long modulus
.......++++++
.............................................++++++
e is 65537 (0x10001)
# 查看私钥
➜ cat private_ssl.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDSgkiwisLr7yTuKnn6jANvRXRfnA9PINojpPiegMkv/mnScEvM
czP8OZjpFrsjSKFnlc6OX04O+4G3GuBMjc75wQw79auM4WMJtSh3PAWiBGu6Woto
AqZFbWRnIzk2Wjw1xSJxpOUa0ed1plU/jut1dKgDTi4q+BDqGizI2JeJdQIDAQAB
AoGAFij24/bHjDSxi4zXKGPi3KzQElyIVAkeTZBJR85A35eFpkyB/jTGbS/XA/qL
mqxDqXbgtqYbvoIFZrQilox7FCi5AzxhQDB3wD67y5OjuSWhTKypq5UOj/6y9zkC
Gbzi4zIBlOZIskfj81a+WBg7vi6FCaCg105nDJOCDs0IYiECQQDpZNBoolQGgsmR
M/x699WXhG1xYV9bTDhBKpsW/O0mRjiK/6pCbDjRWGxeB+BmFmRofYwWRj2stzkg
We1if8jNAkEA5uYFWBqHpKpFUULM7fqoyixrTXz+3h22vcKc4s/xhSCfM8yCS/ad
7S4tzpEGAenLPWYERhm6Cm/0yVavtYBjSQJBAN0MBG71P0ujVzDU4c29KGiGnfkC
VgPsHmNp7NVK23iijS7okeKzCOUNMCWmpBtMHfDw51q5T/Ri3BIN2cyuZgkCQQCV
Hz2YVxn/mRBHmRLtJ5PXbrSmSPH51crt50CXo6DiT91CAPStxsrcIZTn8fWlSq8+
KiLce0UR9JhtaBT27cIxAkEArozPsVt273/UkAru4LgBURK5ZEaHful/oK0xRDdg
fq+Ij4rs24CVPlNXfycZEDrKYMS9ScZrraf8JsTSEBx++w==
-----END RSA PRIVATE KEY-----
2.生成公钥(PKCS8格式)
# 生成公钥
➜ openssl rsa -in private_ssl.pem -pubout -out public_ssl.pem
writing RSA key
# 查看公钥
➜ cat public_ssl.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSgkiwisLr7yTuKnn6jANvRXRf
nA9PINojpPiegMkv/mnScEvMczP8OZjpFrsjSKFnlc6OX04O+4G3GuBMjc75wQw7
9auM4WMJtSh3PAWiBGu6WotoAqZFbWRnIzk2Wjw1xSJxpOUa0ed1plU/jut1dKgD
Ti4q+BDqGizI2JeJdQIDAQAB
-----END PUBLIC KEY-----
3. 私钥PKCS1转PKCS8
➜ openssl pkcs8 -topk8 -inform pem -in private_ssl.pem -outform PEM -nocrypt
-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANKCSLCKwuvvJO4q
efqMA29FdF+cD08g2iOk+J6AyS/+adJwS8xzM/w5mOkWuyNIoWeVzo5fTg77gbca
4EyNzvnBDDv1q4zhYwm1KHc8BaIEa7pai2gCpkVtZGcjOTZaPDXFInGk5RrR53Wm
VT+O63V0qANOLir4EOoaLMjYl4l1AgMBAAECgYAWKPbj9seMNLGLjNcoY+LcrNAS
XIhUCR5NkElHzkDfl4WmTIH+NMZtL9cD+ouarEOpduC2phu+ggVmtCKWjHsUKLkD
PGFAMHfAPrvLk6O5JaFMrKmrlQ6P/rL3OQIZvOLjMgGU5kiyR+PzVr5YGDu+LoUJ
oKDXTmcMk4IOzQhiIQJBAOlk0GiiVAaCyZEz/Hr31ZeEbXFhX1tMOEEqmxb87SZG
OIr/qkJsONFYbF4H4GYWZGh9jBZGPay3OSBZ7WJ/yM0CQQDm5gVYGoekqkVRQszt
+qjKLGtNfP7eHba9wpziz/GFIJ8zzIJL9p3tLi3OkQYB6cs9ZgRGGboKb/TJVq+1
gGNJAkEA3QwEbvU/S6NXMNThzb0oaIad+QJWA+weY2ns1UrbeKKNLuiR4rMI5Q0w
JaakG0wd8PDnWrlP9GLcEg3ZzK5mCQJBAJUfPZhXGf+ZEEeZEu0nk9dutKZI8fnV
yu3nQJejoOJP3UIA9K3GytwhlOfx9aVKrz4qItx7RRH0mG1oFPbtwjECQQCujM+x
W3bvf9SQCu7guAFRErlkRod+6X+grTFEN2B+r4iPiuzbgJU+U1d/JxkQOspgxL1J
xmutp/wmxNIQHH77
-----END PRIVATE KEY-----

3.读取密钥

3.1 代码

// 读取PKCS1格式私钥
func ReadRSAPKCS1PrivateKey(path string) (*rsa.PrivateKey, error) {
    // 读取文件
    context, err := ioutil.ReadFile(path)
    if err != nil {
        return nil, err
    }
    // pem解码
    pemBlock, _ := pem.Decode(context)
    // x509解码
    privateKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
    return privateKey, err
}
// 读取公钥(包含PKCS1和PKCS8)
func ReadRSAPublicKey(path string) (*rsa.PublicKey, error) {
    var  err error
    // 读取文件
    readFile, err := ioutil.ReadFile(path)
    if err != nil {
        return nil, err
    }
    // 使用pem解码
    pemBlock, _ := pem.Decode(readFile)
    var pkixPublicKey interface{}
    if pemBlock.Type == "RSA PUBLIC KEY" {
        // -----BEGIN RSA PUBLIC KEY-----
        pkixPublicKey, err = x509.ParsePKCS1PublicKey(pemBlock.Bytes)
    } else if pemBlock.Type == "PUBLIC KEY" {
        // -----BEGIN PUBLIC KEY-----
        pkixPublicKey, err = x509.ParsePKIXPublicKey(pemBlock.Bytes)
    }
    if err != nil {
        return nil,err
    }
    publicKey := pkixPublicKey.(*rsa.PublicKey)
    return publicKey, nil
}

3.2 测试

// 读取密钥
func TestReadKey(t *testing.T) {
    // pkcs1格式-私钥
    privatePKCS1KeyPath := "../../tmp/private_ssl.pem"
    privatePKCS1Key, err := crypto.ReadRSAPKCS1PrivateKey(privatePKCS1KeyPath)
    if err != nil {
        t.Error(err)
    }
    fmt.Printf("PKCS1私钥: %#v\n",privatePKCS1Key)
    // pkcs8格式-公钥
    publicPKCS8KeyPath := "../../tmp/public_ssl.pem"
    publicPKCS8Key, err := crypto.ReadRSAPublicKey(publicPKCS8KeyPath)
    if err != nil {
        t.Error(err)
    }
    fmt.Printf("PKCS8公钥: %#v\n",publicPKCS8Key)
}

4.加密

4.1 代码

// 加密(使用公钥加密)
func RSAEncrypt(data, publicKeyPath string) (string, error) {
    // 获取公钥
  // ReadRSAPublicKey代码在 【3.读取密钥】
    rsaPublicKey, err := ReadRSAPublicKey(publicKeyPath)
    if err != nil {
        return "", err
    }
    // 加密
    encryptPKCS1v15, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, []byte(data))
    if err != nil {
        return "",err
    }
    // 把加密结果转成Base64
    encryptString := base64.StdEncoding.EncodeToString(encryptPKCS1v15)
    return encryptString, err
}

4.2 测试

// 加密测试
func TestRsaEncrypt(t *testing.T) {
    publicKeyPath := "../../tmp/public_ssl.pem"
    data := "123456"
    encrypt, err := crypto.RSAEncrypt(data, publicKeyPath)
    if err != nil {
        t.Error(err)
    }
    fmt.Printf("加密结果:%v \n",encrypt)
}
/** 输出
=== RUN   TestRsaEncrypt
加密结果:SRYyBXd4p+wUeTZ5478g+hW2P3OvqhYMyPwW/j91SappgxMWC/O3vCG2aVTcAHknUkK2oEs6e28deKuOvOkjSWl/jnXFDCkXklgbgnXJtfu2FjP9jXhG2b6/Eo3okxLvLXZtkaRAgZKNbbKkeiNASUO4IidkoNrnI4aOuuuVIOY= 
--- PASS: TestRsaEncrypt (0.00s)
PASS
*/

5.解密

5.1 代码

// 解密(使用私钥解密)
func RSADecrypt(base64data,privateKeyPath string) (string,error) {
    // data反解base64
    decodeString, err := base64.StdEncoding.DecodeString(base64data)
    if err != nil {
        return "", err
    }
    // 读取密钥
    rsaPrivateKey, err := ReadRSAPKCS1PrivateKey(privateKeyPath)
    if err != nil {
        return "", err
    }
    // 解密
    decryptPKCS1v15, err := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, decodeString)
    return string(decryptPKCS1v15),err
}

5.2 测试

// 解密测试
func TestRsaDecrypt(t *testing.T) {
    privateKeyPath := "../../tmp/private_ssl.pem"
    data := "pUYa4set6XkBshfio5g2hzPx1tA67sxEvJBpJiuK3McJ9cPJAXzuRkWIy4s6cDQOhrPUaNXhr3M3WLHH19/eaqcNZz1yOFZwgGKmkWtdmygtLB/wrDant9uRfXrvzlV9iMq+cUlqsrwuCa0wcGEBNHRhIJOQSTs+SxaRTeoRCbU="
    encrypt, err := crypto.RSADecrypt(data, privateKeyPath)
    if err != nil {
        t.Error(err)
    }
    fmt.Printf("解密结果:%v \n",encrypt)
}
/** 输出
=== RUN   TestRsaDecrypt
解密结果:123456 
--- PASS: TestRsaDecrypt (0.00s)
PASS
*/

6.数据签名

6.1 加签

a. 代码

// 对数据进行数字签名
func GetRSASign(data, privateKeyPath string) (string, error) {
    // 读取私钥
    privateKey, err := ReadRSAPKCS1PrivateKey(privateKeyPath)
    if err != nil {
        return "", err
    }
    // 计算Sha1散列值
    hash := sha256.New()
    hash.Write([]byte(data))
    sum := hash.Sum(nil)
    // 从1.5版本规定,使用RSASSA-PKCS1-V1_5-SIGN 方案计算签名
    signPKCS1v15, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, sum)
    // 结果转成base64
    toString := base64.StdEncoding.EncodeToString(signPKCS1v15)
    return toString, err
}

b. 测试

// 数据加签
func TestAddSign(t *testing.T) {
    privateKeyPath := "../../tmp/private_ssl.pem"
    data := "123456"
    sign, err := crypto.GetRSASign(data,privateKeyPath)
    if err != nil {
        t.Error(err)
    }
    fmt.Printf("数据签名: %v \n",sign)
}
/** 输出
=== RUN   TestAddSign
数据签名: QnGqGbIqoHjJG1l+JiaOKWBdX+h00lnKCoO2rTYKIro9hoaDj7nqmu+Mxsuo+2jumicvCNBZNOpMzYryjZf0x7Q4ycLBtqtCWuFRasiInUO7Avy19LRTjdMf2xw9968vilB/xEAQ53JXIDUVvCsMxTfpHI9oRiWEGXWNkhfkjkQ= 
--- PASS: TestAddSign (0.00s)
PASS
*/

6.2 验签

a. 代码

// 验证签名
func VerifyRsaSign(data, publicKeyPath, base64Sign string) (bool, error) {
    // 反解base64
    sign,err := base64.StdEncoding.DecodeString(base64Sign)
    if err != nil {
        return false, err
    }
    // 获取公钥
    publicKey, err := ReadRSAPublicKey(publicKeyPath)
    if err != nil {
        return false, err
    }
    // 计算Sha1散列值
    hash := sha256.New()
    hash.Write([]byte(data))
    bytes := hash.Sum(nil)
    err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, bytes, sign)
    return err == nil, err
}

b. 测试

// 数据签名验证
func TestVaSign(t *testing.T) {
    publicKeyPath := "../../tmp/public_ssl.pem"
    data := "123456"
    sign := "QnGqGbIqoHjJG1l+JiaOKWBdX+h00lnKCoO2rTYKIro9hoaDj7nqmu+Mxsuo+2jumicvCNBZNOpMzYryjZf0x7Q4ycLBtqtCWuFRasiInUO7Avy19LRTjdMf2xw9968vilB/xEAQ53JXIDUVvCsMxTfpHI9oRiWEGXWNkhfkjkQ="
    verifyRsaSign,err := crypto.VerifyRsaSign(data, publicKeyPath, sign)
    if err != nil {
        fmt.Printf("验签失败: %v \n",err)
    }
    fmt.Printf("验签结果: %v \n",verifyRsaSign)
}
/** 输出
=== RUN   TestVaSign
验签结果: true 
--- PASS: TestVaSign (0.00s)
PASS
*/
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容