Documentation ¶
Overview ¶
The concept of identities allows you to amend the static public key (as defined in noiseprotocol) with additional metadata, effectively creating a certificate (if the combination if metadata and public is signed by trusted party). The downside of this approach is, that the private key, which the static public key is derived from needs to reside in memory (at least for now), because we will perform DH operations on it. So if you want to use certificates with private keys stored in TPMs, TEEs etc. this approach is not for you (for now).
Package noise implements the Noise Protocol Framework.
Noise is a low-level framework for building crypto protocols. Noise protocols support mutual and optional authentication, identity hiding, forward secrecy, zero round-trip encryption, and other advanced features. For more details, visit https://noiseprotocol.org.
Index ¶
- Constants
- Variables
- type Cipher
- type CipherFunc
- type CipherState
- type CipherSuite
- type Config
- type DHFunc
- type DHKey
- type HandshakePattern
- type HandshakeState
- func (s *HandshakeState) ChannelBinding() []byte
- func (s *HandshakeState) LocalEphemeral() DHKey
- func (s *HandshakeState) MessageIndex() int
- func (s *HandshakeState) PeerEphemeral() []byte
- func (s *HandshakeState) PeerIdentity() Identity
- func (s *HandshakeState) ReadMessage(out []byte, message ReadableHandshakeMessage) ([]byte, *CipherState, *CipherState, error)
- func (s *HandshakeState) WriteMessage(out WriteableHandshakeMessage, payload []byte) (*CipherState, *CipherState, error)
- type HashFunc
- type Identity
- type IdentityMarshaler
- type IdentityVerifier
- type MessagePattern
- type PrivateIdentity
- type PrivateSmolIdentity
- type ReadableHandshakeMessage
- type SimpleIdentity
- type SimpleMessage
- func (s *SimpleMessage) Length() int
- func (s *SimpleMessage) ReadEPublic() ([]byte, error)
- func (s *SimpleMessage) ReadEncryptedIdentity() ([]byte, error)
- func (s *SimpleMessage) ReadPayload() ([]byte, error)
- func (s *SimpleMessage) Reset()
- func (s *SimpleMessage) Serialize() []byte
- func (s *SimpleMessage) WriteEPublic(e []byte)
- func (s *SimpleMessage) WriteEncryptedIdentity(sr []byte)
- func (s *SimpleMessage) WriteEncryptedPayload(p []byte)
- type SmolIdentity
- type SmolIdentityMarshaler
- type SmolIdentityVerifier
- type WriteableHandshakeMessage
Constants ¶
const MaxMsgLen = 65535
MaxMsgLen is the maximum number of bytes that can be sent in a single Noise message.
Variables ¶
var ErrShortMessage = errors.New("noise: message is too short")
ErrShortMessage is returned by ReadMessage if a message is not as long as it should be.
var HandshakeIK = HandshakePattern{ Name: "IK", ResponderPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHES, MessagePatternS, MessagePatternDHSS}, {MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, }, }
var HandshakeIN = HandshakePattern{ Name: "IN", Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternS}, {MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, }, }
var HandshakeIX = HandshakePattern{ Name: "IX", Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternS}, {MessagePatternE, MessagePatternDHEE, MessagePatternDHSE, MessagePatternS, MessagePatternDHES}, }, }
var HandshakeK = HandshakePattern{ Name: "K", InitiatorPreMessages: []MessagePattern{MessagePatternS}, ResponderPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHES, MessagePatternDHSS}, }, }
var HandshakeKK = HandshakePattern{ Name: "KK", InitiatorPreMessages: []MessagePattern{MessagePatternS}, ResponderPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHES, MessagePatternDHSS}, {MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, }, }
var HandshakeKN = HandshakePattern{ Name: "KN", InitiatorPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE}, {MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, }, }
var HandshakeKX = HandshakePattern{ Name: "KX", InitiatorPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE}, {MessagePatternE, MessagePatternDHEE, MessagePatternDHSE, MessagePatternS, MessagePatternDHES}, }, }
var HandshakeN = HandshakePattern{ Name: "N", ResponderPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHES}, }, }
var HandshakeNK = HandshakePattern{ Name: "NK", ResponderPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHES}, {MessagePatternE, MessagePatternDHEE}, }, }
var HandshakeNN = HandshakePattern{ Name: "NN", Messages: [][]MessagePattern{ {MessagePatternE}, {MessagePatternE, MessagePatternDHEE}, }, }
var HandshakeNX = HandshakePattern{ Name: "NX", Messages: [][]MessagePattern{ {MessagePatternE}, {MessagePatternE, MessagePatternDHEE, MessagePatternS, MessagePatternDHES}, }, }
var HandshakeX = HandshakePattern{ Name: "X", ResponderPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHES, MessagePatternS, MessagePatternDHSS}, }, }
var HandshakeXK = HandshakePattern{ Name: "XK", ResponderPreMessages: []MessagePattern{MessagePatternS}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHES}, {MessagePatternE, MessagePatternDHEE}, {MessagePatternS, MessagePatternDHSE}, }, }
var HandshakeXN = HandshakePattern{ Name: "XN", Messages: [][]MessagePattern{ {MessagePatternE}, {MessagePatternE, MessagePatternDHEE}, {MessagePatternS, MessagePatternDHSE}, }, }
var HandshakeXX = HandshakePattern{ Name: "XX", Messages: [][]MessagePattern{ {MessagePatternE}, {MessagePatternE, MessagePatternDHEE, MessagePatternS, MessagePatternDHES}, {MessagePatternS, MessagePatternDHSE}, }, }
var HandshakeXXfallback = HandshakePattern{ Name: "XXfallback", ResponderPreMessages: []MessagePattern{MessagePatternE}, Messages: [][]MessagePattern{ {MessagePatternE, MessagePatternDHEE, MessagePatternS, MessagePatternDHSE}, {MessagePatternS, MessagePatternDHES}, }, }
Functions ¶
This section is empty.
Types ¶
type Cipher ¶
type Cipher interface { // Encrypt encrypts the provided plaintext with a nonce and then appends the // ciphertext to out along with an authentication tag over the ciphertext // and optional authenticated data. Encrypt(out []byte, n uint64, ad, plaintext []byte) []byte // Decrypt authenticates the ciphertext and optional authenticated data and // then decrypts the provided ciphertext using the provided nonce and // appends it to out. Decrypt(out []byte, n uint64, ad, ciphertext []byte) ([]byte, error) }
A Cipher is a AEAD cipher that has been initialized with a key.
type CipherFunc ¶
type CipherFunc interface { // Cipher initializes the algorithm with the provided key and returns a Cipher. Cipher(k [32]byte) Cipher // CipherName is the name of the cipher. CipherName() string }
A CipherFunc implements an AEAD symmetric cipher.
var CipherAESGCM CipherFunc = cipherFn{cipherAESGCM, "AESGCM"}
CipherAESGCM is the AES256-GCM AEAD cipher.
var CipherChaChaPoly CipherFunc = cipherFn{cipherChaChaPoly, "ChaChaPoly"}
CipherChaChaPoly is the ChaCha20-Poly1305 AEAD cipher construction.
type CipherState ¶
type CipherState struct {
// contains filtered or unexported fields
}
A CipherState provides symmetric encryption and decryption after a successful handshake.
func (*CipherState) Cipher ¶
func (s *CipherState) Cipher() Cipher
Cipher returns the low-level symmetric encryption primitive. It should only be used if nonces need to be managed manually, for example with a network protocol that can deliver out-of-order messages. This is dangerous, users must ensure that they are incrementing a nonce after every encrypt operation. After calling this method, it is an error to call Encrypt/Decrypt on the CipherState.
func (*CipherState) Decrypt ¶
func (s *CipherState) Decrypt(out, ad, ciphertext []byte) ([]byte, error)
Decrypt checks the authenticity of the ciphertext and authenticated data and then decrypts and appends the plaintext to out. This method automatically increments the nonce after every call, messages must be provided in the same order that they were encrypted with no missing messages.
func (*CipherState) Encrypt ¶
func (s *CipherState) Encrypt(out, ad, plaintext []byte) []byte
Encrypt encrypts the plaintext and then appends the ciphertext and an authentication tag across the ciphertext and optional authenticated data to out. This method automatically increments the nonce after every call, so messages must be decrypted in the same order.
func (*CipherState) Rekey ¶
func (s *CipherState) Rekey()
type CipherSuite ¶
type CipherSuite interface { DHFunc CipherFunc HashFunc Name() []byte }
A CipherSuite is a set of cryptographic primitives used in a Noise protocol. It should be constructed with NewCipherSuite.
func NewCipherSuite ¶
func NewCipherSuite(dh DHFunc, c CipherFunc, h HashFunc) CipherSuite
NewCipherSuite returns a CipherSuite constructed from the specified primitives.
type Config ¶
type Config struct { // CipherSuite is the set of cryptographic primitives that will be used. CipherSuite CipherSuite // Random is the source for cryptographically appropriate random bytes. If // zero, it is automatically configured. Random io.Reader // Pattern is the pattern for the handshake. Pattern HandshakePattern // Initiator must be true if the first message in the handshake will be sent // by this peer. Initiator bool // Prologue is an optional message that has already be communicated and must // be identical on both sides for the handshake to succeed. Prologue []byte PresharedKey []byte // when PresharedKey is specified PresharedKeyPlacement int // StaticKeypair is this peer's static keypair, required if part of the // handshake. StaticKeypair PrivateIdentity // EphemeralKeypair is this peer's ephemeral keypair that was provided as // a pre-message in the handshake. EphemeralKeypair DHKey // PeerStatic is the static public key of the remote peer that was provided // as a pre-message in the handshake. PeerStatic Identity // PeerEphemeral is the ephemeral public key of the remote peer that was // provided as a pre-message in the handshake. PeerEphemeral []byte // IdMarshaller allows you to use more complex IDs than plain public keys, i.e. certificates. // This parameter is optional. IDMarshaler IdentityMarshaler // IDVerifier can optionally be set to verify the remote identity. IDVerifier IdentityVerifier }
A Config provides the details necessary to process a Noise handshake. It is never modified by this package, and can be reused.
type DHFunc ¶
type DHFunc interface { // GenerateKeypair generates a new keypair using random as a source of // entropy. GenerateKeypair(random io.Reader) (DHKey, error) // DH performs a Diffie-Hellman calculation between the provided private and // public keys and returns the result. DH(privkey, pubkey []byte) []byte // DHLen is the number of bytes returned by DH. DHLen() int // DHName is the name of the DH function. DHName() string }
A DHFunc implements Diffie-Hellman key agreement.
var DH25519 DHFunc = dh25519{}
DH25519 is the Curve25519 ECDH function.
type DHKey ¶
A DHKey is a keypair used for Diffie-Hellman key agreement.
func (DHKey) PrivateKey ¶
PrivateKey returns the private key part of DHKey
type HandshakePattern ¶
type HandshakePattern struct { Name string InitiatorPreMessages []MessagePattern ResponderPreMessages []MessagePattern Messages [][]MessagePattern }
A HandshakePattern is a list of messages and operations that are used to perform a specific Noise handshake.
type HandshakeState ¶
type HandshakeState struct {
// contains filtered or unexported fields
}
A HandshakeState tracks the state of a Noise handshake. It may be discarded after the handshake is complete.
func NewHandshakeState ¶
func NewHandshakeState(c Config) (*HandshakeState, error)
NewHandshakeState starts a new handshake using the provided configuration.
func NewSmolHandshakeState ¶ added in v0.1.5
func NewSmolHandshakeState(c Config, rootCerts ...*smolcert.Certificate) (*HandshakeState, error)
func (*HandshakeState) ChannelBinding ¶
func (s *HandshakeState) ChannelBinding() []byte
ChannelBinding provides a value that uniquely identifies the session and can be used as a channel binding. It is an error to call this method before the handshake is complete.
func (*HandshakeState) LocalEphemeral ¶
func (s *HandshakeState) LocalEphemeral() DHKey
LocalEphemeral returns the local ephemeral key pair generated during a handshake.
func (*HandshakeState) MessageIndex ¶
func (s *HandshakeState) MessageIndex() int
MessageIndex returns the current handshake message id
func (*HandshakeState) PeerEphemeral ¶
func (s *HandshakeState) PeerEphemeral() []byte
PeerEphemeral returns the ephemeral key provided by the remote peer during a handshake. It is an error to call this method if a handshake message containing a static key has not been read.
func (*HandshakeState) PeerIdentity ¶
func (s *HandshakeState) PeerIdentity() Identity
PeerIdentity returns the static identity provided by the remote peer during a handshake. It is an error to call this method if a handshake message containing the static identity has not been read.
func (*HandshakeState) ReadMessage ¶
func (s *HandshakeState) ReadMessage(out []byte, message ReadableHandshakeMessage) ([]byte, *CipherState, *CipherState, error)
ReadMessage processes a received handshake message and appends the payload, if any to out. If the handshake is completed by the call, two CipherStates will be returned, one is used for encryption of messages to the remote peer, the other is used for decryption of messages from the remote peer. It is an error to call this method out of sync with the handshake pattern.
func (*HandshakeState) WriteMessage ¶
func (s *HandshakeState) WriteMessage(out WriteableHandshakeMessage, payload []byte) (*CipherState, *CipherState, error)
WriteMessage appends a handshake message to out. The message will include the optional payload if provided. If the handshake is completed by the call, two CipherStates will be returned, one is used for encryption of messages to the remote peer, the other is used for decryption of messages from the remote peer. It is an error to call this method out of sync with the handshake pattern.
type HashFunc ¶
type HashFunc interface { // Hash returns a hash state. Hash() hash.Hash // HashName is the name of the hash function. HashName() string }
A HashFunc implements a cryptographic hash function.
var HashBLAKE2b HashFunc = hashFn{blake2bNew, "BLAKE2b"}
HashBLAKE2b is the BLAKE2b hash function.
var HashBLAKE2s HashFunc = hashFn{blake2sNew, "BLAKE2s"}
HashBLAKE2s is the BLAKE2s hash function.
type Identity ¶
type Identity interface {
PublicKey() []byte
}
Identity is an interface which provides the public key of a static identity to the HandshakeState
type IdentityMarshaler ¶
type IdentityMarshaler interface { UnmarshalIdentity(identityBytes []byte) (Identity, error) MarshalIdentity(identity Identity) ([]byte, error) }
IdentityMarshaler provides the HandshakeState with the ability to marshal und unmarshal identities from byte slices, enabling the use of certificates instead of plain public keys
type IdentityVerifier ¶
IdentityVerifier can be used by a HandshakeState to verify the remote identity fulfills certain criteria (i.e. signed by common authority etc.)
type MessagePattern ¶
type MessagePattern int
A MessagePattern is a single message or operation used in a Noise handshake.
const ( // MessagePatternS Appends EncryptAndHash(s.public_key) to the buffer. // // Sets temp to the next DHLEN + 16 bytes of the message if HasKey() == True, or to the next DHLEN bytes otherwise. Sets rs (which must be empty) to DecryptAndHash(temp). MessagePatternS MessagePattern = iota // MessagePatternE Sets e (which must be empty) to GENERATE_KEYPAIR(). // Appends e.public_key to the buffer. Calls MixHash(e.public_key) // // Sets re (which must be empty) to the next DHLEN bytes from the message. Calls MixHash(re.public_key). MessagePatternE // MessagePatternDHEE Calls MixKey(DH(e, re)). // // Calls MixKey(DH(e, re)). MessagePatternDHEE // MessagePatternDHES Calls MixKey(DH(e, rs)) if initiator, MixKey(DH(s, re)) if responder. // // Calls MixKey(DH(e, rs)) if initiator, MixKey(DH(s, re)) if responder. MessagePatternDHES // MessagePatternDHSE Calls MixKey(DH(s, re)) if initiator, MixKey(DH(e, rs)) if responder. // // Calls MixKey(DH(s, re)) if initiator, MixKey(DH(e, rs)) if responder. MessagePatternDHSE // MessagePatternDHSS Calls MixKey(DH(s, rs)). // // Calls MixKey(DH(s, rs)). MessagePatternDHSS // MessagePatternPSK for PresharedKey MessagePatternPSK )
type PrivateIdentity ¶
PrivateIdentity is an Identity with access to the private key
type PrivateSmolIdentity ¶ added in v0.1.5
type PrivateSmolIdentity struct { SmolIdentity // contains filtered or unexported fields }
PrivateSmolIdentity wraps a SmolIdentity and an ed25519 private key
func NewPrivateSmolIdentity ¶ added in v0.1.5
func NewPrivateSmolIdentity(cert *smolcert.Certificate, privKey ed25519.PrivateKey) *PrivateSmolIdentity
NewPrivateSmolIdentity creates a new PrivateSmolIdentity which contains the smolcert with the private key. This might be needed for cryptographic operations like eDH or eDSA etc.
func (*PrivateSmolIdentity) PrivateKey ¶ added in v0.1.5
func (p *PrivateSmolIdentity) PrivateKey() []byte
PrivateKey returns a curve25519 representation of the private key
type ReadableHandshakeMessage ¶
type ReadableHandshakeMessage interface { ReadEPublic() ([]byte, error) ReadEncryptedIdentity() ([]byte, error) ReadPayload() ([]byte, error) Length() int }
ReadableHandshakeMessage provides the HandshakeState the possibility to digest handshake messages in other formats than simple concatenated byte slices
type SimpleIdentity ¶
type SimpleIdentity struct { // PubKey is the static public key PubKey []byte }
SimpleIdentity gives the possibility to simply use plain public keys as identity, similar to the original behavior
func (*SimpleIdentity) PublicKey ¶
func (s *SimpleIdentity) PublicKey() []byte
PublicKey gives you the static public key of this identity
type SimpleMessage ¶
type SimpleMessage struct {
// contains filtered or unexported fields
}
SimpleMessage is mostly used for testing, but can also be used to emulate the previous behavior of simply concatenating bytes together
func (*SimpleMessage) Length ¶
func (s *SimpleMessage) Length() int
Length gives you the total length of this message
func (*SimpleMessage) ReadEPublic ¶
func (s *SimpleMessage) ReadEPublic() ([]byte, error)
ReadEPublic gives you the ephemeral remote public key from this payload
func (*SimpleMessage) ReadEncryptedIdentity ¶
func (s *SimpleMessage) ReadEncryptedIdentity() ([]byte, error)
ReadEncryptedIdentity gives you the bytes of the encrypted static remote identity (key)
func (*SimpleMessage) ReadPayload ¶
func (s *SimpleMessage) ReadPayload() ([]byte, error)
ReadPayload gives you the encrypted bytes of the additional optional payload
func (*SimpleMessage) Reset ¶
func (s *SimpleMessage) Reset()
Reset sets the fields to empty values, used in testing
func (*SimpleMessage) Serialize ¶
func (s *SimpleMessage) Serialize() []byte
Serialize simply concatenates all fields in an expected order
func (*SimpleMessage) WriteEPublic ¶
func (s *SimpleMessage) WriteEPublic(e []byte)
WriteEPublic writes the ephemeral public key to the payload
func (*SimpleMessage) WriteEncryptedIdentity ¶
func (s *SimpleMessage) WriteEncryptedIdentity(sr []byte)
WriteEncryptedIdentity writes the encrypted static identity (public key) to this payload
func (*SimpleMessage) WriteEncryptedPayload ¶
func (s *SimpleMessage) WriteEncryptedPayload(p []byte)
WriteEncryptedPayload adds the encrypted payload
type SmolIdentity ¶ added in v0.1.5
type SmolIdentity struct {
smolcert.Certificate
}
SmolIdentity wraps a smolcert based certificate and provides the public key as curve25519 representation instead of ed25519
func (*SmolIdentity) Cert ¶ added in v0.1.5
func (s *SmolIdentity) Cert() *smolcert.Certificate
Cert returns the plain smolcert certificate
func (*SmolIdentity) PublicKey ¶ added in v0.1.5
func (s *SmolIdentity) PublicKey() []byte
PublicKey returns the curve25519 representation of the ed25519 public key of this certificate
type SmolIdentityMarshaler ¶ added in v0.1.5
type SmolIdentityMarshaler struct{}
func (SmolIdentityMarshaler) MarshalIdentity ¶ added in v0.1.5
func (s SmolIdentityMarshaler) MarshalIdentity(identity Identity) ([]byte, error)
func (SmolIdentityMarshaler) UnmarshalIdentity ¶ added in v0.1.5
func (s SmolIdentityMarshaler) UnmarshalIdentity(identityBytes []byte) (Identity, error)
type SmolIdentityVerifier ¶ added in v0.1.5
type SmolIdentityVerifier struct {
// contains filtered or unexported fields
}
SmolIdentityVerifier verifies certificates against a set of root certificates
func NewSmolIdentityVerifier ¶ added in v0.1.5
func NewSmolIdentityVerifier(rootCerts ...*smolcert.Certificate) *SmolIdentityVerifier
func (*SmolIdentityVerifier) VerifyIdentity ¶ added in v0.1.5
func (s *SmolIdentityVerifier) VerifyIdentity(id Identity) error
type WriteableHandshakeMessage ¶
type WriteableHandshakeMessage interface { WriteEPublic(e []byte) WriteEncryptedIdentity(s []byte) WriteEncryptedPayload(p []byte) }
WriteableHandshakeMessage takes data from the HandshakeState to marshal it to a custom format.