概述

  1. 数字签名

  2. 加解密

  3. 对称

  4. 非对称

  5. 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
package main

import (
"errors"
"fmt"
"reflect"
"strconv"
"strings"
)

func main() {
//publicKey, privateKey := generateKey(999773, 999959)
publicKey, privateKey := generateKey(7001, 7079)
txt := "password"
fmt.Println("publicKey",publicKey)
fmt.Println("privateKey", privateKey)
encode := rsaEnCode(publicKey, txt)
fmt.Println(encode)
decode := rsaDeCode(privateKey, encode)
fmt.Println(decode)
}

//gcd 最大公约数greatest common divisor,辗转相除法
func gcd(x, y uint64) uint64 {
tmp := x % y
if tmp > 0 {
return gcd(y, tmp)
}
return y

}

//lcm 最小公倍数least common multiple,公式法
func lcm(x, y uint64) uint64 {
return x * y / gcd(x, y)
}

//generateKey 生成密钥
func generateKey(a, b uint64) ([2]uint64, [2]uint64) {
publicKey := [2]uint64{}
privateKey := [2]uint64{}
n := a * b
publicKey[0] = n
privateKey[0] = n

l := lcm(a-1, b-1)
e, err := getE(l)
if err != nil {
fmt.Println(err)
}
d, err := getD(e, l)
if err != nil {
fmt.Println(err)
}
publicKey[1] = e
privateKey[1] = d
fmt.Println(e)
fmt.Println(d)
return publicKey, privateKey
}

// 获取公钥参数e
func getE(l uint64) (uint64, error) {
e := l - 1
for {
if e <= 1 {
return 0, errors.New("no e founded")
}
if gcd(e, l) == 1 {
return e, nil
}
e--
}
}

//获取私钥参数d
func getD(e, l uint64) (uint64, error) {
d := l - 1
for {
if d <= 1 {
return 0, errors.New("no d founded")
}
if e*d%l == 1 {
return e, nil
}
d--
}
}

// 无符号64位整形求幂
func pow(a, b uint64) uint64 {
if b == 0 {
return 1
}
out := a
for {
if b == 1 {
return out
}
out *= a
b--
}
}

//rsa加密
func rsaEnCode(publicKey [2]uint64, string2 string) string {
pp := make([]string,0,len(string2))
for _,v :=range string2 {
uint64String := uint64(v)
encodeUint := pow(uint64String, publicKey[1]) % publicKey[0]
encodeString := strconv.FormatUint(encodeUint, 10)
pp = append(pp, encodeString)
}
fmt.Println("rsaEncode",fmt.Sprintf(strings.Join(pp,",")))
return fmt.Sprintf(strings.Join(pp,","))
}

//rsa解密
func rsaDeCode(publicKey [2]uint64, string2 string) string {
txtSlice := strings.Split(string2,",")
fmt.Println("txt",txtSlice,reflect.TypeOf(txtSlice))
pp := make([]string,0,len(txtSlice))
for _,v :=range txtSlice {
uint64String,_ := strconv.ParseUint(v,10,64)
encodeUint := pow(uint64String, publicKey[1]) % publicKey[0]
encodeString := string(encodeUint)
fmt.Println(encodeUint,encodeString)
pp = append(pp, encodeString)
}
fmt.Println("rsaDecode",pp,fmt.Sprintf(strings.Join(pp,"")))
return fmt.Sprintf(strings.Join(pp,""))
}

PKCS1与PKCS8

PKCS1:全名《Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications》最新版本2.2 (rfc8017, 有兴趣的同学可以读一下) ,从名称上可以看出它是针对RSA算法的一个规范。里面包含了RSA加密、解密、签名验签等所有的内容,当然也包含了私钥的格式。PKCS1的1.1版本是1991年发布的。

1
2
3
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

PKCS8:全名《Public-Key Cryptography Standards (PKCS) #8: Private-Key Information Syntax Specification》最新版本1.2,从名称上可以看出它是一个专门用来存储私钥的文件格式规范。PKCS1的1.2版本是2008年发布的。

1
2
3
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

将私钥PEM格式的文件转换为DER格式

1
2
3
4
bash# openssl rsa -in pkcs1.pem -out pkcs1.der -outform DER
bash# openssl pkcs8 -topk8 -inform PEM -in pkcs1.pem -outform DER -nocrypt -out pkcs8.der
bash# ls
pkcs1.der pkcs1.pem pkcs8.der pkcs8.pem

对比两个der格式内容

使用hexdump查看内容

1
cat pkcs1.der | hexdump

PEM 和DER区别

PEM与DER有什么区别呢?其实PEM就是对DER的内容做了base64的编码并做了一下格式化的输出而已。