golang 如何获取pem格式RSA公私钥长度

时间:2022-11-18 15:39:13

因在做license注册机制当中,有对根据本地RSA pem密钥文件判断出RSA的公私密钥长度的需求(即:根据pem内容判断出RSA密钥是1024位或者2048位,或者其他位数等),因此个人通过思考,摸索整理出一个方法,予以记录,备用,分享。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package main
import (
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "errors"
    "fmt"
    "io/ioutil"
    "os"
)
//全局变量
var privateKey, publicKey []byte
func init() {
    var err error
    publicKey, err = ioutil.ReadFile("public.pem")
    if err != nil {
        os.Exit(-1)
    }
    privateKey, err = ioutil.ReadFile("private.pem")
    if err != nil {
        os.Exit(-1)
    }
}
/**
 * @brief 获取RSA公钥长度
 * @param[in]    PubKey               RSA公钥
 * @return  成功返回 RSA公钥长度,失败返回error  错误信息
 */
func GetPubKeyLen(PubKey []byte) (int, error) {
    if PubKey == nil {
        return 0, errors.New("input arguments error")
    }
    block, _ := pem.Decode(PubKey)
    if block == nil {
        return 0, errors.New("public rsaKey error")
    }
    pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        return 0, err
    }
    pub := pubInterface.(*rsa.PublicKey)
    return pub.N.BitLen(), nil
}
/**
 * @brief 获取RSA私钥长度
 * @param[in]    PriKey               RSA私钥
 * @return  成功返回 RSA私钥长度,失败返回error  错误信息
 */
func GetPriKeyLen(PriKey []byte) (int, error) {
    if PriKey == nil {
        return 0, errors.New("input arguments error")
    }
    block, _ := pem.Decode(PriKey)
    if block == nil {
        return 0, errors.New("private rsaKey error!")
    }
    priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        return 0, err
    }
    return priv.N.BitLen(), nil
}
func main() {
    //获取rsa 公钥长度
    PubKeyLen, _ := GetPubKeyLen(publicKey)
    fmt.Println("pbulic key len is ", PubKeyLen)
    //获取rsa 私钥长度
    PriKeyLen, _ := GetPriKeyLen(privateKey)
    fmt.Println("private key len is ", PriKeyLen)
}

附录:以下程序是产生RSA公私密钥的程序,附件,方便测试。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package main
import (
 "crypto/rand"
 "crypto/rsa"
 "crypto/x509"
 "encoding/pem"
 "flag"
 "log"
 "os"
)
func main() {
 var bits int
 flag.IntVar(&bits, "b", 1024, "密钥长度,默认为1024位")
 flag.Parse()
 
 if err := GenRsaKey(bits); err != nil {
 log.Fatal("密钥文件生成失败!")
 }
 log.Println("密钥文件生成成功!")
}
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: "私钥",
 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.PublicKey
 derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
 if err != nil {
 return err
 }
 block = &pem.Block{
 Type: "公钥",
 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
}

补充:golang 使用RSA生成公私钥,加密,解密,并使用SHA256进行签名,验证

话不多说直接上代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package main
import (
    "crypto"
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "crypto/x509"
    "encoding/hex"
    "encoding/pem"
    "errors"
    "fmt"
)
func main() {
    //rsa 密钥文件产生
    fmt.Println("-------------------------------获取RSA公私钥-----------------------------------------")
    prvKey, pubKey := GenRsaKey()
    fmt.Println(string(prvKey))
    fmt.Println(string(pubKey))
    fmt.Println("-------------------------------进行签名与验证操作-----------------------------------------")
    var data = "卧了个槽,这么神奇的吗??!!! ԅ(¯﹃¯ԅ) !!!!!!)"
    fmt.Println("对消息进行签名操作...")
    signData := RsaSignWithSha256([]byte(data), prvKey)
    fmt.Println("消息的签名信息: ", hex.EncodeToString(signData))
    fmt.Println("\n对签名信息进行验证...")
    if RsaVerySignWithSha256([]byte(data), signData, pubKey) {
        fmt.Println("签名信息验证成功,确定是正确私钥签名!!")
    }
    fmt.Println("-------------------------------进行加密解密操作-----------------------------------------")
    ciphertext := RsaEncrypt([]byte(data), pubKey)
    fmt.Println("公钥加密后的数据:", hex.EncodeToString(ciphertext))
    sourceData := RsaDecrypt(ciphertext, prvKey)
    fmt.Println("私钥解密后的数据:", string(sourceData))
}
//RSA公钥私钥产生
func GenRsaKey() (prvkey, pubkey []byte) {
    // 生成私钥文件
    privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
    if err != nil {
        panic(err)
    }
    derStream := x509.MarshalPKCS1PrivateKey(privateKey)
    block := &pem.Block{
        Type: "RSA PRIVATE KEY",
        Bytes: derStream,
    }
    prvkey = pem.EncodeToMemory(block)
    publicKey := &privateKey.PublicKey
    derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
    if err != nil {
        panic(err)
    }
    block = &pem.Block{
        Type: "PUBLIC KEY",
        Bytes: derPkix,
    }
    pubkey = pem.EncodeToMemory(block)
    return
}
//签名
func RsaSignWithSha256(data []byte, keyBytes []byte) []byte {
    h := sha256.New()
    h.Write(data)
    hashed := h.Sum(nil)
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("private key error"))
    }
    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        fmt.Println("ParsePKCS8PrivateKey err", err)
        panic(err)
    }
    signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
    if err != nil {
        fmt.Printf("Error from signing: %s\n", err)
        panic(err)
    }
    return signature
}
//验证
func RsaVerySignWithSha256(data, signData, keyBytes []byte) bool {
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("public key error"))
    }
    pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    hashed := sha256.Sum256(data)
    err = rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), crypto.SHA256, hashed[:], signData)
    if err != nil {
        panic(err)
    }
    return true
}
// 公钥加密
func RsaEncrypt(data, keyBytes []byte) []byte {
    //解密pem格式的公钥
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("public key error"))
    }
    // 解析公钥
    pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    // 类型断言
    pub := pubInterface.(*rsa.PublicKey)
    //加密
    ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, pub, data)
    if err != nil {
        panic(err)
    }
    return ciphertext
}
// 私钥解密
func RsaDecrypt(ciphertext, keyBytes []byte) []byte {
    //获取私钥
    block, _ := pem.Decode(keyBytes)
    if block == nil {
        panic(errors.New("private key error!"))
    }
    //解析PKCS1格式的私钥
    priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    // 解密
    data, err := rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
    if err != nil {
        panic(err)
    }
    return data
}

