Eli's Blog

1. 存储格式

密钥、密文、签名字符串的存储格式

1
2
3
4
5
6
7
8
9
10
// hex:转为十六进制字符串表示
hex.EncodeToString(src []byte) string
hex.DecodeString(s string) ([]byte, error)

// base64
base64.StdEncoding.EncodeToString(src []byte) string
base64.StdEncoding.DecodeString(s string) ([]byte, error)

// pem: 密钥解析
pem.Decode(data []byte) (p *Block, rest []byte)

2. 生成密钥

1
2
3
4
5
# 私钥
openssl genrsa -out rsa_private_key.pem 2048

# 公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

3. 私钥格式

1
2
3
4
5
// PKCS1
x509.ParsePKCS1PrivateKey(der []byte) (key interface{}, err error)

// PKCS2
x509.ParsePKCS8PrivateKey(der []byte) (key interface{}, err error)

4. SHA算法

1
2
3
4
5
6
// sha1 or sha256
h := sha1.New()
h := sha256.New()

h.Write([]byte(data))
hash := h.Sum(nil)

5. RSA类型

  • 公钥加密、私钥解密
  • 私钥签名、公钥验签
1
2
3
4
5
6
7
8
9
10
11
// 加密
rsa.EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)

// 解密
rsa.DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)

// 签名
rsa.SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)

// 验签
rsa.VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error

5.1 加密和解密

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
func RsaEncrypt(plainText, publicKey string) (string, error) {
block, _ := pem.Decode([]byte(publicKey))
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return "", err
}

cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey.(*rsa.PublicKey), []byte(plainText))
if err != nil {
return "", err
}

return base64.StdEncoding.EncodeToString(cipherText), nil
}

func RsaDecrypt(cipherText, privateKey string) (string, error) {
block, _ := pem.Decode([]byte(privateKey))
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return "", err
}

cipherTextData, err := base64.StdEncoding.DecodeString(cipherText)
if err != nil {
return "", err
}

plainTextData, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, cipherTextData)
if err != nil {
return "", err
}

return string(plainTextData), nil
}

5.2 签名和验签

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
func RsaSign(originalData, privateKey string) (string, error) {
block, _ := pem.Decode([]byte(privateKey))
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return "", err
}

h := sha256.New()
h.Write([]byte(originalData))
hash := h.Sum(nil)

signature, err := rsa.SignPKCS1v15(rand.Reader, priKey, crypto.SHA256, hash[:])
if err != nil {
return "", err
}

return hex.EncodeToString(signature), nil
}

func RsaVerify(originalData, SignatureData, publicKey string) error {
block, _ := pem.Decode([]byte(publicKey))
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}

signature, err := hex.DecodeString(SignatureData)

h := sha256.New()
h.Write([]byte(originalData))
hash := h.Sum(nil)

return rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), crypto.SHA256, hash[:], signature)
}

6. AES

1
2
3
4
5
6
7
8
9
aes.NewCipher(key []byte) (cipher.Block, error)

cipher.NewCBCEncrypter(b Block, iv []byte) BlockMode
cipherTextData := make([]byte, len(originalData))
blockMode.CryptBlocks(cipherTextData, originalData)

cipher.NewCBCDecrypter(b Block, iv []byte) BlockMode
originalData := make([]byte, len(cipherTextData))
blockMode.CryptBlocks(originalData, cipherTextData)

实例:

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
func AesEncrypt(plainText, key, iv string) (string, error) {
// 密钥: 长度必须为16, 24, 32
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}

// 加密模式: IV长度和KEY保持一致
blockMode := cipher.NewCBCEncrypter(block, []byte(iv))

// 填充内容
blockSize := block.BlockSize()
left := blockSize - len(plainText)%blockSize
padding := bytes.Repeat([]byte{byte(left)}, left)
originalData := append([]byte(plainText), padding...)

// 加密
cipherTextData := make([]byte, len(originalData))
blockMode.CryptBlocks(cipherTextData, originalData)

return base64.StdEncoding.EncodeToString(cipherTextData), nil
}

func AesDecrypt(cipherText, key, iv string) (string, error) {
// 密钥: 长度必须为16, 24, 32
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}

// 加密模式: IV长度和KEY保持一致
blockMode := cipher.NewCBCDecrypter(block, []byte(iv))

// 密文
cipherTextData, err := base64.StdEncoding.DecodeString(cipherText)

// 解密
originalData := make([]byte, len(cipherTextData))
blockMode.CryptBlocks(originalData, cipherTextData)

// 去除填充
length := len(originalData)
left := int(originalData[length-1])
plainTextData := originalData[:(length - left)]

return string(plainTextData), nil
}