signing

package
v0.0.0-...-ff5f600 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2016 License: BSD-3-Clause Imports: 13 Imported by: 0

Documentation

Overview

Package signing signs syncbase updates using public key signatures, and allows these signatures to be checked on other nodes.

The functionality is geared specifically towards syncbase synchronization because it is designed to allow a signature to remain valid during its propagation across the syncgroup once it has been accepted by at least one member of a syncgroup, even if the original key or its blessings are invalidated in the meantime.

There are three types of participant:

  • an "author", which creates an update, and signs it with Sign().
  • one or more "validators", each of which receives a change directly from the author, and applies Check() to validate it.
  • zero or more "checkers', each of whom receives a change from a validator or another checker, and applied Check() to check it.

A validator checks the signature and blessings provided by the author, and then appends its own signature, vouching for the fact that the author's signature was good at the time the validator saw it.

A checker checks the signatures of both the author and validator but uses weaker checks for signature validity than a validator. In particular, it uses a significant grace period for key expiry so that a change admitted to the syncgroup by a validator has an opportunity to propagate to all the nodes in the syncgroup if the keys or blessings are revoked after the change is admitted, but before it is fully propagated. The intent is that the grace period be chosen to be greater than the diameter of the syncgroup (measured in time). One way to ensure that is to insist that members sync with a central server at least every T time units, and make the grace period be 2T. The central server may sign the data anew to allow new members to pick it up.

The model is further complicated by performance concerns. An update written to syncbase might be quite small (perhaps tens of bytes) but: a) a public key signature or verification can take on the order of a

millisecond.  (Currently, ECDSA signing might a little under 1ms and
verification just over 2ms on a workstation.  A checker performs two such
verifications.)

b) unmarshalling even a simple Blessings object can take milliseconds. (!) c) marshalling a public key can take 10us. d) a Blessings object is of the order of a kilobyte of more, which may

represent substantial space overhead if duplicated.

Because of (a), we wish to batch syncbase updates, so that a single signature check applies to several updates. Thus the Data in a DataWithSignature is a vector of Item, rather than a single Item.

However, we will not always wish to put all updates in the same batch. For example, an author and a validator might share two different syncgroups with different memberships. In such a case, the author might keep the batches for one syncgoup separate from batches for the other syncgroup, even though the author blessings and validator identities are the same for all the batches. Thus, because of (b,c,d), it's worth decoupling the author's Blessings data and the validator's key data separately from the signed batches itself, so that the blessings and validator data can be processed once, even though several batches of updates are being sent. A ValidationCache is used to hold this data separately, and allow it to be sent just once, rather than once per signature.

Lastly, imagine that the author sends a batch of 10 updates to a validator, and the validator then syncs with a checker that is permitted to see only half of the updates; perhaps ACLs prevent if from seeing the others. This requires that the signature on the batch remain valid even if some of the updates in the batch are removed. This is accomplished via the Item type, which is a VDL union type that contains either the bytes of the marshalled form of the update, or (if the update must not be sent) the SHA-256 hash of the data (which can be computed with SumByteVectorWithLength()).

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNeedAuthorBlessingsAndValidatorDataForHash = verror.Register(
		pkgPath+".ErrNeedAuthorBlessingsAndValidatorDataForHash",
		verror.RetryRefetch,
		"{1:}{2:} The ValidationCache contains neither the author blessings nor the validator data{:_}")
	ErrNeedAuthorBlessingsForHash = verror.Register(
		pkgPath+".ErrNeedAuthorBlessingsForHash",
		verror.RetryRefetch,
		"{1:}{2:} The ValidationCache does not contain the author blessings{:_}")
	ErrNeedValidatorDataForHash = verror.Register(
		pkgPath+".ErrNeedValidatorDataForHash",
		verror.RetryRefetch,
		"{1:}{2:} The ValidationCache does not contain the validator data{:_}")
)

These are among the errors may be returned by Check(), and indicate that the operation should be retried when new data has been added to the ValidationCache. The errors are public to make it easier for the client to test for them.

Functions

func SignData

func SignData(ctx *context.T, cache *ValidationCache, authorPrincipal security.Principal,
	blessings security.Blessings, data []Item) (d *DataWithSignature, blessingsData *BlessingsData, err error)

SignData() uses authorPrincipal to sign data using blessings (which must be associated with the authorPrincipal). A pointer to a newly constructed DataWithSignature with IsValidated==false is returned. Ensures that the blessings are stored in *cache. Typically, "authorPrincipal" is obtained from v23.GetPrincipal(ctx).

If a recipient of the result *d complains that it does not understand the hash d.BlessingHash, the signer should present it with blessingsData.MarshalledBlessings, which will allow the recipient to construct the Blessings. The Blessings are transmitted out of line because they are large, and may be reused for multiple signatures.

