Documentation
¶
Overview ¶
Package protocol is a library for building compatible CONIKS clients and servers.
protocol implements the server- and client-side components of the CONIKS key management and verification protocols. More specifically, protocol provides an API for maintaining an auditable, privacy-preserving key directory on a server, as well as an API for checking the consistency of the directory at the client.
Consistency Checks ¶
This module implements all consistency checks performed by a CONIKS client on directory proofs received from a CONIKS server. These operations include the verification of username-to-key bindings (authentication paths), and non-equivocation checks (signed tree roots).
Directory ¶
This module implements a CONIKS key directory that a CONIKS key server maintains. A directory is a publicly auditable, tamper-evident, privacy-preserving data structure that contains mappings from usernames to public keys. It currently supports registration of new mappings, latest-version key lookups, historical key lookups, and monitoring of mappings.
Error ¶
This module defines the constants representing the types of errors that a CONIKS server may return to a client, and the results of a consistency check or a cryptographic verification that a CONIKS client performs.
Message ¶
This module defines the message format of the CONIKS client requests and corresponding CONIKS server responses for each CONIKS protocol. It also provides constructors for the response messages for each protocol.
Policy ¶
This module defines the directory's current CONIKS security/privacy policies, which include the public part of the VRF key used to generate private indices, the cryptographic algorithms in use, as well as the protocol version number.
Temporary Binding ¶
This module implements a temporary binding, which serves both as a proof of registration with a directory and as a signed promise by a CONIKS server to include the corresponding name-to-key binding in the next directory snapshot. As such, TBs allow clients to begin using a newly registered name-to-key binding for encryption/signing immediately without having to wait for the binding's inclusion in the next snapshot. However, clients must still check in the next epoch that the binding has been included in the snapshot to ensure that the server has not equivocated about it.
Index ¶
- Constants
- Variables
- func NewKeyLookupInEpochProof(ap *m.AuthenticationPath, str []*DirSTR, e ErrorCode) (*Response, ErrorCode)
- func NewKeyLookupProof(ap *m.AuthenticationPath, str *DirSTR, tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode)
- func NewMonitoringProof(ap []*m.AuthenticationPath, str []*DirSTR) (*Response, ErrorCode)
- func NewRegistrationProof(ap *m.AuthenticationPath, str *DirSTR, tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode)
- type ConiksDirectory
- func (d *ConiksDirectory) EpochDeadline() Timestamp
- func (d *ConiksDirectory) KeyLookup(req *KeyLookupRequest) (*Response, ErrorCode)
- func (d *ConiksDirectory) KeyLookupInEpoch(req *KeyLookupInEpochRequest) (*Response, ErrorCode)
- func (d *ConiksDirectory) LatestSTR() *DirSTR
- func (d *ConiksDirectory) Monitor(req *MonitoringRequest) (*Response, ErrorCode)
- func (d *ConiksDirectory) NewTB(name string, key []byte) *TemporaryBinding
- func (d *ConiksDirectory) Register(req *RegistrationRequest) (*Response, ErrorCode)
- func (d *ConiksDirectory) SetPolicies(epDeadline Timestamp)
- func (d *ConiksDirectory) Update()
- type ConsistencyChecks
- type DirSTR
- type DirectoryProof
- type DirectoryProofs
- type DirectoryResponse
- type ErrorCode
- type KeyLookupInEpochRequest
- type KeyLookupRequest
- type MonitoringRequest
- type Policies
- type RegistrationRequest
- type Request
- type Response
- type TemporaryBinding
- type Timestamp
Constants ¶
const ( RegistrationType = iota KeyLookupType KeyLookupInEpochType MonitoringType )
The types of requests CONIKS clients send during the CONIKS protocols.
const (
// Version indicates the current protocol version.
Version = "0.3"
)
Variables ¶
var Errors = map[ErrorCode]bool{ ErrMalformedClientMessage: true, ErrDirectory: true, ErrMalformedDirectoryMessage: true, }
Errors contains codes indicating the client should skip the consistency checks. These errors indicate that either a client request could not be processed due to a malformed client request, an internal server error or due to a malformed server response.
Functions ¶
func NewKeyLookupInEpochProof ¶
func NewKeyLookupInEpochProof(ap *m.AuthenticationPath, str []*DirSTR, e ErrorCode) (*Response, ErrorCode)
NewKeyLookupInEpochProof creates the response message a CONIKS directory sends to a client upon a KeyLookupRequest, and returns a Response containing a DirectoryProofs struct. directory.KeyLookupInEpoch() passes an authentication path ap and error code e according to the result of the lookup, and a list of signed tree roots for the requested range of epochs str.
See directory.KeyLookupInEpoch() for details on the contents of the created DirectoryProofs.
func NewKeyLookupProof ¶
func NewKeyLookupProof(ap *m.AuthenticationPath, str *DirSTR, tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode)
NewKeyLookupProof creates the response message a CONIKS directory sends to a client upon a KeyLookupRequest, and returns a Response containing a DirectoryProof struct. directory.KeyLookup() passes an authentication path ap, temporary binding tb and error code e according to the result of the key lookup, and the signed tree root for the latest epoch str.
See directory.KeyLookup() for details on the contents of the created DirectoryProof.
func NewMonitoringProof ¶
func NewMonitoringProof(ap []*m.AuthenticationPath, str []*DirSTR) (*Response, ErrorCode)
NewMonitoringProof creates the response message a CONIKS directory sends to a client upon a MonitoringRequest, and returns a Response containing a DirectoryProofs struct. directory.Monitor() passes a list of authentication paths ap and a list of signed tree roots for the requested range of epochs str.
See directory.Monitor() for details on the contents of the created DirectoryProofs.
func NewRegistrationProof ¶
func NewRegistrationProof(ap *m.AuthenticationPath, str *DirSTR, tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode)
NewRegistrationProof creates the response message a CONIKS directory sends to a client upon a RegistrationRequest, and returns a Response containing a DirectoryProof struct. directory.Register() passes an authentication path ap, temporary binding tb and error code e according to the result of the registration, and the signed tree root for the latest epoch str.
See directory.Register() for details on the contents of the created DirectoryProof.
Types ¶
type ConiksDirectory ¶
type ConiksDirectory struct {
// contains filtered or unexported fields
}
A ConiksDirectory maintains the underlying persistent authenticated dictionary (PAD) and its policies (i.e. epoch deadline, VRF public key, etc.).
The current implementation of ConiksDirectory also keeps track of temporary bindings (TBs). This feature may be split into a separate protocol extension in a future release.
func NewDirectory ¶
func NewDirectory(epDeadline Timestamp, vrfKey vrf.PrivateKey, signKey sign.PrivateKey, dirSize uint64, useTBs bool) *ConiksDirectory
NewDirectory constructs a new ConiksDirectory given the key server's PAD policies (i.e. epDeadline, vrfKey).
signKey is the private key the key server uses to generate signed tree roots (STRs) and TBs. dirSize indicates the number of PAD snapshots the server keeps in memory. useTBs indicates whether the key server returns TBs upon a successful registration.
func NewTestDirectory ¶
NewTestDirectory creates a ConiksDirectory used for testing server-side CONIKS operations.
func (*ConiksDirectory) EpochDeadline ¶
func (d *ConiksDirectory) EpochDeadline() Timestamp
EpochDeadline returns this ConiksDirectory's latest epoch deadline as a timestamp.
func (*ConiksDirectory) KeyLookup ¶
func (d *ConiksDirectory) KeyLookup(req *KeyLookupRequest) ( *Response, ErrorCode)
KeyLookup gets the public key for the username indicated in the KeyLookupRequest req received from a CONIKS client from the latest snapshot of this ConiksDirectory, and returns a tuple of the form (response, error). The response (which also includes the error code) is supposed to be sent back to the client. The returned error is used by the key server for logging purposes.
A request without a username is considered malformed, and causes KeyLookup() to return a message.NewErrorResponse(ErrMalformedClientMessage) tuple. If the username doesn't have an entry in the latest directory snapshot and also isn't pending registration (i.e. has a corresponding TB), KeyLookup() returns a message.NewKeyLookupProof(ap=proof of absence, str, nil, ReqNameNotFound) tuple. Otherwise, KeyLookup() returns a message.NewKeyLookupProof(ap=proof of absence, str, tb, ReqSuccess) tuple if there is a corresponding TB for the username, but there isn't an entry in the directory yet, and a a message.NewKeyLookupProof(ap=proof of inclusion, str, nil, ReqSuccess) if there is. In any case, str is the signed tree root for the latest epoch. If KeyLookup() encounters an internal error at any point, it returns a message.NewErrorResponse(ErrDirectory) tuple.
func (*ConiksDirectory) KeyLookupInEpoch ¶
func (d *ConiksDirectory) KeyLookupInEpoch(req *KeyLookupInEpochRequest) ( *Response, ErrorCode)
KeyLookupInEpoch gets the public key for the username for a prior epoch in the directory history indicated in the KeyLookupInEpochRequest req received from a CONIKS client, and returns a tuple of the form (response, error). The response (which also includes the error code) is supposed to be sent back to the client. The returned error is used by the key server for logging purposes.
A request without a username or with an epoch greater than the latest epoch of this directory is considered malformed, and causes KeyLookupInEpoch() to return a message.NewErrorResponse(ErrMalformedClientMessage) tuple. If the username doesn't have an entry in the directory snapshot for the indicated epoch, KeyLookupInEpoch() returns a message.NewKeyLookupInEpochProof(ap=proof of absence, str, ReqNameNotFound) tuple. Otherwise, KeyLookupInEpoch() returns a message.NewKeyLookupInEpochProof(ap=proof of inclusion, str, ReqSuccess) tuple. In either case, str is a list of STRs for the epoch range [ep, d.LatestSTR().Epoch], where ep is the past epoch for which the client has requested the user's key. KeyLookupInEpoch() proofs do not include temporary bindings since the TB corresponding to a registered binding is discarded at the time the binding is included in a directory snapshot. If KeyLookupInEpoch() encounters an internal error at any point, it returns a message.NewErrorResponse(ErrDirectory) tuple.
func (*ConiksDirectory) LatestSTR ¶
func (d *ConiksDirectory) LatestSTR() *DirSTR
LatestSTR returns this ConiksDirectory's latest STR.
func (*ConiksDirectory) Monitor ¶
func (d *ConiksDirectory) Monitor(req *MonitoringRequest) ( *Response, ErrorCode)
Monitor gets the directory proofs for the username for the range of epochs indicated in the MonitoringRequest req received from a CONIKS client, and returns a tuple of the form (response, error). The response (which also includes the error code) is supposed to be sent back to the client. The returned error is used by the key server for logging purposes.
A request without a username, with a start epoch greater than the latest epoch of this directory, or a start epoch greater than the end epoch is considered malformed, and causes Monitor() to return a message.NewErrorResponse(ErrMalformedClientMessage) tuple. Monitor() returns a message.NewMonitoringProof(ap, str) tuple. ap is a list of proofs of inclusion, and str is a list of STRs for the epoch range [startEpoch, endEpoch], where startEpoch and endEpoch are the epoch range endpoints indicated in the client's request. If req.endEpoch is greater than d.LatestSTR().Epoch, the end of the range will be set to d.LatestSTR().Epoch. If Monitor() encounters an internal error at any point, it returns a message.NewErrorResponse(ErrDirectory) tuple.
func (*ConiksDirectory) NewTB ¶
func (d *ConiksDirectory) NewTB(name string, key []byte) *TemporaryBinding
NewTB creates a new temporary binding for the given name-to-key mapping. NewTB() computes the private index for the name, and digitally signs the (index, key, latest STR signature) tuple.
func (*ConiksDirectory) Register ¶
func (d *ConiksDirectory) Register(req *RegistrationRequest) ( *Response, ErrorCode)
Register inserts the username-to-key mapping contained in a RegistrationRequest req received from a CONIKS client into this ConiksDirectory, and returns a tuple of the form (response, error). The response (which also includes the error code) is supposed to be sent back to the client. The returned error is used by the key server for logging purposes.
A request without a username or without a public key is considered malformed, and causes Register() to return a message.NewErrorResponse(ErrMalformedClientMessage) tuple. Register() inserts the new mapping in req into a pending version of the directory so it can be included in the snapshot taken at the end of the latest epoch, and returns a message.NewRegistrationProof(ap=proof of absence, str, tb, ReqSuccess) tuple if this operation succeeds. Otherwise, if the username already exists, Register() returns a message.NewRegistrationProof(ap=proof of inclusion, str, nil, ReqNameExisted) tuple. ap will be a proof of absence with a non-nil TB, if the username is still pending inclusion in the next directory snapshot. In any case, str is the signed tree root for the latest epoch. If Register() encounters an internal error at any point, it returns a message.NewErrorResponse(ErrDirectory) tuple.
func (*ConiksDirectory) SetPolicies ¶
func (d *ConiksDirectory) SetPolicies(epDeadline Timestamp)
SetPolicies sets this ConiksDirectory's epoch deadline, which will be used in the next epoch.
func (*ConiksDirectory) Update ¶
func (d *ConiksDirectory) Update()
Update creates a new PAD snapshot updating this ConiksDirectory. Update() is called at the end of a CONIKS epoch. This implementation also deletes all issued TBs for the ending epoch as their corresponding mappings will have been inserted into the PAD.
type ConsistencyChecks ¶
type ConsistencyChecks struct { // SavedSTR stores the latest verified signed tree root. SavedSTR *DirSTR Bindings map[string][]byte TBs map[string]*TemporaryBinding // contains filtered or unexported fields }
ConsistencyChecks stores the latest consistency check state of a CONIKS client. This includes the latest SignedTreeRoot, all the verified name-to-key bindings of the client, as well as a directory's policies (e.g., whether the TemporaryBinding extension is being used).
The client should create a new ConsistencyChecks instance only once, when it registers its user's binding with a ConiksDirectory. This ConsistencyChecks instance will then be used to verify subsequent responses from the ConiksDirectory to any client request.
func NewCC ¶
func NewCC(savedSTR *DirSTR, useTBs bool, signKey sign.PublicKey) *ConsistencyChecks
NewCC creates an instance of ConsistencyChecks using a CONIKS directory's pinned STR at epoch 0, or the consistency state read from persistent storage.
func (*ConsistencyChecks) HandleResponse ¶
func (cc *ConsistencyChecks) HandleResponse(requestType int, msg *Response, uname string, key []byte) ErrorCode
HandleResponse verifies the directory's response for a request. It first verifies the directory's returned status code of the request. If the status code is not in the Errors array, it means the directory has successfully handled the request. The verifier will then check the consistency (i.e. binding validity and non-equivocation) of the response.
HandleResponse() will panic if it is called with an int that isn't a valid/known request type.
Note that the consistency state will be updated regardless of whether the checks pass / fail, since a response message contains cryptographic proof of having been issued nonetheless.
type DirSTR ¶
type DirSTR struct { *merkletree.SignedTreeRoot Policies *Policies }
DirSTR disambiguates merkletree.SignedTreeRoot's AssocData interface, for the purpose of exporting and unmarshalling.
func NewDirSTR ¶
func NewDirSTR(str *merkletree.SignedTreeRoot) *DirSTR
NewDirSTR constructs a new DirSTR from a merkletree.SignedTreeRoot
func (*DirSTR) VerifyHashChain ¶
VerifyHashChain wraps merkletree.SignedTreeRoot.VerifyHashChain
type DirectoryProof ¶
type DirectoryProof struct { AP *m.AuthenticationPath STR *DirSTR TB *TemporaryBinding `json:",omitempty"` }
A DirectoryProof response includes an authentication path AP for a given username-to-key binding in the directory, a signed tree root STR, and optionally a temporary binding for the given binding for a single epoch. A CONIKS directory returns this DirectoryResponse type upon a RegistrationRequest or a KeyLookupRequest.
type DirectoryProofs ¶
type DirectoryProofs struct { AP []*m.AuthenticationPath STR []*DirSTR }
A DirectoryProofs response includes a list of authentication paths AP for a given username-to-key binding in the directory and a list of signed tree roots STR for a range of epochs. A CONIKS directory returns this DirectoryResponse type upon a KeyLookupInEpochRequest or a MonitoringRequest.
type DirectoryResponse ¶
type DirectoryResponse interface{}
A DirectoryResponse is a message that includes cryptographic proofs about the key directory that a CONIKS key directory returns to a CONIKS client.
type ErrorCode ¶
type ErrorCode int
An ErrorCode implements the built-in error interface type.
const ( ReqSuccess ErrorCode = iota + 100 ReqNameExisted ReqNameNotFound ErrDirectory ErrMalformedClientMessage ErrMalformedDirectoryMessage )
These codes indicate the status of a client-server message exchange. Codes prefixed by "Req" indicate different client request results. Codes prefixed by "Err" indicate an internal server error or a malformed message.
const ( CheckPassed ErrorCode = iota + 200 CheckBadSignature CheckBadVRFProof CheckBindingsDiffer CheckBadCommitment CheckBadLookupIndex CheckBadAuthPath CheckBadSTR CheckBadPromise CheckBrokenPromise )
These codes indicate the result of a consistency check or cryptographic verification. These codes are prefixed by "Check".
type KeyLookupInEpochRequest ¶
A KeyLookupInEpochRequest is a message with a username as a string and an epoch as a uint64 that a CONIKS client sends to the directory to retrieve the public key bound to the username in the given epoch. The client sends this request type when it needs to obtain a user's key for a past epoch. The client can send a KeyLookupRequest if it needs to look up a user's key for the latest epoch.
The response to a successful request is a DirectoryProofs with an AP of length 1 containing the auth path for the requested Epoch, and a list of STRs covering the epoch range [Epoch, d.LatestSTR().Epoch].
type KeyLookupRequest ¶
type KeyLookupRequest struct {
Username string
}
A KeyLookupRequest is a message with a username as a string that a CONIKS client sends to a CONIKS directory to retrieve the public key bound to the given username at the latest epoch. If the client needs to look up a username's key for a prior epoch, it must send a KeyLookupInEpochRequest.
The response to a successful request is a DirectoryProof with a TB if the requested username was registered during the latest epoch (i.e. the new binding hasn't been committed to the directory).
type MonitoringRequest ¶
A MonitoringRequest is a message with a username as a string and the start and end epochs of an epoch range as two uint64 that a CONIKS client sends to the directory to monitor the given user's key in a CONIKS key directory, i.e. to ensure that the key bound to the username hasn't changed unexpectedly.
If the client needs to check the consistency of a user's binding for a range of epochs (e.g. if the client went offline for several epochs and was unable to monitor its user's binding during that period), it indicates the beginning of the range with the start epoch, and the end of the range with the end epoch. An end epoch with a value greater than the key directory's latest epoch sets the end of the epoch range at the directory's latest epoch.
Specifically, there are two cases for doing monitoring: prior history verification which can be used to verify the absence of the binding before registration, and name-to-key binding monitoring which can be used to verify the inclusion of the binding after registration.
type Policies ¶
type Policies struct { Version string HashID string VrfPublicKey vrf.PublicKey EpochDeadline Timestamp }
Policies is a summary of the directory's current CONIKS security/privacy policies. This includes the public part of the VRF key used to generate private indices, the cryptographic algorithms in use, as well as the protocol version number.
func GetPolicies ¶
func GetPolicies(str *merkletree.SignedTreeRoot) *Policies
GetPolicies returns the set of policies included in the STR.
func NewPolicies ¶
NewPolicies returns a new Policies with the given epoch deadline and public VRF key.
type RegistrationRequest ¶
type RegistrationRequest struct { Username string Key []byte AllowUnsignedKeychange bool `json:",omitempty"` AllowPublicLookup bool `json:",omitempty"` }
A RegistrationRequest is a message with a username as a string and a public key as bytes that a CONIKS client sends to a CONIKS directory to register a new entry (i.e. name-to-key binding). Optionally, the client can include the user's key change and visibility policies as boolean values in the request. These flags are currently unused by the CONIKS protocols.
The response to a successful request is a DirectoryProof with a TB for the requested username and public key.
type Request ¶
type Request struct { Type int Request interface{} }
A Request message defines the data a CONIKS client must send to a CONIKS directory for a particular request.
type Response ¶
type Response struct { Error ErrorCode DirectoryResponse `json:",omitempty"` }
A Response message indicates the result of a CONIKS client request with an appropriate error code, and defines the set of cryptographic proofs a CONIKS directory must return as part of its response.
func NewErrorResponse ¶
NewErrorResponse creates a new response message indicating the error that occurred while a CONIKS directory was processing a client request.
func (*Response) GetKey ¶
GetKey returns the key extracted from a validated CONIKS directory's response.
If the response contains a single authentication path, the key is obtained from that authentication path or the temporary binding, depending on the returned proof type.
If the response contains a range of authentication paths, the key is obtained from the authentication path corresponding to the most recent signed tree root.
type TemporaryBinding ¶
A TemporaryBinding consists of the private Index for a username, the Value (i.e. public key etc.) mapped to this index in a key directory, and a digital Signature of these fields.
A TB serves as a proof of registration and as a signed promise by a CONIKS server to include the corresponding name-to-key binding in the next directory snapshot. As such, TBs allow clients to begin using the contained name-to-key binding for encryption/signing without having to wait for the binding's inclusion in the next snapshot.
func (*TemporaryBinding) Serialize ¶
func (tb *TemporaryBinding) Serialize(strSig []byte) []byte
Serialize serializes the temporary binding into a specified format.