Golang便捷的结构体加密库(GDPR)
Golang便捷的结构体加密库(GDPR) GDPR 第32条规定:
- 考虑到现有技术水平、实施成本以及处理的性质、范围、背景和目的,以及对自然人权利和自由造成不同程度可能性和严重性的风险,控制者和处理者应实施适当的技术和组织措施,以确保与风险相适应的安全水平,其中包括酌情采取以下措施:
(a) 个人数据的假名化和加密;
…
因此,我希望以加密形式存储个人数据。ORM/DAO 应该接收已经加密的结构体,并且不应透明地处理它。所以,只有必要的用例(处理原因)才会显式地对数据进行解密。而其他任何操作都会将这些数据视为“垃圾”。
我之前没有大规模数据加密的经验,也没有持久化加密的经验,例如对表行进行加密。我只在传输流中使用过加密,那种情况下数据不会持久保存。然而,我了解到,对所有数据使用相同的密钥是一种不好的做法,因为可以从多个加密数据实例(在原始数据已知的情况下)轻松提取密钥。
对于这种加密,一个好的起点是什么?另外,是否有任何库(至少部分地)关注这个 GDPR 问题,或者关注结构体加密(例如使用反射)?
更多关于Golang便捷的结构体加密库(GDPR)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang便捷的结构体加密库(GDPR)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
对于GDPR合规的结构体加密,Go语言中有几个值得考虑的库和实现模式。以下是一个基于结构体标签的加密方案示例:
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"reflect"
)
// 加密器接口
type Encryptor interface {
Encrypt(data []byte) ([]byte, error)
Decrypt(data []byte) ([]byte, error)
}
// AES-GCM加密实现
type AESGCMEncryptor struct {
key []byte
}
func NewAESGCMEncryptor(key []byte) (*AESGCMEncryptor, error) {
if len(key) != 32 {
return nil, errors.New("key must be 32 bytes for AES-256")
}
return &AESGCMEncryptor{key: key}, nil
}
func (e *AESGCMEncryptor) Encrypt(plaintext []byte) ([]byte, error) {
block, err := aes.NewCipher(e.key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
return ciphertext, nil
}
func (e *AESGCMEncryptor) Decrypt(ciphertext []byte) ([]byte, error) {
block, err := aes.NewCipher(e.key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, errors.New("ciphertext too short")
}
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
return gcm.Open(nil, nonce, ciphertext, nil)
}
// 结构体加密处理器
type StructEncryptor struct {
encryptor Encryptor
}
func NewStructEncryptor(encryptor Encryptor) *StructEncryptor {
return &StructEncryptor{encryptor: encryptor}
}
// 加密结构体
func (s *StructEncryptor) EncryptStruct(obj interface{}) error {
v := reflect.ValueOf(obj)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return errors.New("must pass a pointer to struct")
}
v = v.Elem()
t := v.Type()
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
fieldType := t.Field(i)
// 检查是否有encrypt标签
if tag, ok := fieldType.Tag.Lookup("encrypt"); ok && tag == "true" {
if field.Kind() == reflect.String && field.CanSet() {
plaintext := field.String()
if plaintext != "" {
ciphertext, err := s.encryptor.Encrypt([]byte(plaintext))
if err != nil {
return err
}
// 存储为base64或直接存储字节,这里使用base64
field.SetString(fmt.Sprintf("%x", ciphertext))
}
}
}
}
return nil
}
// 解密结构体
func (s *StructEncryptor) DecryptStruct(obj interface{}) error {
v := reflect.ValueOf(obj)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return errors.New("must pass a pointer to struct")
}
v = v.Elem()
t := v.Type()
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
fieldType := t.Field(i)
if tag, ok := fieldType.Tag.Lookup("encrypt"); ok && tag == "true" {
if field.Kind() == reflect.String && field.CanSet() {
ciphertextHex := field.String()
if ciphertextHex != "" {
var ciphertext []byte
fmt.Sscanf(ciphertextHex, "%x", &ciphertext)
plaintext, err := s.encryptor.Decrypt(ciphertext)
if err != nil {
return err
}
field.SetString(string(plaintext))
}
}
}
}
return nil
}
// 使用示例
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email" encrypt:"true"`
Phone string `json:"phone" encrypt:"true"`
CreatedAt string `json:"created_at"`
}
func main() {
// 生成或加载密钥(实际应用中应从安全的地方获取)
key := make([]byte, 32)
rand.Read(key)
encryptor, _ := NewAESGCMEncryptor(key)
structEncryptor := NewStructEncryptor(encryptor)
// 创建用户数据
user := &User{
ID: 1,
Username: "john_doe",
Email: "john@example.com",
Phone: "+1234567890",
CreatedAt: "2024-01-01",
}
fmt.Println("原始数据:")
fmt.Printf("%+v\n", user)
// 加密敏感字段
structEncryptor.EncryptStruct(user)
fmt.Println("\n加密后数据:")
fmt.Printf("%+v\n", user)
// 解密敏感字段
structEncryptor.DecryptStruct(user)
fmt.Println("\n解密后数据:")
fmt.Printf("%+v\n", user)
// JSON序列化示例
jsonData, _ := json.Marshal(user)
fmt.Println("\nJSON序列化:")
fmt.Println(string(jsonData))
}
对于GDPR合规的库,可以考虑以下选项:
- age:一个简单、现代的加密工具,支持文件加密
import "filippo.io/age"
- nacl/secretbox:NaCl加密库,提供简单的加密接口
import "golang.org/x/crypto/nacl/secretbox"
- gormcrypto:GORM的加密插件
import "github.com/pkasila/gorm-crypto"
- 自定义解决方案:结合KMS(密钥管理服务)和信封加密
// 使用AWS KMS示例
import "github.com/aws/aws-sdk-go/service/kms"
对于密钥管理,建议采用分层密钥策略:
- 使用KMS管理根密钥
- 为每个用户或数据记录派生不同的数据密钥
- 实现密钥轮换机制
存储加密数据时,建议将加密元数据(算法、版本、密钥ID)与密文一起存储,以便未来兼容性。

