一种安全加密文件的方式,文件可以实现自校验,防止文件损坏和篡改
这个项目是很久以前的,当时go
能力有限,写的不尽人意。刚好最近有加密文件的需求,所以就完善了相关逻辑。
之前的方案还依赖 Seek(offset int64, whence int) (int64, error)
,看了go很多源码,都说Seek
不可靠。所以目前改为纯Reader
和Writer
这两种接口,当然文件的结构也必须改变。
因为自带hash校验,因此内容连一个字节都不能被篡改,安全性很高。而且随机的aes
密码也是通过rsa
进行加密,因此只要妥善保管好rsa
的私钥就能保证万无一失。
加密后内容结构如下所示:
rsa密文长度 | rsa加密aes密码后的密文 | aes加密内容 | 数据hash值 |
---|---|---|---|
len(rsa(password)) | rsa(password) | aesEnc(data) | hash(data) |
下面是示例代码:
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"flag"
"io"
"log"
"os"
"github.com/jan-bar/EncryptionFile"
)
func main() {
org := flag.String("f", "", "enc file path")
flag.Parse()
src := *org // dst为生成的加密文件,cmp是通过解密dst生成的文件
dst, cmp := src+".dst", src+".cmp"
var pri, pub bytes.Buffer // 生成一对公私钥数据
err := EncryptionFile.GenRsaKey(2048, &pub, &pri)
if err != nil {
log.Fatal(err)
}
//goland:noinspection GoUnhandledErrorResult
enc := func() error {
fr, err := os.Open(src)
if err != nil {
return err
}
defer fr.Close()
fw, err := os.Create(dst)
if err != nil {
return err
}
defer fw.Close()
return EncryptionFile.EncData(fr, fw, pub.Bytes(), md5.New())
}
if err = enc(); err != nil {
log.Fatal(err)
}
//goland:noinspection GoUnhandledErrorResult
dec := func() error {
fr, err := os.Open(dst)
if err != nil {
return err
}
defer fr.Close()
fw, err := os.Create(cmp)
if err != nil {
return err
}
defer fw.Close()
return EncryptionFile.DecData(fr, fw, pri.Bytes(), md5.New())
}
if err = dec(); err != nil {
log.Fatal(err)
}
md5Src, err := md5file(src)
if err != nil {
log.Fatal(err)
}
md5Org, err := md5file(cmp)
if err != nil {
log.Fatal(err)
}
if md5Src != md5Org {
log.Fatalf("src(%s) != org(%s)", md5Src, md5Org)
}
}
func md5file(s string) (string, error) {
fr, err := os.Open(s)
if err != nil {
return "", err
}
//goland:noinspection GoUnhandledErrorResult
defer fr.Close()
h := md5.New()
_, err = io.Copy(h, fr)
if err != nil {
return "", err
}
return hex.EncodeToString(h.Sum(nil)), nil
}