在当今的数字化时代,数据的加密和解密已经成为保护隐私和确保数据安全的重要工具。而golang作为一种高效且易于使用的编程语言,也提供了强大的加解密功能,使开发人员能够轻松实现各种加密算法。本文将介绍如何使用golang进行流式加解密。
1. AES加解密
AES(Advanced Encryption Standard)是一种最常用的对称加密算法之一,它使用相同的密钥来加密和解密数据。在golang中,我们可以使用crypto/aes包来实现AES加解密。以下是一个简单的示例代码:
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
)
func encrypt(plainText []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
cipherText := make([]byte, aes.BlockSize+len(plainText))
iv := cipherText[:aes.BlockSize]
if _, err := rand.Read(iv); err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(cipherText[aes.BlockSize:], plainText)
return cipherText, nil
}
func decrypt(cipherText []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(cipherText) < aes.BlockSize {
return nil, errors.New("cipher text too short")
}
iv := cipherText[:aes.BlockSize]
cipherText = cipherText[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(cipherText, cipherText)
return cipherText, nil
}
func main() {
plainText := []byte("Hello, World!")
key := []byte("abcdefghijklmnop")
cipherText, err := encrypt(plainText, key)
if err != nil {
fmt.Println("Encryption error:", err)
return
}
fmt.Printf("Cipher Text: %x\n", cipherText)
decryptedPlainText, err := decrypt(cipherText, key)
if err != nil {
fmt.Println("Decryption error:", err)
return
}
fmt.Println("Decrypted Plain Text:", string(decryptedPlainText))
}
在上述代码中,我们通过crypto/aes包中的NewCipher函数创建一个AES解密块。然后,我们使用NewCBCEncrypter和NewCBCDecrypter函数分别创建加密器和解密器。经过加密后,我们打印出了密文,并通过解密函数将其解密为明文。
2. RSA加解密
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,它使用一对公私钥来加密和解密数据。在golang中,我们可以使用crypto/rsa包来实现RSA加解密。以下是一个简单的示例代码:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
)
func encrypt(plainText []byte, publicKey []byte) ([]byte, error) {
block, _ := pem.Decode(publicKey)
if block == nil {
return nil, errors.New("failed to decode public key")
}
publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey.(*rsa.PublicKey), plainText)
if err != nil {
return nil, err
}
return cipherText, nil
}
func decrypt(cipherText []byte, privateKey []byte) ([]byte, error) {
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, errors.New("failed to decode private key")
}
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)
if err != nil {
return nil, err
}
return plainText, nil
}
func main() {
plainText := []byte("Hello, World!")
publicKey := []byte(`
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
`)
privateKey := []byte(`
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
`)
cipherText, err := encrypt(plainText, publicKey)
if err != nil {
fmt.Println("Encryption error:", err)
return
}
fmt.Printf("Cipher Text: %x\n", cipherText)
decryptedPlainText, err := decrypt(cipherText, privateKey)
if err != nil {
fmt.Println("Decryption error:", err)
return
}
fmt.Println("Decrypted Plain Text:", string(decryptedPlainText))
}
在上述代码中,我们通过crypto/rsa包中的EncryptPKCS1v15和DecryptPKCS1v15函数分别使用公钥和私钥进行加解密。我们首先使用编码的PEM格式的密钥,并使用Pem.Decode函数对其进行解码。然后,我们使用x509.ParsePKIXPublicKey和x509.ParsePKCS1PrivateKey函数将解码后的密钥转换为RSA公钥和私钥。最后,我们使用EncryptPKCS1v15和DecryptPKCS1v15函数进行加解密。
3. 使用流式加解密进行文件加解密
以上示例中我们展示了如何对数据进行流式加解密,但是在实际应用中,我们也需要对文件进行加解密。golang中提供了io.Writer和io.Reader接口,可以将加解密算法应用于文件操作中。以下示例代码展示了如何使用流式加解密进行文件加解密:
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"io"
"log"
"os"
)
func encryptFile(inputFilePath string, outputFilePath string, key []byte) error {
inputFile, err := os.Open(inputFilePath)
if err != nil {
return err
}
defer inputFile.Close()
outputFile, err := os.OpenFile(outputFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer outputFile.Close()
block, err := aes.NewCipher(key)
if err != nil {
return err
}
iv := make([]byte, aes.BlockSize)
if _, err := rand.Read(iv); err != nil {
return err
}
outputFile.Write(iv)
mode := cipher.NewCBCEncrypter(block, iv)
writer := &cipher.StreamWriter{S: mode, W: outputFile}
if _, err := io.Copy(writer, inputFile); err != nil {
return err
}
return nil
}
func decryptFile(inputFilePath string, outputFilePath string, key []byte) error {
inputFile, err := os.Open(inputFilePath)
if err != nil {
return err
}
defer inputFile.Close()
outputFile, err := os.OpenFile(outputFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer outputFile.Close()
block, err := aes.NewCipher(key)
if err != nil {
return err
}
iv := make([]byte, aes.BlockSize)
if _, err := inputFile.Read(iv); err != nil {
return err
}
mode := cipher.NewCBCDecrypter(block, iv)
reader := &cipher.StreamReader{S: mode, R: inputFile}
if _, err := io.Copy(outputFile, reader); err != nil {
return err
}
return nil
}
func main() {
inputFilePath := "input.txt"
encryptedFilePath := "encrypted.bin"
decryptedFilePath := "decrypted.txt"
plainText := []byte("Hello, World!")
key := []byte("abcdefghijklmnop")
if err := os.WriteFile(inputFilePath, plainText, 0644); err != nil {
log.Fatal(err)
}
if err := encryptFile(inputFilePath, encryptedFilePath, key); err != nil {
log.Fatal(err)
}
if err := decryptFile(encryptedFilePath, decryptedFilePath, key); err != nil {
log.Fatal(err)
}
}
以上代码中,我们通过使用os.Open、os.OpenFile和os.WriteFile函数对文件进行