Golang中的加密和解密:使用AES和RSA算法
Golang中的加密和解密:使用AES和RSA算法
随着互联网的不断发展,安全性越来越受到人们的关注。加密和解密成为了保护数据安全的重要手段之一。在Golang中,加密和解密可以使用AES和RSA算法来实现。本文将介绍Golang中如何使用AES和RSA算法进行加密和解密。
一、AES
AES是一种高级加密标准,是一种对称加密算法。对称加密算法是指加密和解密所使用的密钥是相同的。使用AES算法进行加密和解密需要先生成一个密钥,然后使用该密钥进行加密和解密操作。
1.生成密钥
生成密钥可以使用crypto/rand包中的函数实现。下面是一个生成32位密钥的示例代码:
```go
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
log.Fatal(err)
}
```
2.加密
使用AES算法进行加密需要使用crypto/aes包中的函数实现。下面是一个使用AES算法进行加密的示例代码:
```go
func aesEncrypt(plaintext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
plaintext = PKCS5Padding(plaintext, block.BlockSize())
ciphertext := make([]byte, len(plaintext))
iv := make([]byte, aes.BlockSize)
if _, err := rand.Read(iv); err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, plaintext)
ciphertext = append(iv, ciphertext...)
return ciphertext, nil
}
```
在上面的代码中,使用AES算法进行加密的关键步骤是:
1.创建AES加密器,使用密钥key作为参数。
2.对明文进行填充,使其长度为AES块大小的倍数。
3.生成一个随机的初始化向量iv。
4.创建CBC加密模式,使用加密器和初始化向量iv作为参数。
5.对明文进行加密,返回密文。
在加密过程中,需要注意的是,需要使用填充算法对明文进行填充,以保证明文长度是AES块大小的倍数。
3.解密
使用AES算法进行解密的过程与加密过程类似。下面是一个使用AES算法进行解密的示例代码:
```go
func aesDecrypt(ciphertext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
plaintext = PKCS5UnPadding(plaintext)
return plaintext, nil
}
```
在上面的代码中,使用AES算法进行解密的关键步骤是:
1.创建AES解密器,使用密钥key作为参数。
2.从密文中获取初始化向量iv。
3.创建CBC解密模式,使用解密器和初始化向量iv作为参数。
4.对密文进行解密,返回明文。
在解密过程中,需要注意的是,需要使用填充算法对解密出来的明文进行去填充,以得到原始的明文。
二、RSA
RSA是一种非对称加密算法。与对称加密算法不同,RSA算法加密和解密使用的密钥是不同的。RSA算法包括公钥和私钥两个密钥,公钥用于加密,私钥用于解密。
1.生成密钥对
生成RSA密钥对可以使用crypto/rsa包中的函数实现。下面是一个生成RSA密钥对的示例代码:
```go
func generateRSAKey() (*rsa.PrivateKey, error) {
bits := 2048
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, err
}
return privateKey, nil
}
```
在上面的代码中,使用2048位的RSA算法生成一个私钥。
2.加密
使用RSA算法进行加密需要使用crypto/rsa包中的函数实现。下面是一个使用RSA算法进行加密的示例代码:
```go
func rsaEncrypt(plaintext []byte, publicKey *rsa.PublicKey) ([]byte, error) {
ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plaintext)
if err != nil {
return nil, err
}
return ciphertext, nil
}
```
在上面的代码中,使用RSA算法进行加密的关键步骤是:
1.调用rsa.EncryptPKCS1v15函数进行加密,使用公钥publicKey作为参数。
2.对密文进行返回。
3.解密
使用RSA算法进行解密的过程与加密过程类似。下面是一个使用RSA算法进行解密的示例代码:
```go
func rsaDecrypt(ciphertext []byte, privateKey *rsa.PrivateKey) ([]byte, error) {
plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertext)
if err != nil {
return nil, err
}
return plaintext, nil
}
```
在上面的代码中,使用RSA算法进行解密的关键步骤是:
1.调用rsa.DecryptPKCS1v15函数进行解密,使用私钥privateKey作为参数。
2.对明文进行返回。
三、示例代码
下面是一个使用AES和RSA算法进行加密和解密的示例代码:
```go
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
)
func main() {
plaintext := "Hello, world!"
fmt.Println("Plaintext:", plaintext)
// AES加密
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
log.Fatal(err)
}
ciphertext, err := aesEncrypt([]byte(plaintext), key)
if err != nil {
log.Fatal(err)
}
fmt.Println("AES key:", base64.StdEncoding.EncodeToString(key))
fmt.Println("AES ciphertext:", base64.StdEncoding.EncodeToString(ciphertext))
// RSA加密
publicKey, err := readRSAPublicKey("public.pem")
if err != nil {
log.Fatal(err)
}
encryptedKey, err := rsaEncrypt(key, publicKey)
if err != nil {
log.Fatal(err)
}
fmt.Println("RSA encrypted key:", base64.StdEncoding.EncodeToString(encryptedKey))
// RSA解密
privateKey, err := readRSAPrivateKey("private.pem")
if err != nil {
log.Fatal(err)
}
decryptedKey, err := rsaDecrypt(encryptedKey, privateKey)
if err != nil {
log.Fatal(err)
}
fmt.Println("RSA decrypted key:", base64.StdEncoding.EncodeToString(decryptedKey))
// AES解密
plaintext2, err := aesDecrypt(ciphertext, decryptedKey)
if err != nil {
log.Fatal(err)
}
fmt.Println("Plaintext2:", string(plaintext2))
}
func aesEncrypt(plaintext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
plaintext = PKCS5Padding(plaintext, block.BlockSize())
ciphertext := make([]byte, len(plaintext))
iv := make([]byte, aes.BlockSize)
if _, err := rand.Read(iv); err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, plaintext)
ciphertext = append(iv, ciphertext...)
return ciphertext, nil
}
func aesDecrypt(ciphertext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
plaintext = PKCS5UnPadding(plaintext)
return plaintext, nil
}
func PKCS5Padding(src []byte, blockSize int) []byte {
padding := blockSize - len(src)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
func PKCS5UnPadding(src []byte) []byte {
length := len(src)
unpadding := int(src[length-1])
return src[:(length - unpadding)]
}
func readRSAPrivateKey(filename string) (*rsa.PrivateKey, error) {
privateKeyBytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
privateKeyBlock, _ := pem.Decode(privateKeyBytes)
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
if err != nil {
return nil, err
}
return privateKey, nil
}
func readRSAPublicKey(filename string) (*rsa.PublicKey, error) {
publicKeyBytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
publicKeyBlock, _ := pem.Decode(publicKeyBytes)
publicKey, err := x509.ParsePKCS1PublicKey(publicKeyBlock.Bytes)
if err != nil {
return nil, err
}
return publicKey, nil
}
```
在上面的代码中,首先使用AES算法对明文进行加密,然后使用RSA算法对密钥进行加密,最后把加密后的密钥和密文一起传输到对方。对方先使用RSA算法对密钥进行解密,然后再使用AES算法对密文进行解密,从而得到原始的明文。