golang实现RSA和AES加解密
密码学里目前有两大经典算法,一个是对称加解密,其代表是AES加解密;另一个是非对加解密,其代表是RSA加解密。这里就以这两个经典算法为例,简单列下其在golang里实现的代码。
一、AES加解密
AES加密又分为ECB、CBC、CFB、OFB等几种,这里只列两种吧。
1、CBC加解密
1/*
2code from www.361way.com
3mail:[email protected]
4desc:aes加密之一
5*/
6package main
7import(
8 "bytes"
9 "crypto/aes"
10 "fmt"
11 "crypto/cipher"
12 "encoding/base64"
13)
14func main() {
15 orig := "hello world"
16 //key := "123456781234567812345678"
17 key := "9871267812345mn812345xyz"
18 fmt.Println("原文:", orig)
19 encryptCode := AesEncrypt(orig, key)
20 fmt.Println("密文:" , encryptCode)
21 decryptCode := AesDecrypt(encryptCode, key)
22 fmt.Println("解密结果:", decryptCode)
23}
24func AesEncrypt(orig string, key string) string {
25 // 转成字节数组
26 origData := []byte(orig)
27 k := []byte(key)
28 // 分组秘钥
29 block, _ := aes.NewCipher(k)
30 // 获取秘钥块的长度
31 blockSize := block.BlockSize()
32 // 补全码
33 origData = PKCS7Padding(origData, blockSize)
34 // 加密模式
35 blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
36 // 创建数组
37 cryted := make([]byte, len(origData))
38 // 加密
39 blockMode.CryptBlocks(cryted, origData)
40 return base64.StdEncoding.EncodeToString(cryted)
41}
42func AesDecrypt(cryted string, key string) string {
43 // 转成字节数组
44 crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
45 k := []byte(key)
46 // 分组秘钥
47 block, _ := aes.NewCipher(k)
48 // 获取秘钥块的长度
49 blockSize := block.BlockSize()
50 // 加密模式
51 blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
52 // 创建数组
53 orig := make([]byte, len(crytedByte))
54 // 解密
55 blockMode.CryptBlocks(orig, crytedByte)
56 // 去补全码
57 orig = PKCS7UnPadding(orig)
58 return string(orig)
59}
60//补码
61func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
62 padding := blocksize - len(ciphertext)%blocksize
63 padtext := bytes.Repeat([]byte{byte(padding)}, padding)
64 return append(ciphertext, padtext...)
65}
66//去码
67func PKCS7UnPadding(origData []byte) []byte {
68 length := len(origData)
69 unpadding := int(origData[length-1])
70 return origData[:(length - unpadding)]
71}
其运行结果如下:
1[root@361way crypto]# go run aes.go
2原文: hello world
3密文: v3/NfSN7XwqXu2gC08+3QA==
4解密结果: hello world
2、CFB加解密
代码如下:
1/*
2code from www.361way.com
3mail:[email protected]
4desc:aes加密之一
5*/
6package main
7import (
8 "crypto/aes"
9 "crypto/cipher"
10 "fmt"
11 "os"
12)
13var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
14func main() {
15 //需要去加密的字符串
16 plaintext := []byte("My name is Astaxie")
17 //如果传入加密串的话,plaint就是传入的字符串
18 if len(os.Args) > 1 {
19 plaintext = []byte(os.Args[1])
20 }
21 //aes的加密字符串
22 key_text := "astaxie12798akljzmknm.ahkjkljl;k"
23 if len(os.Args) > 2 {
24 key_text = os.Args[2]
25 }
26 fmt.Println(len(key_text))
27 // 创建加密算法aes
28 c, err := aes.NewCipher([]byte(key_text))
29 if err != nil {
30 fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key_text), err)
31 os.Exit(-1)
32 }
33 //加密字符串
34 cfb := cipher.NewCFBEncrypter(c, commonIV)
35 ciphertext := make([]byte, len(plaintext))
36 cfb.XORKeyStream(ciphertext, plaintext)
37 fmt.Printf("%s=>%x\n", plaintext, ciphertext)
38 // 解密字符串
39 cfbdec := cipher.NewCFBDecrypter(c, commonIV)
40 plaintextCopy := make([]byte, len(plaintext))
41 cfbdec.XORKeyStream(plaintextCopy, ciphertext)
42 fmt.Printf("%x=>%s\n", ciphertext, plaintextCopy)
43}
其运行结果如下:
1[root@361way crypto]# go run aes2.go
232
3My name is Astaxie=>5072eadc20720cdb321b7c62947982d8227d
45072eadc20720cdb321b7c62947982d8227d=>My name is Astaxie
上面的代码如果细看和分解成加解密函数,发现是有问题的,这里再列个官方的示例 (需翻墙):
1/*
2code by www.361way.com,from golang.org
3[email protected]
4AES CFB加解密
5*/
6package main
7import (
8 "crypto/aes"
9 "crypto/cipher"
10 "crypto/rand"
11 "encoding/hex"
12 "fmt"
13 "io"
14)
15func ExampleNewCFBDecrypter() {
16 key, _ := hex.DecodeString("6368616e676520746869732070617373")
17 ciphertext, _ := hex.DecodeString("e38932f30048f4cf2ecff113b29c4aed3dc0fb65c8d16ae0171aee54d207")
18 block, err := aes.NewCipher(key)
19 if err != nil {
20 panic(err)
21 }
22 if len(ciphertext) < aes.BlockSize {
23 panic("ciphertext too short")
24 }
25 iv := ciphertext[:aes.BlockSize]
26 ciphertext = ciphertext[aes.BlockSize:]
27 stream := cipher.NewCFBDecrypter(block, iv)
28 stream.XORKeyStream(ciphertext, ciphertext)
29 fmt.Printf("%s\n", ciphertext)
30}
31func ExampleNewCFBEncrypter() {
32 key, _ := hex.DecodeString("6368616e676520746869732070617373")
33 plaintext := []byte("www.361way.com")
34 block, err := aes.NewCipher(key)
35 if err != nil {
36 panic(err)
37 }
38 ciphertext := make([]byte, aes.BlockSize+len(plaintext))
39 iv := ciphertext[:aes.BlockSize]
40 if _, err := io.ReadFull(rand.Reader, iv); err != nil {
41 panic(err)
42 }
43 stream := cipher.NewCFBEncrypter(block, iv)
44 stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
45 fmt.Printf("%x\n", ciphertext)
46}
47func main() {
48 ExampleNewCFBDecrypter()
49 ExampleNewCFBEncrypter()
50}
二、golang下RSA加解密
AES一般用于加解密文,而RSA算法一算用来加解密密码。这里列举一个代码示例,如下:
1/*
2code from www.361way.com
3mail:[email protected]
4desc:rsa加解密
5*/
6package main
7import (
8 "crypto/rand"
9 "crypto/rsa"
10 "crypto/x509"
11 "encoding/base64"
12 "encoding/pem"
13 "errors"
14 "fmt"
15)
16// 可通过openssl产生
17//openssl genrsa -out rsa_private_key.pem 1024
18var privateKey = []byte(`
19-----BEGIN RSA PRIVATE KEY-----
20MIICXQIBAAKBgQDfw1/P15GQzGGYvNwVmXIGGxea8Pb2wJcF7ZW7tmFdLSjOItn9
21kvUsbQgS5yxx+f2sAv1ocxbPTsFdRc6yUTJdeQolDOkEzNP0B8XKm+Lxy4giwwR5
22LJQTANkqe4w/d9u129bRhTu/SUzSUIr65zZ/s6TUGQD6QzKY1Y8xS+FoQQIDAQAB
23AoGAbSNg7wHomORm0dWDzvEpwTqjl8nh2tZyksyf1I+PC6BEH8613k04UfPYFUg1
240F2rUaOfr7s6q+BwxaqPtz+NPUotMjeVrEmmYM4rrYkrnd0lRiAxmkQUBlLrCBiF
25u+bluDkHXF7+TUfJm4AZAvbtR2wO5DUAOZ244FfJueYyZHECQQD+V5/WrgKkBlYy
26XhioQBXff7TLCrmMlUziJcQ295kIn8n1GaKzunJkhreoMbiRe0hpIIgPYb9E57tT
27/mP/MoYtAkEA4Ti6XiOXgxzV5gcB+fhJyb8PJCVkgP2wg0OQp2DKPp+5xsmRuUXv
28720oExv92jv6X65x631VGjDmfJNb99wq5QJBAMSHUKrBqqizfMdOjh7z5fLc6wY5
29M0a91rqoFAWlLErNrXAGbwIRf3LN5fvA76z6ZelViczY6sKDjOxKFVqL38ECQG0S
30pxdOT2M9BM45GJjxyPJ+qBuOTGU391Mq1pRpCKlZe4QtPHioyTGAAMd4Z/FX2MKb
313in48c0UX5t3VjPsmY0CQQCc1jmEoB83JmTHYByvDpc8kzsD8+GmiPVrausrjj4p
32y2DQpGmUic2zqCxl6qXMpBGtFEhrUbKhOiVOJbRNGvWW
33-----END RSA PRIVATE KEY-----
34`)
35//openssl
36//openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
37var publicKey = []byte(`
38-----BEGIN PUBLIC KEY-----
39MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfw1/P15GQzGGYvNwVmXIGGxea
408Pb2wJcF7ZW7tmFdLSjOItn9kvUsbQgS5yxx+f2sAv1ocxbPTsFdRc6yUTJdeQol
41DOkEzNP0B8XKm+Lxy4giwwR5LJQTANkqe4w/d9u129bRhTu/SUzSUIr65zZ/s6TU
42GQD6QzKY1Y8xS+FoQQIDAQAB
43-----END PUBLIC KEY-----
44`)
45// 加密
46func RsaEncrypt(origData []byte) ([]byte, error) {
47 //解密pem格式的公钥
48 block, _ := pem.Decode(publicKey)
49 if block == nil {
50 return nil, errors.New("public key error")
51 }
52 // 解析公钥
53 pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
54 if err != nil {
55 return nil, err
56 }
57 // 类型断言
58 pub := pubInterface.(*rsa.PublicKey)
59 //加密
60 return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
61}
62// 解密
63func RsaDecrypt(ciphertext []byte) ([]byte, error) {
64 //解密
65 block, _ := pem.Decode(privateKey)
66 if block == nil {
67 return nil, errors.New("private key error!")
68 }
69 //解析PKCS1格式的私钥
70 priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
71 if err != nil {
72 return nil, err
73 }
74 // 解密
75 return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
76}
77func main() {
78 data, _ := RsaEncrypt([]byte("hello world"))
79 fmt.Println(base64.StdEncoding.EncodeToString(data))
80 origData, _ := RsaDecrypt(data)
81 fmt.Println(string(origData))
82}
运行结果如下:
1[root@361way crypto]# go run rsa.go
2ocYqyhRtngT/G9TteTHxAmg9E3KNuw0zskKXcQbxeWEwFoHzGGIrfkDokq+SMvYeQjVCWTADBL3zzlelBBaZIVaJ11PndffC+2AlDVhLrvRqy5MeEYFafH40ZH1qUptt/UiY4imgaQc1dhcQol0+4dTfGmgN8CMAi3od7AU+/RM=
3hello world
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/golang-rsa-aes/5828.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.