golang-标准库(crypto/ecdsa)

ecdsa包提供了非对称加密算法ECDSA,ECDSA为椭圆曲线加密算法,是基于椭圆方程公式,安全性要高于RSA。这里说下使用ecdsa的密匙生成和签名校验,不涉及原理;go中ecdsa目前只有用私钥加密,公钥做校验,没有解密环节;目前可以应用于数字签名;
  • 基于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
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
137
138
139
package main

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
)

//随机熵,用于加密安全
var randSign = "22220316zafes20180lk7zafes20180619zafepikas"

//随机key,用于创建公钥和私钥
var randKey = "lk0f7279c18d439459435s714797c9680335a320"

var PriKey *ecdsa.PrivateKey
var PubKey *ecdsa.PublicKey

func init() {
// 初始化生成私匙公匙
priFile, _ := os.Create("ec-pri.pem")
pubFile, _ := os.Create("ec-pub.pem")
if err := generateKey(priFile, pubFile); err != nil {
log.Println(err)
os.Exit(1)
}
// 加载私匙公匙
if err := loadKey(); err != nil {
log.Println(err)
os.Exit(1)
}
}
func main() {

// 预加密数据
text := "hello dalgurak"
// hash签名
hashText := sha256.Sum256([]byte(text))
// 加密私匙
r, s, err := ecdsa.Sign(strings.NewReader(randSign), PriKey, hashText)
if err != nil {
log.Println(err)
os.Exit(1)
}

// 公匙验证hash的正确性
b := ecdsa.Verify(PubKey, hashText, r, s)
fmt.Println(b)
}

// 生成密匙对
func generateKey(priFile, pubFile *os.File) error {
lenth := len(randKey)
if lenth < 224/8 {
return errors.New("私钥长度太短,至少为36位!")
}
// 根据随机密匙的长度创建私匙
var curve elliptic.Curve
if lenth > 521/8+8 {
curve = elliptic.P521()
} else if lenth > 384/8+8 {
curve = elliptic.P384()
} else if lenth > 256/8+8 {
curve = elliptic.P256()
} else if lenth > 224/8+8 {
curve = elliptic.P224()
}
// 生成私匙
priKey, err := ecdsa.GenerateKey(curve, strings.NewReader(randKey))
if err != nil {
return err
}
// *****************保存私匙*******************
// 序列化私匙
priBytes, err := x509.MarshalECPrivateKey(priKey)
if err != nil {
return err
}
priBlock := pem.Block{
Type: "ECD PRIVATE KEY",
Bytes: priBytes,
}
// 编码私匙,写入文件
if err := pem.Encode(priFile, &priBlock); err != nil {
return err
}
// *****************保存公匙*******************
// 序列化公匙
pubBytes, err := x509.MarshalPKIXPublicKey(&priKey.PublicKey)
if err != nil {
return err
}
pubBlock := pem.Block{
Type: "ECD PUBLIC KEY",
Bytes: pubBytes,
}
// 编码公匙,写入文件
if err := pem.Encode(pubFile, &pubBlock); err != nil {
return err
}
return nil
}

// 加载私匙公匙
func loadKey() error {
// 读取密匙
pri, _ := ioutil.ReadFile("ec-pri.pem")
pub, _ := ioutil.ReadFile("ec-pub.pem")
// 解码私匙
block, _ := pem.Decode(pri)
var err error
// 反序列化私匙
PriKey, err = x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return err
}
// 解码公匙
block, _ = pem.Decode(pub)
// 反序列化公匙
var i interface{}
i, err = x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
// PubKey = (*ecdsa.PublicKey)(i)
var ok bool
PubKey, ok = i.(*ecdsa.PublicKey)
if !ok {
return errors.New("the public conversion error")
}
return nil
}
作者

itpika

发布于

2020-04-14 17:14:31

更新于

2021-06-15 09:30:32

许可协议

评论