Files
bluebird/internal/app/integrity.go
T

72 lines
1.4 KiB
Go

package app
import (
"crypto/sha256"
"encoding/hex"
"errors"
"io"
"strings"
"filippo.io/age"
)
func (a *App) verifyObjects() error {
rows, e := a.db.Query("SELECT id,digest,size,encrypted,key_id FROM objects")
if e != nil {
return e
}
type object struct {
id, digest, key string
size int64
encrypted bool
}
objects := []object{}
for rows.Next() {
var o object
if e = rows.Scan(&o.id, &o.digest, &o.size, &o.encrypted, &o.key); e != nil {
rows.Close()
return e
}
objects = append(objects, o)
}
e = rows.Err()
rows.Close()
if e != nil {
return e
}
for _, o := range objects {
if len(o.id) != 32 {
return errors.New("非法对象ID")
}
if _, e = hex.DecodeString(o.id); e != nil {
return e
}
f, e := a.root.Open(objectPath(o.id))
if e != nil {
return e
}
var reader io.Reader = f
if o.encrypted {
if a.identity == nil {
f.Close()
return errors.New("缺少加密私钥")
}
reader, e = age.Decrypt(f, a.identity)
if e != nil {
f.Close()
return e
}
}
h := sha256.New()
n, e := io.CopyBuffer(h, reader, make([]byte, 128<<10))
f.Close()
if e != nil {
return e
}
if n != o.size || a.keyed(hex.EncodeToString(h.Sum(nil))+"/"+o.key) != strings.Split(o.digest, "/")[0] {
return errors.New("对象内容完整性检查失败: " + o.id)
}
}
return nil
}