check / check (push) Waiting to run
The Signature Scheme section now states what signatureString builds: the magic, the outer uuid as lower-case hex with no hyphens, and the outer sha256 as the lower-case hex of its multihash, which starts 1220, with an example string taken from a run of the code. It says signer is the upper-case hex fingerprint of the signing primary key and that a signature is stored only in the manifest. The mf.proto comments on fields 201 to 203 say the same, and mf.pb.go is regenerated. A new test pins the example string. Nothing about what is signed or how changes. Model: opus-5-5
92 lines
2.4 KiB
Protocol Buffer
92 lines
2.4 KiB
Protocol Buffer
syntax = "proto3";
|
|
|
|
option go_package = "sneak.berlin/go/mfer/mfer";
|
|
|
|
message Timestamp {
|
|
int64 seconds = 1;
|
|
int32 nanos = 2;
|
|
}
|
|
|
|
message MFFileOuter {
|
|
enum Version {
|
|
VERSION_NONE = 0;
|
|
VERSION_ONE = 1; // only one for now
|
|
}
|
|
|
|
// required mffile root attributes 1xx
|
|
Version version = 101;
|
|
|
|
enum CompressionType {
|
|
COMPRESSION_NONE = 0;
|
|
COMPRESSION_ZSTD = 1;
|
|
}
|
|
|
|
CompressionType compressionType = 102;
|
|
|
|
// these are used solely to detect corruption/truncation
|
|
// and not for cryptographic integrity.
|
|
int64 size = 103;
|
|
bytes sha256 = 104;
|
|
|
|
// uuid must match the uuid in the inner message
|
|
bytes uuid = 105;
|
|
|
|
bytes innerMessage = 199;
|
|
|
|
// 2xx for optional manifest root attributes
|
|
|
|
// one OpenPGP signature, armored or binary, over the canonical string
|
|
// ZNAVSRFG-<uuid>-<sha256 as a multihash>, with the uuid as 32
|
|
// lower-case hex digits and no hyphens, and the multihash in lower-case
|
|
// hex (see docs/FORMAT.md). A signature is never stored anywhere else.
|
|
optional bytes signature = 201;
|
|
// fingerprint of the signing primary key, in upper-case hex
|
|
optional bytes signer = 202;
|
|
// OpenPGP public key of the signer, one primary key, armored or binary
|
|
optional bytes signingPubKey = 203;
|
|
}
|
|
|
|
message MFFilePath {
|
|
// required attributes:
|
|
// Path invariants: must be valid UTF-8, use forward slashes only,
|
|
// be relative (no leading /), contain no ".." segments, and no
|
|
// empty segments (no "//").
|
|
string path = 1;
|
|
int64 size = 2;
|
|
|
|
// gotta have at least one:
|
|
repeated MFFileChecksum hashes = 3;
|
|
|
|
// optional per-file metadata
|
|
optional string mimeType = 301;
|
|
optional Timestamp mtime = 302;
|
|
optional Timestamp ctime = 303;
|
|
// permission bits, at most 0777; 0 when not recorded
|
|
uint32 mode = 304;
|
|
}
|
|
|
|
message MFFileChecksum {
|
|
// 1.0 golang implementation must write a multihash here
|
|
// it's ok to only ever use/verify sha256 multihash
|
|
bytes multiHash = 1;
|
|
}
|
|
|
|
message MFFile {
|
|
enum Version {
|
|
VERSION_NONE = 0;
|
|
VERSION_ONE = 1; // only one for now
|
|
}
|
|
Version version = 100;
|
|
|
|
// required manifest attributes:
|
|
repeated MFFilePath files = 101;
|
|
|
|
// uuid is a random v4 UUID generated when creating the manifest
|
|
// used as part of the signature to prevent replay attacks
|
|
bytes uuid = 102;
|
|
|
|
// optional manifest attributes 2xx:
|
|
optional Timestamp createdAt = 201;
|
|
}
|
|
|