Documentation ¶
Overview ¶
Package hashchain implements a hash chain of signatures over a chain of code changes.
A hash chain is stored in a simple newline separated text file where each hash chain entry corresponds to a single line and has the following form:
hash-of-previous current-time type type-fields ...
Where hash-of-previous is the SHA256 hash of the previous line (without the trailing newline) in hex encoding. The fields are separated by single white spaces. The current-time is encoded as an ISO 8601 string in UTC (corresponds to time.RFC3339).
All hashes in a hash chain are SHA256 hashes encoded in hex notation. Hex encodings have to be lowercase. All public keys are Ed25519 keys and they and their signatures are encoded in base64 (URL encoding without padding). Comments are arbitrary UTF-8 sequences, but cannot contain newlines.
There are six different types of hash chain entries:
cstart source signtr addkey remkey sigctl
A hash chain must start with a cstart entry and that is the only line where this type must appear.
Type cstart ¶
A cstart entry starts a new hash chain.
hash-of-previous current-time cstart pubkey nonce signature [comment]
The hash-of-previous for the cstart time is the hash of an empty source tree (see tree.EmptyHash). The signature by pubkey is over the pubkey, the nonce, and the optional comment. The comment should identify the owner of the pubkey, not the project. The nonce must be a 24 byte random number in base64 (URL encoding without padding). This makes pubkey the only valid signer for the hash chain and implicitly sets the signature threshold m to 1.
Type source ¶
A source entry marks a new source tree state for publication from the developer owning the signing pubkey. The optional comment can be used to describe the change to the reviewers.
hash-of-previous current-time source tree-hash pubkey signature [comment]
The signature by pubkey is over the source tree hash and the optional comment. See the tree package for a detailed description of source tree hashes.
Type signtr ¶
A signtr entry signs a previous hash chain entry and thereby approves all code changes and changes to the set of signature keys and m up to that point.
hash-of-previous current-time signtr hash-of-chain-entry pubkey signature
It does not necessarily sign the previous line and can therefore be done in a detached fashion by a reviewer and added later by the developer responsible for maintaining the hash chain. This avoids merge conflicts.
Type addkey ¶
An addkey entry marks a signature pubkey for addition to the list of approved signature keys.
hash-of-previous current-time addkey w pubkey signature [comment]
The weight of the key towards the minimum number of necessary signatures m is denoted by w. The pubkey can be accompanied by an optional comment, but the signature must be over both. The comment is added last so it can contain white spaces without complicating the parsing, it should identify the owner of the pubkey.
Type remkey ¶
A remkey entry marks a signature pubkey for removal from the list of approved signature keys.
hash-of-previous current-time remkey pubkey
Type sigctl ¶
A sigctl entry denotes an update of m, the minimum number of necessary signatures to approve state changes (the threshold).
hash-of-previous current-time sigctl m
Example ¶
An example of a hash chain.
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 2018-05-19T00:07:02Z cstart KDKOGoY8ErjOnbDQb4k8SZFMvWdAIb-x6FGKKCRby70 sVnVenzHyCOV6nLUkCKg6ARllkYsTV-n 0UmUcDFZ2j3WWnqzEdxX-wzofWlhF3O0Rm1tT6qMUwLu8a1R5MwbK5zDongYZKccpA37Vp6Sp3m0xSreGskzCg Alice <alice@example.com> 40c7e5ca4be98e9cae6931afa4ac09e11ecb1ce20fa18d0faaabfac7e8fad071 2018-05-19T00:09:44Z addkey 1 91HOu2fvkjHd5S0LtAWTl6dYBk5cqB-NWiJqc0c_7Gc Xsr_L-1_5_B56vocve8s3Pb3vJoc-jpa2-tzIQhEjuoytYfcAiONu3er6RnVNMcsPuZFeqWCQKBwka-F-c13Ag Bob <bob@example.com> 34cd10effd93e67ba96fefb29ea751d013459a6de11cc117cf1deacd77d6b7be 2018-05-19T00:10:25Z sigctl 2 92d2fc6687b0d36d045adaf34a1615e513ef0e2dc60384cfe19863e9753567f8 2018-05-19T00:11:44Z source d844cbe6f6c2c29e97742b272096407e4d92e6ac7f167216b321c7aa55629716 KDKOGoY8ErjOnbDQb4k8SZFMvWdAIb-x6FGKKCRby70 r5aZCYGwWCFppaMDV7XSOHoyCl3qbUKGiSuYzjsTl4C0W9n0tCa0MXDy_fOwspV9f4_o0kMcb6XZS706ml3FAQ first release d258ce20943beeed2d483096702a1449447f112dec7d907d50c285c649c17a24 2018-05-19T00:12:48Z signtr d258ce20943beeed2d483096702a1449447f112dec7d907d50c285c649c17a24 KDKOGoY8ErjOnbDQb4k8SZFMvWdAIb-x6FGKKCRby70 HKlLKnYSCVzc4b-erETK50EN5gKRKZQsT16grv7eFBklFqXBFoSXSmcY99HLWhAP9BJcA6c3Px1trNBns3KkDA 2e34e23ee293e8c0ed174639d325eb3e30f5337d5c5846380367724e93cb619e 2018-05-19T00:34:51Z signtr 2e34e23ee293e8c0ed174639d325eb3e30f5337d5c5846380367724e93cb619e 91HOu2fvkjHd5S0LtAWTl6dYBk5cqB-NWiJqc0c_7Gc xffZultos-MCbI4cNzAzAoccuDSnpL2nq_BsQanIruYM3RXoD9kdC6WiPEUkxrphKdG742IgBWlB3LwY0i1ZCw
Index ¶
- Variables
- type HashChain
- func (c *HashChain) AddKey(weight int, pubKey [32]byte, signature [64]byte, comment []byte) (string, error)
- func (c *HashChain) Apply(head *[32]byte, patchDir string) error
- func (c *HashChain) CheckHead(head [32]byte) error
- func (c *HashChain) Close() error
- func (c *HashChain) DeepVerify(treeDir, patchDir string, excludePaths []string) error
- func (c *HashChain) DetachedSignature(linkHash, pubKey, signature string) (string, error)
- func (c *HashChain) Fprint(w io.Writer) error
- func (c *HashChain) Head() [32]byte
- func (c *HashChain) LastSignedTreeHash() (string, int)
- func (c *HashChain) LastTreeHash() string
- func (c *HashChain) LinkHash(treeHash string) [32]byte
- func (c *HashChain) M() int
- func (c *HashChain) Merge(src *HashChain) error
- func (c *HashChain) N() int
- func (c *HashChain) Print()
- func (c *HashChain) RemoveKey(pubKey [32]byte) (string, error)
- func (c *HashChain) Signature(linkHash [32]byte, secKey [64]byte, detached bool) (string, error)
- func (c *HashChain) SignatureControl(m int) (string, error)
- func (c *HashChain) Signer() map[string]bool
- func (c *HashChain) SignerBarrier(pubKey string) int
- func (c *HashChain) SignerComment(pubKey string) string
- func (c *HashChain) SignerInfo(treeHash string) (string, string)
- func (c *HashChain) SignerWeight(pubKey string) int
- func (c *HashChain) Source(treeHash [32]byte, secKey [64]byte, comment []byte) (string, error)
- func (c *HashChain) SourceLine(treeHash string) int
- func (c *HashChain) TreeComments() []string
- func (c *HashChain) TreeHashes() []string
- func (c *HashChain) UnsignedInfo(pubkey, treeHash string, omitSource bool) ([]string, error)
Constants ¶
This section is empty.
Variables ¶
var ErrCannotMerge = errors.New("hashchain: cannot merge")
ErrCannotMerge is returned if two hash chains cannot be merged.
var ErrDescendingTime = errors.New("hashchain: time is going backwards")
ErrDescendingTime is returned when the time in the hash chain is not ascending.
var ErrEmpty = errors.New("hashchain: is empty")
ErrEmpty is returned when the hash chain is empty.
var ErrHeadNotFound = errors.New("hashchain: head not found")
ErrHeadNotFound is returned if the head could not be found in hash chain.
var ErrIllegalCStart = errors.New("hashchain: cstart is only allowed on start")
ErrIllegalCStart is returned when a cstart entry appears in a different row than row 1.
var ErrLinkBroken = errors.New("hashchain: link broken")
ErrLinkBroken is returned when a link in the hash chain is broken.
var ErrMLargerThanN = errors.New("hashchain: signature threshold m is larger than total weight of signers n")
ErrMLargerThanN is returned when m > n.
var ErrMustStartWithCStart = errors.New("hashchain: must start with cstart")
ErrMustStartWithCStart is returned when the hash chain doess not start with a cstart entry.
var ErrNothingToMerge = errors.New("hashchain: nothing to merge")
ErrNothingToMerge is returned if there is nothing to merge.
var ErrSignatureThresholdNonPositive = errors.New("hashchain: signature threshold m must be positive")
ErrSignatureThresholdNonPositive is returned when the signature threshold is non-positive.
var ErrUnknownLinkType = errors.New("hashchain: unknown link type")
ErrUnknownLinkType is returned when the link type is unknown.
var ErrWrongSigAddKey = errors.New("hashchain: addkey signature doesn't validate")
ErrWrongSigAddKey is returned when the signature of an addkey entry doesn't validate.
var ErrWrongSigCStart = errors.New("hashchain: cstart signature doesn't validate")
ErrWrongSigCStart is returned when the signature of a cstart entry doesn't validate.
var ErrWrongSigSignature = errors.New("hashchain: signature signature doesn't validate")
ErrWrongSigSignature is returned when the signature of a signature entry doesn't validate.
var ErrWrongSigSource = errors.New("hashchain: source signature doesn't validate")
ErrWrongSigSource is returned when the signature of a source entry doesn't validate.
var ErrWrongTypeFields = errors.New("hashchain: entry has wrong number of type fields")
ErrWrongTypeFields is returned when a hash chain entry has the wrong number of type fields.
Functions ¶
This section is empty.
Types ¶
type HashChain ¶
type HashChain struct {
// contains filtered or unexported fields
}
HashChain of threshold signatures over a chain of code changes.
func (*HashChain) AddKey ¶
func (c *HashChain) AddKey(weight int, pubKey [32]byte, signature [64]byte, comment []byte) (string, error)
AddKey adds pubkey with signature and optional comment to hash chain.
func (*HashChain) CheckHead ¶
CheckHead checks wether the hash chain contains the given head as entry.
func (*HashChain) DeepVerify ¶
DeepVerify hash chain. Use directory treeDir to apply patches from patchDir one after another and verify that they reflect the treehashes recorded in the hash chain.
func (*HashChain) DetachedSignature ¶
DetachedSignature adds a detached signature entry for linkHash signed by pubKey to the hash chain.
func (*HashChain) LastSignedTreeHash ¶
LastSignedTreeHash returns the last signed tree hash and its index. The first signed tree hash is tree.EmptyHash with index 0.
func (*HashChain) LastTreeHash ¶
LastTreeHash returns the most current tree hash (can be unsigned).
func (*HashChain) Signature ¶
Signature adds a signature entry for linkHash signed by secKey to the hash chain. If detached it just returns the signature without adding it.
func (*HashChain) SignatureControl ¶
SignatureControl adds a signature control entry to the hash chain.
func (*HashChain) SignerBarrier ¶
SignerBarrier returns the signer barrier for pubKey.
func (*HashChain) SignerComment ¶
SignerComment returns the signer comment for given pubKey.
func (*HashChain) SignerInfo ¶
SignerInfo returns signer pubKey and comment for patch with given treeHash.
func (*HashChain) SignerWeight ¶
SignerWeight returns the signer weight for given pubKey.
func (*HashChain) Source ¶
Source adds a source entry for treeHash and optional comment signed by secKey to the hash chain.
func (*HashChain) SourceLine ¶
SourceLine returns the line number where the given tree hash was signed.
func (*HashChain) TreeComments ¶
TreeComments returns a list of all tree comments in order (starting from tree.EmptyHash).
func (*HashChain) TreeHashes ¶
TreeHashes returns a list of all tree hashes in order (starting from tree.EmptyHash).
func (*HashChain) UnsignedInfo ¶
UnsignedInfo returns a string slice with information about all unsigned entries suitable for printing. If TreeHash is defined it returns info until that treeHash. If omitSource is true source lines are omitted