72 lines
1.4 KiB
Go
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
|
|
}
|