func SumByteVectorWithLength

func SumByteVectorWithLength(b []byte) []byte

SumByteVectorWithLength() returns a SHA-256 hash of len(b), followed by the contents of b.

func VDLReadItem

func VDLReadItem(dec vdl.Decoder, x *Item) error

Types

type BlessingsData

type BlessingsData struct {
	UnmarshalledBlessings security.Blessings // The Blessings.
	MarshalledBlessings   []byte             // VOM encoded Blessings.
	MarshalledPublicKey   []byte             // Value from blessings.PublicKey().MarshalBinary().
}

A BlessingsData contains information about a security.Blessings object. The object itself is referred to by UnmarshalledBlessings. The implementation constructs all instances; the client should not modify fields.

type DataWithSignature

type DataWithSignature struct {
	Data []Item
	// BlessingsHash is a key for the validation cache; the corresponding
	// cached value is a security.Blessings.
	BlessingsHash []byte
	// AuthorSigned is the signature of Data and BlessingsHash using the
	// private key associated with the blessings hashed in BlessingsHash.
	AuthorSigned security.Signature
	IsValidated  bool // Whether fields below are meaningful.
	// ValidatorDataHash is a key for the validation cache returned by
	// ValidatorData.Hash(); the corresponding cached value is the
	// ValidatorData.
	ValidatorDataHash []byte
	ValidatorSigned   security.Signature
}

A DataWithSignature represents a signed, and possibily validated, collection of Item structs.

If IsValidated==false and the AuthorSigned signature is valid, it means:

The signer whose Blessings have hash BlessingsHash asserts Data.

If IsValidated==true and both AuthorSigned and ValidatorSigned signatures are is valid, it means both:

  1. The signer whose Blessings b have hash BlessingsHash asserts Data.
  2. If vd is the ValidatorData with hash ValidatorDataHash, the owner of vd.PublicKey asserts that it checked that at least the names vd.Names[] were valid in b.

The sender obtains: - BlessingsHash (and the wire form of the blessings) with ValidationCache.AddBlessings(). - ValidatorDataHash (and the wire form of the ValidataData) with ValidationCache.AddValidatorData().

The receiver looks up: - BlessingsHash with ValidationCache.LookupBlessingsData() - ValidatorDataHash with ValidationCache.LookupValidatorData()

If not yet there, the receiver inserts the valus into its ValidationCache with: - ValidationCache.AddWireBlessings() - ValidationCache.AddValidatorData()

func (*DataWithSignature) Check

func (d *DataWithSignature) Check(ctx *context.T, cache *ValidationCache, call security.Call,
	krl *krl.KRL, gracePeriod time.Duration) (names []string, err error)

Check() verifies the signature(s) on *d:

If d.IsValidated==false, checks that:

  1. the author's signature is available in *cache.
  2. the author's signature over its blessings and the data is cyprotgraphically valid.
  3. security.SigningBlessingNames() yields a non-empty list of names when applied to the author's blessings.
  4. the author's public key is not known to be revoked.
  5. the local's public key (call.LocalPrincipal().PublicKey()) is not known to be revoked.
  6. the author's public key is the public key of the RPC caller.
  7. the author's public key and the local public key differ.

If checks pass and there are no other errors:

  • records the list of names found in check (3) in the ValidationData
  • adds a validation signature using the local public key (which is now the validator)
  • sets d.IsValidated
  • returns the list of names found in check (3), and a nil error.

Otherwise returns a nil list of names and a non-nil error.

If d.Validated==true, checks that:

  1. the author's signature and the validator data are available in *cache.
  2. the author's signature over its blessings and the data is cyprotgraphically valid.
  3. the list of names stored in the ValidatorData by the validator is non-empty.
  4. the author's public key and the validator's public key differ.
  5. the list of names stored in the ValidatorData by the validator is a subset of the list of names that the author's blessings could have represented.
  6. the author's public key is not known to be revoked more than gracePeriod ago.
  7. the validator's public key is not known to be revoked more than gracePeriod ago.
  8. the validator's signature is cryptographically valid.

If checks pass and there are no other errors:

  • returns the list of names in the validator's data, and a nil error.

Otherwise returns a nil list of names and a non-nil error.

func (*DataWithSignature) FillVDLTarget

func (m *DataWithSignature) FillVDLTarget(t vdl.Target, tt *vdl.Type) error

func (*DataWithSignature) MakeVDLTarget

func (m *DataWithSignature) MakeVDLTarget() vdl.Target

func (DataWithSignature) VDLIsZero

func (x DataWithSignature) VDLIsZero() bool

func (*DataWithSignature) VDLRead

func (x *DataWithSignature) VDLRead(dec vdl.Decoder) error

func (DataWithSignature) VDLWrite

func (x DataWithSignature) VDLWrite(enc vdl.Encoder) error