运行结果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-------------------------------获取RSA公私钥-----------------------------------------
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCgPwlGJrWqTYaoMkI8jXkEI8ewQ7E57G2Fi91WTXMMK7X6GsT9
VmnRcq++Rk/VS+4IPBlfWyVRg0NfQDyuKjed21fUPa9AIbpYWHgP/tojyeYC1+Ra
Xncrt9kLp7nW4FZMJmzwU9hfxIB0nhDQqhJenjdBZuYZfkICfMqyqbVkAwIDAQAB
AoGAJRcSDXOuPrHdBhdD74ILTaL+eFTis3Z+zxdVbsFUbK+9WhtSFxUmPv1dohvi
JIuDl9JZSRHurFRGhsh2gxVwc7JXwWfD0DmD8dvdzr8q85Jml9YVZ7uhHFqSO4cY
I7dlBOd7Uwjnc39E/d+1E/kWVNfKt7opPHgt02zOHLSxkbECQQDS7H3myu3oLOi0
Slpd1MmmHVOo2cqJ1b3H6E8JtEjmHGswWTYvQNAe4yZ+Kffsp5LUYujedncPKvEj
4G+iz44bAkEAwn4Bx30FKTri/tybgSnCWKwTGSX479829Xucrm5pYU/3D5/PeJQL
Ra4YSyg2/hU3ZBrue6CdzYJgGXNGEWhAOQJBALMlOB4A96X+FruidzRA2fBj8j10
lakSSHl1H0RfwpbnRkcvTm0+AEZrqbL4lGGFRplrVNw2BBN25o8RPeArp0cCQEhu
kw0PI1fqhVUzJXqh6a4KT4aDHMWAlMAxi/VuSzKhjDo2Yxbd06DcqFF9JZXUou9W
FFDYTUyW7GEuC/85mwkCQCOEjUQX0C3JCSr6fyZIjpEr+znyc9eFHyBp+533Ur4g
eFu2ewJ3ufJiUBmEj1rEQku8W7h9DS2rXl10IiSwUAA=
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgPwlGJrWqTYaoMkI8jXkEI8ew
Q7E57G2Fi91WTXMMK7X6GsT9VmnRcq++Rk/VS+4IPBlfWyVRg0NfQDyuKjed21fU
Pa9AIbpYWHgP/tojyeYC1+RaXncrt9kLp7nW4FZMJmzwU9hfxIB0nhDQqhJenjdB
ZuYZfkICfMqyqbVkAwIDAQAB
-----END PUBLIC KEY-----
-------------------------------进行签名与验证操作-----------------------------------------
对消息进行签名操作...
消息的签名信息: 24a29efbc27e7b84c3b0eed683af28915381b2a0312f5383143cd2006b804d3a16c2b4750fb1857445b46664b795b6cefd402c5cf25e0f28116b7b50f5c16e80af9f9481def0161c6dac7a5d05c56595b891d84091e444ef4012ba1a0efd5cd2ff17c6dfdc109a2a3349ae2523217706a03042ea16d84fcf7d3dae37ee36d2e8
对签名信息进行验证...
签名信息验证成功,确定是正确私钥签名!!
-------------------------------进行加密解密操作-----------------------------------------
公钥加密后的数据: 2b34d46a62317f4f5e5c8618671831c0970cef2eeddc0d3aca02e1d5b411a067844e1250a1f69cbb1cbcb0cb1964af85836faa346f9ce9fac2710d4fa18e49ee1c4c73496183952fa95a54dd2d633b115504f0a365bac6d022399059a53f51c474e5e4f0f8eefde61bb85d5d812b67114f5d419c33496acaf11d3d84828733f7
私钥解密后的数据: 卧了个槽,这么神奇的吗??!!! ԅ(¯﹃¯ԅ) !!!!!!)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。如有错误或未考虑完全的地方,望不吝赐教。

原文链接:https://water.blog.csdn.net/article/details/79817733