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 }