golang流式加解密

发布时间:2024-06-16 23:11:04

在当今的数字化时代,数据的加密和解密已经成为保护隐私和确保数据安全的重要工具。而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函数对文件进行

相关推荐