用Golang中的秘密密钥进行数据加密和解密的例子

508 阅读1分钟

你可以使用下面的例子在Golang中进行数据加密和解密。它使用一个静态的密匙,如果加密和解密是在同一台机器上进行,那就很理想。你可以在URL中使用加密后的数据。

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
)

func main() {
	// You can generate this only once and use as an environment variable.
	secret, err := secret()
	if err != nil {
		panic(fmt.Sprintf("unable to create secret key: %v", err))
	}

	message := "I am a very secret message"
	fmt.Println("Message:", message)

	encrypted, err := encrypt(message, secret)
	if err != nil {
		panic(fmt.Sprintf("unable to encrypt the data: %v", err))
	}
	fmt.Println("Encrypted:", encrypted)

	decrypted, err := decrypt(encrypted, secret)
	if err != nil {
		panic(fmt.Sprintf("unable to decrypt the data: %v", err))
	}
	fmt.Println("Decrypted:", decrypted)
}

// secret returns a 32 bytes AES key.
func secret() ([]byte, error) {
	key := make([]byte, 16)

	if _, err := rand.Read(key); err != nil {
		return nil, err
	}

	return key, nil
}

// encrypt encrypts plain string with a secret key and returns encrypt string.
func encrypt(plainData string, secret []byte) (string, error) {
	cipherBlock, err := aes.NewCipher(secret)
	if err != nil {
		return "", err
	}

	aead, err := cipher.NewGCM(cipherBlock)
	if err != nil {
		return "", err
	}

	nonce := make([]byte, aead.NonceSize())
	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
		return "", err
	}

	return base64.URLEncoding.EncodeToString(aead.Seal(nonce, nonce, []byte(plainData), nil)), nil
}

// decrypt decrypts encrypt string with a secret key and returns plain string.
func decrypt(encodedData string, secret []byte) (string, error) {
	encryptData, err := base64.URLEncoding.DecodeString(encodedData)
	if err != nil {
		return "", err
	}

	cipherBlock, err := aes.NewCipher(secret)
	if err != nil {
		return "", err
	}

	aead, err := cipher.NewGCM(cipherBlock)
	if err != nil {
		return "", err
	}

	nonceSize := aead.NonceSize()
	if len(encryptData) < nonceSize {
		return "", err
	}

	nonce, cipherText := encryptData[:nonceSize], encryptData[nonceSize:]
	plainData, err := aead.Open(nil, nonce, cipherText, nil)
	if err != nil {
		return "", err
	}

	return string(plainData), nil
}
$ go run -race main.go 
Message: I am a very secret message
Encrypted: tW-khZy3YYpYytPjfffrwHXaaNqMZxugqeBx5vkgc75Nd8HUky8duwit8CiGOUecN5ZxxRox
Decrypted: I am a very secret message

$ go run -race main.go 
Message: I am a very secret message
Encrypted: Xbvm0z0wC1eHJqaWZn03vDYUdO4NgtWvXEN_aqjQaKw6J_oKXlOVXOyRp8N8s0qtEHUm93Ny
Decrypted: I am a very secret message

$ go run -race main.go 
Message: I am a very secret message
Encrypted: 13hKVuxfVVcRMD3-aW5eiXRGgWChIws56px7pc41yTYkdoJ-obIaBu3-p9SLIIvMY_4aeP9y
Decrypted: I am a very secret message

$ go run -race main.go 
Message: I am a very secret message
Encrypted: 8XCqFxJkZKGKC1rYmxU_1-HvYVWwJvN3WmkRSZBHFSKSEaJBmvDuP0HHAwjjE_hvWxgT2jLY
Decrypted: I am a very secret message

$ go run -race main.go 
Message: I am a very secret message
Encrypted: 3o8p-xTEcDtSvz6PRdIbK9TRqBmrPohxh6XM33hlMnsZCvkZDbp5Eo4_mqAELZof91sFyvdY
Decrypted: I am a very secret message