使用Golang将MSSQL数据导出到加密文件
使用Golang将MSSQL数据导出到加密文件 大家好,
我需要将大量数据从 MSSQL 查询导出到加密的平面文件中。
要求是“静态数据”必须被加密,并且不能先将其以未加密的形式保存到磁盘上。如果可以先将其未加密保存到磁盘,我完全可以在 CSV 文件生成后运行 PGP 对其进行加密。
这意味着我需要从数据库获取数据后,在内存中对其进行加密,很可能通过使用流的方式来实现。
为了避免在处理大量数据行时耗尽内存,更好的做法是分块地将数据(以加密格式)写入磁盘。也就是说,读取一小部分,写入一小部分(加密后)。
这可行吗?能否提供一些伪代码帮助?
2 回复
基本上,你可以从数据库中读取每一行(或一组行),并使用AES或PK(即RSA等公钥)单独加密。
相关资源:

使用Crypto包在Golang应用程序中加密和解密数据
学习如何在Golang应用程序中使用可用的加密包通过AES加密和解密数据。
https://gist.github.com/miguelmota/3ea9286bd1d3c2a985b67cac4ba2130a
rsa_util.go
package ciphers
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha512"
"crypto/x509"
"encoding/pem"
"log"
)
此文件已被截断。显示原文
更多关于使用Golang将MSSQL数据导出到加密文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
可以使用Go的database/sql和crypto/cipher包流式处理数据并加密写入文件。以下是一个示例实现:
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"database/sql"
"encoding/csv"
"io"
"os"
_ "github.com/denisenkom/go-mssqldb"
)
func main() {
// 1. 数据库连接
connStr := "server=localhost;user id=sa;password=your_password;database=your_db"
db, err := sql.Open("sqlserver", connStr)
if err != nil {
panic(err)
}
defer db.Close()
// 2. 创建加密文件
key := make([]byte, 32) // AES-256密钥
if _, err := rand.Read(key); err != nil {
panic(err)
}
outputFile, err := os.Create("encrypted_data.bin")
if err != nil {
panic(err)
}
defer outputFile.Close()
// 3. 初始化加密流
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
iv := make([]byte, aes.BlockSize)
if _, err := rand.Read(iv); err != nil {
panic(err)
}
// 写入IV到文件头部
if _, err := outputFile.Write(iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
writer := &cipher.StreamWriter{S: stream, W: outputFile}
// 4. 创建CSV写入器包装加密流
csvWriter := csv.NewWriter(writer)
defer csvWriter.Flush()
// 5. 流式查询和写入
rows, err := db.Query("SELECT col1, col2, col3 FROM large_table")
if err != nil {
panic(err)
}
defer rows.Close()
cols, err := rows.Columns()
if err != nil {
panic(err)
}
// 缓冲区大小(每次处理1000行)
bufferSize := 1000
buffer := make([][]string, 0, bufferSize)
for rows.Next() {
row := make([]string, len(cols))
rowPtrs := make([]interface{}, len(cols))
for i := range row {
rowPtrs[i] = &row[i]
}
if err := rows.Scan(rowPtrs...); err != nil {
panic(err)
}
buffer = append(buffer, row)
// 缓冲区满时写入加密文件
if len(buffer) >= bufferSize {
if err := csvWriter.WriteAll(buffer); err != nil {
panic(err)
}
buffer = buffer[:0] // 清空缓冲区
}
}
// 写入剩余数据
if len(buffer) > 0 {
if err := csvWriter.WriteAll(buffer); err != nil {
panic(err)
}
}
if err := rows.Err(); err != nil {
panic(err)
}
}
如果需要使用PGP加密,可以使用golang.org/x/crypto/openpgp包:
package main
import (
"database/sql"
"io"
"os"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
_ "github.com/denisenkom/go-mssqldb"
)
func pgpEncryptStream() {
// ... 数据库连接代码同上 ...
// 创建加密文件
encryptedFile, err := os.Create("encrypted_data.pgp")
if err != nil {
panic(err)
}
defer encryptedFile.Close()
// 读取PGP公钥
pubKeyFile, err := os.Open("public.key")
if err != nil {
panic(err)
}
defer pubKeyFile.Close()
entityList, err := openpgp.ReadArmoredKeyRing(pubKeyFile)
if err != nil {
panic(err)
}
// 创建加密流
armorWriter, err := armor.Encode(encryptedFile, "PGP MESSAGE", nil)
if err != nil {
panic(err)
}
defer armorWriter.Close()
plainWriter, err := openpgp.Encrypt(armorWriter, entityList, nil, nil, nil)
if err != nil {
panic(err)
}
defer plainWriter.Close()
// 流式处理数据
rows, err := db.Query("SELECT col1, col2, col3 FROM large_table")
if err != nil {
panic(err)
}
defer rows.Close()
// 直接写入加密流(这里简化为文本格式)
for rows.Next() {
var col1, col2, col3 string
if err := rows.Scan(&col1, &col2, &col3); err != nil {
panic(err)
}
line := col1 + "," + col2 + "," + col3 + "\n"
if _, err := plainWriter.Write([]byte(line)); err != nil {
panic(err)
}
}
}
这个方案通过流式处理避免了内存溢出,数据在内存中始终以加密形式存在,不会在磁盘上留下未加密的临时文件。

