Files
opentimestamps/detached_timestamp.go
2023-09-18 16:29:42 -03:00

101 lines
2.2 KiB
Go

package opentimestamps
import (
"bytes"
"fmt"
"io"
"os"
)
var fileHeaderMagic = []byte(
"\x00OpenTimestamps\x00\x00Proof\x00\xbf\x89\xe2\xe8\x84\xe8\x92\x94",
)
const (
minFileDigestLength = 20
maxFileDigestLength = 32
fileMajorVersion = 1
)
type DetachedTimestamp struct {
HashOp cryptOp
FileHash []byte
Timestamp *Timestamp
}
func (d *DetachedTimestamp) Dump() string {
w := &bytes.Buffer{}
fmt.Fprintf(
w, "File %s hash: %x\n", d.HashOp.name, d.Timestamp.Message,
)
fmt.Fprint(w, d.Timestamp.Dump())
return w.String()
}
func (d *DetachedTimestamp) encode(ctx *serializationContext) error {
if err := ctx.writeBytes(fileHeaderMagic); err != nil {
return err
}
if err := ctx.writeVarUint(fileMajorVersion); err != nil {
return err
}
if err := d.HashOp.encode(ctx); err != nil {
return err
}
if err := ctx.writeBytes(d.FileHash); err != nil {
return err
}
return d.Timestamp.encode(ctx)
}
func (d *DetachedTimestamp) WriteToStream(w io.Writer) error {
return d.encode(&serializationContext{w})
}
func NewDetachedTimestamp(
hashOp cryptOp, fileHash []byte, ts *Timestamp,
) (*DetachedTimestamp, error) {
if len(fileHash) != hashOp.digestLength {
return nil, fmt.Errorf(
"op %v expects %d byte digest, got %d",
hashOp, hashOp.digestLength, len(fileHash),
)
}
return &DetachedTimestamp{hashOp, fileHash, ts}, nil
}
func NewDetachedTimestampFromReader(r io.Reader) (*DetachedTimestamp, error) {
ctx := newDeserializationContext(r)
if err := ctx.assertMagic([]byte(fileHeaderMagic)); err != nil {
return nil, err
}
major, err := ctx.readVarUint()
if err != nil {
return nil, err
}
if major != uint64(fileMajorVersion) {
return nil, fmt.Errorf("unexpected major version %d", major)
}
fileHashOp, err := parseCryptOp(ctx)
if err != nil {
return nil, err
}
fileHash, err := ctx.readBytes(fileHashOp.digestLength)
if err != nil {
return nil, err
}
ts, err := newTimestampFromContext(ctx, fileHash)
if err != nil {
return nil, err
}
return &DetachedTimestamp{*fileHashOp, fileHash, ts}, nil
}
func NewDetachedTimestampFromPath(p string) (*DetachedTimestamp, error) {
f, err := os.Open(p)
if err != nil {
return nil, err
}
return NewDetachedTimestampFromReader(f)
}