type DataWithSignatureTarget

type DataWithSignatureTarget struct {
	Value *DataWithSignature

	vdl.TargetBase
	vdl.FieldsTargetBase
	// contains filtered or unexported fields
}

func (*DataWithSignatureTarget) FinishField

func (t *DataWithSignatureTarget) FinishField(_, _ vdl.Target) error

func (*DataWithSignatureTarget) FinishFields

func (t *DataWithSignatureTarget) FinishFields(_ vdl.FieldsTarget) error

func (*DataWithSignatureTarget) StartField

func (t *DataWithSignatureTarget) StartField(name string) (key, field vdl.Target, _ error)

func (*DataWithSignatureTarget) StartFields

func (t *DataWithSignatureTarget) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error)

func (*DataWithSignatureTarget) ZeroField

func (t *DataWithSignatureTarget) ZeroField(name string) error

type Item

type Item interface {
	// Index returns the field index.
	Index() int
	// Interface returns the field value as an interface.
	Interface() interface{}
	// Name returns the field name.
	Name() string

	FillVDLTarget(vdl.Target, *vdl.Type) error
	VDLIsZero() bool
	VDLWrite(vdl.Encoder) error
	// contains filtered or unexported methods
}

Item represents any single field of the Item union type.

An Item represents either a marshalled data item or its SHA-256 hash. The Data field is a []byte, rather than an "any" to make signatures determistic. VOM encoding is not deterministic for two reasons: - map elements may be marshalled in any order - different versions of VOM may marshal in different ways. Thus, the initial producer of a data item marshals the data once, and it is this marshalled form that is transmitted from device to device. If the data were unmarshalled and then remarsahalled, the signatures might not match. The Hash field is used instead of the Data field when the recipient of the DataWithSignature is not permitted to see certain Items' Data fields.

type ItemData

type ItemData struct{ Value []byte } // Marshalled form of data.

ItemData represents field Data of the Item union type.

func (ItemData) FillVDLTarget

func (m ItemData) FillVDLTarget(t vdl.Target, tt *vdl.Type) error

func (ItemData) Index

func (x ItemData) Index() int

func (ItemData) Interface

func (x ItemData) Interface() interface{}

func (ItemData) MakeVDLTarget

func (m ItemData) MakeVDLTarget() vdl.Target

func (ItemData) Name

func (x ItemData) Name() string

func (ItemData) VDLIsZero

func (x ItemData) VDLIsZero() bool

func (ItemData) VDLWrite

func (x ItemData) VDLWrite(enc vdl.Encoder) error

type ItemHash

type ItemHash struct{ Value []byte } // Hash of what would have been in Data, as returned by SumByteVectorWithLength(Data).

ItemHash represents field Hash of the Item union type.

func (ItemHash) FillVDLTarget

func (m ItemHash) FillVDLTarget(t vdl.Target, tt *vdl.Type) error

func (ItemHash) Index

func (x ItemHash) Index() int

func (ItemHash) Interface

func (x ItemHash) Interface() interface{}

func (ItemHash) MakeVDLTarget

func (m ItemHash) MakeVDLTarget() vdl.Target

func (ItemHash) Name

func (x ItemHash) Name() string

func (ItemHash) VDLIsZero

func (x ItemHash) VDLIsZero() bool

func (ItemHash) VDLWrite

func (x ItemHash) VDLWrite(enc vdl.Encoder) error

type ItemTarget

type ItemTarget struct {
	Value *Item

	vdl.TargetBase
	vdl.FieldsTargetBase
	// contains filtered or unexported fields
}

func (*ItemTarget) FinishField

func (t *ItemTarget) FinishField(_, fieldTarget vdl.Target) error

func (*ItemTarget) FinishFields

func (t *ItemTarget) FinishFields(_ vdl.FieldsTarget) error

func (*ItemTarget) StartField

func (t *ItemTarget) StartField(name string) (key, field vdl.Target, _ error)

func (*ItemTarget) StartFields

func (t *ItemTarget) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error)

type ValidationCache

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

A ValidationCache records recently-seen instances of BlessingsData and ValidatorData values, keys by hashes of the blessings and validator keys respectively. Values may expire from the cache if unused for a duration specified with NewValidationCache().

func NewValidationCache

func NewValidationCache(expiry time.Duration) *ValidationCache

NewValidationCache() returns a pointer to a new, empty ValidationCache with the specified expiry duration..

func (*ValidationCache) AddBlessings

func (vc *ValidationCache) AddBlessings(ctx *context.T, blessings security.Blessings) (blessingsHash []byte, data *BlessingsData, err error)

AddBlessings() adds a BlessingsData for blessings to *cv, and returns a hash value, which if passed to LookupBlessingsData() will yield a pointer to the BlessingsData, or a non-nil error. The fields of BlessingsData other than UnmarshalledBlessings are constructed by this routine.

