codechain: github.com/frankbraun/codechain/ssot Index | Files | Directories

package ssot

import "github.com/frankbraun/codechain/ssot"

Package ssot implements a single source of truth (SSOT) with DNS TXT records.

Signed head specification

Signed heads have the following fields:

- PUBKEY (32-byte), the Ed25519 public key of SSOT head signer.
- PUBKEY_ROTATE (32-byte), Ed25519 pubkey to rotate to, set to 0 if unused.
- VALID_FROM (8-byte), the signed head is valid from the given Unix time.
- VALID_TO (8-byte), the signed head is valid to the given Unix time.
- COUNTER (8-byte), strictly increasing signature counter.
- HEAD, the Codechain head to sign.
- SIGNATURE, signature with PUBKEY.

The SIGNATURE is over all previous fields:

PUBKEY|PUBKEY_ROTATE|VALID_FROM|VALID_TO|COUNTER|HEAD

The signed head is a concatenation of

PUBKEY|PUBKEY_ROTATE|VALID_FROM|VALID_TO|COUNTER|HEAD|SIGNATURE

encoded in base64 (URL encoding without padding).

All integers (VALID_FROM, VALID_TO, COUNTER) are encoded in network order (big-endian).

CreatePkg specification

To create a new secure package for a project developed with Codechain that should be distributed with a SSOT using DNS TXT records, the following procedure is defined:

1. Make sure the project with NAME has not been published before.
   That is, the directory ~/.config/ssotpub/pkgs/NAME does not exist.

2. Create a new .secpkg file which specifies the following:

   - The NAME of the project.
   - The fully qualified domain name (DNS) where the TXT records can be
     queried.
   - The current HEAD of the project's Codechain.

   The .secpkg file is saved to the current working directory, which is
   typically added to the root of the project's repository.

3. Create the first signed head (see SignHead) for the current project's
   HEAD with a supplied secret key and counter set to 0.

4. Create the directory ~/.config/ssotpub/pkgs/NAME/dists
   and save the current distribution to
    ~/.config/ssotpub/pkgs/NAME/dists/HEAD.tar.gz (`codechain createdist`).

5. Save the signed head to ~/.config/ssotpub/pkgs/NAME/signed_head

6. Print the distribution name: ~/.config/secpkg/pkgs/NAME/dists/HEAD.tar.gz

7. Print DNS TXT records as defined by the .secpkg, the first signed head,
   and the download URL.

Afterwards the administrator manually uploads the distribution HEAD.tar.gz
to the download URL and publishes the new DNS TXT record in the defined
zone. DNSSEC should be enabled.

SignHead specification

To publish an update of a secure package with SSOT do the following:

1. Parse the .secpkg file in the current working directory.

2. Make sure the project with NAME has been published before.
   That is, the directory ~/.config/ssotpub/pkgs/NAME exists.

3. Validate the signed head in ~/.config/ssotpub/pkgs/NAME/signed_head
   and make sure the corresponding secret key is available.

4. Get the HEAD from .codechain/hashchain in the current working directory.

5. Create a new signed head with current HEAD, the counter of the previous
   signed head plus 1, and update the saved signed head:

   - `cp -f ~/.config/ssotpub/pkgs/NAME/signed_head
            ~/.config/ssotpub/pkgs/NAME/previous_signed_head`
   - Save new signed head to ~/.config/ssotpub/pkgs/NAME/signed_head (atomic).

6. Save the current distribution to:
   ~/.config/secpkg/pkgs/NAME/dists/HEAD.tar.gz (`codechain createdist`).

7. Lookup the download URL and print where to upload the distribution file:
   ~/.config/ssotpkg/pkgs/NAME/dists/HEAD.tar.gz

8. Print DNS TXT record as defined by the .secpkg and the signed head.

9. If the HEAD changed, update the .secpkg file accordingly.

Afterwards the administrator manually uploads the distribution HEAD.tar.gz
to the download URL and publishes the new DNS TXT record in the defined
zone. DNSSEC should be enabled.

TODO

The following should be specified:

- Key rotation.
- Automatic publishing of TXT records. With https://github.com/xenolf/lego?

Index

Package Files

doc.go errors.go rotatefile.go signhead.go ssot.go valid.go

Constants

const File = "signed_head"

File defines the default file name for a signed head.

const MaximumValidity = 30 * 24 * 60 * 60 // 30d

MaximumValidity of signed heads.

const TTL = 600 // 10m

TTL of signed head TXT records

Variables

var ErrSignedHeadExpired = errors.New("ssot: signed head is expired")

ErrSignedHeadExpired is returned if the validity of a signed head is expired.

var ErrSignedHeadFuture = errors.New("ssot: signed head is valid in the future")

ErrSignedHeadFuture is returned if the validity of a signed head is in the future.

var ErrSignedHeadSignature = errors.New("ssot: signed head signature does not verify")

ErrSignedHeadSignature is returned if a signed head signature does not verify.

func LookupURL Uses

func LookupURL(dns string) (string, error)

LookupURL looks up URL from dns and returns it.

func TXTPrintURL Uses

func TXTPrintURL(dns, url string)

TXTPrintURL prints the TXT record to publish the url.

type SignedHead Uses

type SignedHead struct {
    // contains filtered or unexported fields
}

SignedHead is a signed Codechain head ready for publication as a SSOT with DNS TXT records.

func Load Uses

func Load(filename string) (*SignedHead, error)

Load and verify a base64 encoded signed head from filename.

func LookupHead Uses

func LookupHead(dns string) (*SignedHead, error)

LookupHead and verify base64 encoded signed head from dns.

func SignHead Uses

func SignHead(head [32]byte, counter uint64, secKey [64]byte) *SignedHead

SignHead signs the given Codechain head.

func Unmarshal Uses

func Unmarshal(signedHead string) (*SignedHead, error)

Unmarshal and verify a base64 encoded signed head.

func (*SignedHead) Counter Uses

func (sh *SignedHead) Counter() uint64

Counter returns the counter of signed head.

func (*SignedHead) Head Uses

func (sh *SignedHead) Head() string

Head returns the signed head.

func (*SignedHead) HeadBuf Uses

func (sh *SignedHead) HeadBuf() [32]byte

HeadBuf returns the signed head.

func (*SignedHead) Marshal Uses

func (sh *SignedHead) Marshal() string

Marshal signed head with signature and encode it as base64.

func (*SignedHead) PubKey Uses

func (sh *SignedHead) PubKey() string

PubKey returns the public key in base64 notation.

func (*SignedHead) PubKeyRotate Uses

func (sh *SignedHead) PubKeyRotate() string

PubKeyRotate returns the public key rotate in base64 notation.

func (*SignedHead) RotateFile Uses

func (sh *SignedHead) RotateFile(pkgDir string) error

RotateFile rotates the pkgDir/signed_head to pkgDir/previous_signed_head and saves signed head sh to pkgDir/signed_head.

func (*SignedHead) TXTPrintHead Uses

func (sh *SignedHead) TXTPrintHead(dns string)

TXTPrintHead prints the TXT record to publish the signed head.

func (*SignedHead) Valid Uses

func (sh *SignedHead) Valid() error

Valid checks if the signed head sh is currently valid (as defined by validFrom and validTo). It returns nil, if the signed check is valid and an error otherwise.

Directories

PathSynopsis
commandPackage command implements the ssotpub commands.

Package ssot imports 14 packages (graph) and is imported by 2 packages. Updated 2018-10-28. Refresh now. Tools for package owners.