codechain: Index | Files | Directories

package hashchain

import ""

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:


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


An example of a hash chain.

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 2018-05-19T00:07:02Z cstart KDKOGoY8ErjOnbDQb4k8SZFMvWdAIb-x6FGKKCRby70 sVnVenzHyCOV6nLUkCKg6ARllkYsTV-n 0UmUcDFZ2j3WWnqzEdxX-wzofWlhF3O0Rm1tT6qMUwLu8a1R5MwbK5zDongYZKccpA37Vp6Sp3m0xSreGskzCg Alice <>
40c7e5ca4be98e9cae6931afa4ac09e11ecb1ce20fa18d0faaabfac7e8fad071 2018-05-19T00:09:44Z addkey 1 91HOu2fvkjHd5S0LtAWTl6dYBk5cqB-NWiJqc0c_7Gc Xsr_L-1_5_B56vocve8s3Pb3vJoc-jpa2-tzIQhEjuoytYfcAiONu3er6RnVNMcsPuZFeqWCQKBwka-F-c13Ag Bob <>
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


Package Files

addkey.go apply.go deepverify.go doc.go errors.go hashchain.go link.go merge.go read.go remkey.go sigctl.go signature.go source.go start.go verify.go


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.

type HashChain Uses

type HashChain struct {
    // contains filtered or unexported fields

HashChain of threshold signatures over a chain of code changes.

func Read Uses

func Read(r io.Reader) (*HashChain, error)

Read hash chain from r and verify it.

func ReadFile Uses

func ReadFile(filename string) (*HashChain, error)

ReadFile reads hash chain from filename and verifies it.

func Start Uses

func Start(filename string, secKey [64]byte, comment []byte) (*HashChain, string, error)

Start returns a new hash chain with signature control list m.

func (*HashChain) AddKey Uses

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) Apply Uses

func (c *HashChain) Apply(head *[32]byte) error

Apply to current working directory and check head if not nil.

func (*HashChain) CheckHead Uses

func (c *HashChain) CheckHead(head [32]byte) error

CheckHead checks wether the hash chain contains the given head as entry.

func (*HashChain) Close Uses

func (c *HashChain) Close() error

Close the underlying file pointer of hash chain and release lock.

func (*HashChain) DeepVerify Uses

func (c *HashChain) DeepVerify(treeDir, patchDir string, excludePaths []string) error

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 Uses

func (c *HashChain) DetachedSignature(linkHash, pubKey, signature string) (string, error)

DetachedSignature adds a detached signature entry for linkHash signed by pubKey to the hash chain.

func (*HashChain) Fprint Uses

func (c *HashChain) Fprint(w io.Writer) error

Fprint hash chain to w.

func (*HashChain) Head Uses

func (c *HashChain) Head() [32]byte

Head returns the hash of the last entry.

func (*HashChain) LastSignedTreeHash Uses

func (c *HashChain) LastSignedTreeHash() (string, int)

LastSignedTreeHash returns the last signed tree hash and its index. The first signed tree hash is tree.EmptyHash with index 0.

func (*HashChain) LastTreeHash Uses

func (c *HashChain) LastTreeHash() string

LastTreeHash returns the most current tree hash (can be unsigned).

func (*HashChain) LinkHash Uses

func (c *HashChain) LinkHash(treeHash string) [32]byte

LinkHash returns the link hash corresponding to given treeHash.

func (*HashChain) M Uses

func (c *HashChain) M() int

M returns the signature threshold.

func (*HashChain) Merge Uses

func (c *HashChain) Merge(src *HashChain) error

Merge hashchain src into c.

func (*HashChain) N Uses

func (c *HashChain) N() int

N returns the total weight of all signers.

func (*HashChain) Print Uses

func (c *HashChain) Print()

Print colorized hash chain on stdout.

func (*HashChain) RemoveKey Uses

func (c *HashChain) RemoveKey(pubKey [32]byte) (string, error)

RemoveKey adds a pubkey remove entry to hash chain.

func (*HashChain) Signature Uses

func (c *HashChain) Signature(linkHash [32]byte, secKey [64]byte, detached bool) (string, error)

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 Uses

func (c *HashChain) SignatureControl(m int) (string, error)

SignatureControl adds a signature control entry to the hash chain.

func (*HashChain) Signer Uses

func (c *HashChain) Signer() map[string]bool

Signer returns a map containing all active signers for hash chain.

func (*HashChain) SignerBarrier Uses

func (c *HashChain) SignerBarrier(pubKey string) int

SignerBarrier returns the signer barrier for pubKey.

func (*HashChain) SignerComment Uses

func (c *HashChain) SignerComment(pubKey string) string

SignerComment returns the signer comment for given pubKey.

func (*HashChain) SignerInfo Uses

func (c *HashChain) SignerInfo(treeHash string) (string, string)

SignerInfo returns signer pubKey and comment for patch with given treeHash.

func (*HashChain) SignerWeight Uses

func (c *HashChain) SignerWeight(pubKey string) int

SignerWeight returns the signer weight for given pubKey.

func (*HashChain) Source Uses

func (c *HashChain) Source(treeHash [32]byte, secKey [64]byte, comment []byte) (string, error)

Source adds a source entry for treeHash and optional comment signed by secKey to the hash chain.

func (*HashChain) SourceLine Uses

func (c *HashChain) SourceLine(treeHash string) int

SourceLine returns the line number where the given tree hash was signed.

func (*HashChain) TreeComments Uses

func (c *HashChain) TreeComments() []string

TreeComments returns a list of all tree comments in order (starting from tree.EmptyHash).

func (*HashChain) TreeHashes Uses

func (c *HashChain) TreeHashes() []string

TreeHashes returns a list of all tree hashes in order (starting from tree.EmptyHash).

func (*HashChain) UnsignedInfo Uses

func (c *HashChain) UnsignedInfo(pubkey, treeHash string, omitSource bool) ([]string, error)

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


internal/statePackage state implements the state of a hashchain.
linktypePackage linktype defines the different link types of a hash chain.

Package hashchain imports 24 packages (graph) and is imported by 7 packages. Updated 2019-01-22. Refresh now. Tools for package owners.