func (*ValidationCache) AddValidatorData

func (vc *ValidationCache) AddValidatorData(ctx *context.T, vd *ValidatorData) (validatorDataHash []byte)

AddValidatorData() adds a ValidatorData *vd to cache *vc, and returns a hash value, which if passed to LookupValidatorData() will yield a pointer to the ValidatorData. The client should not modify *vd after the call, since it is shared with *vc.

func (*ValidationCache) AddWireBlessings

func (vc *ValidationCache) AddWireBlessings(ctx *context.T,
	marshalledBlessings []byte) (blessingsHash []byte, data *BlessingsData, err error)

AddWireBlessings() adds a BlessingsData for blessings to *cv, and returns a hash value, which if passed to LookupBlessingsData() will yield a pointer to the BlessingsData, or a non-nil error. The fields of BlessingsData other than MarshalledBlessings are constructed by this routine.

func (*ValidationCache) LookupBlessingsData

func (vc *ValidationCache) LookupBlessingsData(ctx *context.T, blessingsHash []byte) (result *BlessingsData)

LookupBlessingsData() returns a pointer to the BlessingsData associated with blessingsHash in *vc. blessingsHash should have been returned by a previous call to AddBlessings() or AddWireBlessings() (possibly on another machine). nil is returned if the data is not present. The client should not modify *result, since it is shared with *vc.

func (*ValidationCache) LookupValidatorData

func (vc *ValidationCache) LookupValidatorData(ctx *context.T, validatorHash []byte) (result *ValidatorData)

LookupValidatorData() returns a pointer to the ValidatorData associated with hash validatorHash in *vc validatorHash should have been returned by a previous call to AddValidatorData() (possibly on another machine). nil is returned if the data is not present. The client should not modifiy *result, since it it shared with *vc.

type ValidatorData

type ValidatorData struct {
	Names               []string           // Names of valid signing blessings in the Blessings referred to by BlessingsHash.
	PublicKey           security.PublicKey // The key used to create ValidatorSigned.
	MarshalledPublicKey []byte             // PublicKey, marshalled with MarshalBinary().
}

A ValidatorData is the extra data that a validator signs when validating and signing a DataWithSignature. Clients may construct instances to pass to AddValidatorData(), but should not modify the fields of a constructed ValidatorData.

func FromWireValidatorData

func FromWireValidatorData(wvd *WireValidatorData) (vd ValidatorData, err error)

FromWireValidatorData() puts the in-memory form of WireValidatorData *wvd in *vd.

type WireValidatorData

type WireValidatorData struct {
	Names               []string // Names of valid signing blessings in the Blessings referred to by BlessingsHash.
	MarshalledPublicKey []byte   // PublicKey, marshalled with MarshalBinary().
}

WireValidatorData is the wire form of ValidatorData. It excludes the unmarshalled form of the public key.

func ToWireValidatorData

func ToWireValidatorData(vd *ValidatorData) (wvd WireValidatorData)

ToWireValidatorData() puts the wire form of ValidatorData *vd in *wvd.

func (*WireValidatorData) FillVDLTarget

func (m *WireValidatorData) FillVDLTarget(t vdl.Target, tt *vdl.Type) error

func (*WireValidatorData) MakeVDLTarget

func (m *WireValidatorData) MakeVDLTarget() vdl.Target

func (WireValidatorData) VDLIsZero

func (x WireValidatorData) VDLIsZero() bool

func (*WireValidatorData) VDLRead

func (x *WireValidatorData) VDLRead(dec vdl.Decoder) error

func (WireValidatorData) VDLWrite

func (x WireValidatorData) VDLWrite(enc vdl.Encoder) error

type WireValidatorDataTarget

type WireValidatorDataTarget struct {
	Value *WireValidatorData

	vdl.TargetBase
	vdl.FieldsTargetBase
	// contains filtered or unexported fields
}

func (*WireValidatorDataTarget) FinishField

func (t *WireValidatorDataTarget) FinishField(_, _ vdl.Target) error

func (*WireValidatorDataTarget) FinishFields

func (t *WireValidatorDataTarget) FinishFields(_ vdl.FieldsTarget) error

func (*WireValidatorDataTarget) StartField

func (t *WireValidatorDataTarget) StartField(name string) (key, field vdl.Target, _ error)

func (*WireValidatorDataTarget) StartFields

func (t *WireValidatorDataTarget) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error)

func (*WireValidatorDataTarget) ZeroField

func (t *WireValidatorDataTarget) ZeroField(name string) error

Directories

Path Synopsis
Package hashcache implements a simple cache intended to be indexed by hash values.
Package hashcache implements a simple cache intended to be indexed by hash values.
Package krl implements a trivial, in-memory key revocation list.
Package krl implements a trivial, in-memory key revocation list.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL