Documentation ¶
Index ¶
- Constants
- Variables
- func CommitPublicKey(h func() hash.Hash, publicKey []byte, r []byte) []byte
- func IsProtocolIDSupported(protocolID byte) bool
- func PKCS7_Pad(payload []byte, paddingSize int) ([]byte, error)
- func PKCS7_Unpad(payload []byte, paddingSize int) ([]byte, error)
- type CipherState
- type DHKey
- type Handshake
- func NewHandshake(hsPattern HandshakePattern, staticKey Keypair, ephemeralKey Keypair, ...) (*Handshake, error)
- func NewHandshake_K1K1_25519_ChaChaPoly_SHA256(myStaticKeypair Keypair, initiator bool, peerStaticKey []byte, prologue []byte) (*Handshake, error)
- func NewHandshake_WakuPairing_25519_ChaChaPoly_SHA256(myStaticKeypair Keypair, myEphemeralKeypair Keypair, initiator bool, ...) (*Handshake, error)
- func NewHandshake_XK1_25519_ChaChaPoly_SHA256(myStaticKeypair Keypair, initiator bool, responderStaticKey []byte, ...) (*Handshake, error)
- func NewHandshake_XX_25519_ChaChaPoly_SHA256(staticKeypair Keypair, initiator bool, prologue []byte) (*Handshake, error)
- func NewHandshake_XXpsk0_25519_ChaChaPoly_SHA256(staticKeypair Keypair, initiator bool, presharedKey []byte, prologue []byte) (*Handshake, error)
- func (h *Handshake) Authcode() (string, error)
- func (h *Handshake) Equals(b *Handshake) bool
- func (h *Handshake) FinalizeHandshake() (*HandshakeResult, error)
- func (h *Handshake) H() []byte
- func (h *Handshake) IsComplete() bool
- func (h *Handshake) LocalEphemeralKeypair() Keypair
- func (h *Handshake) RemoteEphemeralPublicKey() []byte
- func (h *Handshake) RemoteStaticPublicKey() []byte
- func (h *Handshake) Step(readPayloadV2 *PayloadV2, transportMessage []byte, ...) (*HandshakeStepResult, error)
- func (hs *Handshake) ToMessageNametag() (MessageNametag, error)
- type HandshakePattern
- type HandshakeResult
- type HandshakeState
- type HandshakeStepResult
- type Keypair
- type MessageDirection
- type MessageNametag
- type MessageNametagBuffer
- type MessagePattern
- type NoisePublicKey
- type NoiseTokens
- type PayloadV2
- type PreMessagePattern
- type SerializedNoisePublicKey
- type SymmetricState
Constants ¶
const ChaChaPoly = 30
const MaxUint8 = 1<<8 - 1
const MessageNametagBufferSize = 50
const MessageNametagLength = 16
const NoisePaddingBlockSize = 248
The padding blocksize of a transport message
const Noise_K1K1_25519_ChaChaPoly_SHA256 = 10
Supported Protocol ID for PayloadV2 objects Protocol IDs are defined according to https://rfc.vac.dev/spec/35/#specification
const Noise_WakuPairing_25519_ChaChaPoly_SHA256 = 14
const Noise_XK1_25519_ChaChaPoly_SHA256 = 11
const Noise_XX_25519_ChaChaPoly_SHA256 = 12
const Noise_XXpsk0_25519_ChaChaPoly_SHA256 = 13
const None = 0
Variables ¶
var ( ErrNametagNotFound = errors.New("message nametag not found in buffer") ErrNametagNotExpected = errors.New("message nametag is present in buffer but is not the next expected nametag. One or more messages were probably lost") )
var DH25519 = dh25519{}
var EmptyPreMessage = []PreMessagePattern{}
var ErrHandshakeComplete = errors.New("handshake complete")
var ErrUnexpectedMessageNametag = errors.New("the message nametag of the read message doesn't match the expected one")
var K1K1 = NewHandshakePattern( Noise_K1K1_25519_ChaChaPoly_SHA256, "Noise_K1K1_25519_ChaChaPoly_SHA256", sha256.New, chacha20poly1305.New, 16, DH25519, []PreMessagePattern{ NewPreMessagePattern(Right, []NoiseTokens{S}), NewPreMessagePattern(Left, []NoiseTokens{S}), }, []MessagePattern{ NewMessagePattern(Right, []NoiseTokens{E}), NewMessagePattern(Left, []NoiseTokens{E, EE, ES}), NewMessagePattern(Right, []NoiseTokens{SE}), }, )
var WakuPairing = NewHandshakePattern( Noise_WakuPairing_25519_ChaChaPoly_SHA256, "Noise_WakuPairing_25519_ChaChaPoly_SHA256", sha256.New, chacha20poly1305.New, 16, DH25519, []PreMessagePattern{ NewPreMessagePattern(Left, []NoiseTokens{E}), }, []MessagePattern{ NewMessagePattern(Right, []NoiseTokens{E, EE}), NewMessagePattern(Left, []NoiseTokens{S, ES}), NewMessagePattern(Right, []NoiseTokens{S, SE, SS}), }, )
var XK1 = NewHandshakePattern( Noise_XK1_25519_ChaChaPoly_SHA256, "Noise_XK1_25519_ChaChaPoly_SHA256", sha256.New, chacha20poly1305.New, 16, DH25519, []PreMessagePattern{ NewPreMessagePattern(Left, []NoiseTokens{S}), }, []MessagePattern{ NewMessagePattern(Right, []NoiseTokens{E}), NewMessagePattern(Left, []NoiseTokens{E, EE, ES}), NewMessagePattern(Right, []NoiseTokens{S, SE}), }, )
var XX = NewHandshakePattern( Noise_XX_25519_ChaChaPoly_SHA256, "Noise_XX_25519_ChaChaPoly_SHA256", sha256.New, chacha20poly1305.New, 16, DH25519, EmptyPreMessage, []MessagePattern{ NewMessagePattern(Right, []NoiseTokens{E}), NewMessagePattern(Left, []NoiseTokens{E, EE, S, ES}), NewMessagePattern(Right, []NoiseTokens{S, SE}), }, )
var XXpsk0 = NewHandshakePattern( Noise_XXpsk0_25519_ChaChaPoly_SHA256, "Noise_XXpsk0_25519_ChaChaPoly_SHA256", sha256.New, chacha20poly1305.New, 16, DH25519, EmptyPreMessage, []MessagePattern{ NewMessagePattern(Right, []NoiseTokens{PSK, E}), NewMessagePattern(Left, []NoiseTokens{E, EE, S, ES}), NewMessagePattern(Right, []NoiseTokens{S, SE}), }, )
Functions ¶
func CommitPublicKey ¶
CommitPublicKey commits a public key pk for randomness r as H(pk || s)
func IsProtocolIDSupported ¶
func PKCS7_Pad ¶
PKCS7_Pad pads a payload according to PKCS#7 as per RFC 5652 https://datatracker.ietf.org/doc/html/rfc5652#section-6.3
func PKCS7_Unpad ¶
PKCS7_Unpad unpads a payload according to PKCS#7 as per RFC 5652 https://datatracker.ietf.org/doc/html/rfc5652#section-6.3
Types ¶
type CipherState ¶
type CipherState struct {
// contains filtered or unexported fields
}
The Cipher State as in https://noiseprotocol.org/noise.html#the-cipherstate-object Contains an encryption key k and a nonce n (used in Noise as a counter)
func NewCipherState ¶
func (*CipherState) Equals ¶
func (c *CipherState) Equals(b *CipherState) bool
type Handshake ¶
type Handshake struct {
// contains filtered or unexported fields
}
func NewHandshake ¶
func NewHandshake(hsPattern HandshakePattern, staticKey Keypair, ephemeralKey Keypair, prologue []byte, psk []byte, preMessagePKs []*NoisePublicKey, initiator bool) (*Handshake, error)
func NewHandshake_K1K1_25519_ChaChaPoly_SHA256 ¶
func NewHandshake_K1K1_25519_ChaChaPoly_SHA256(myStaticKeypair Keypair, initiator bool, peerStaticKey []byte, prologue []byte) (*Handshake, error)
NewHandshake_K1K1_25519_ChaChaPoly_SHA256 creates a handshake where both initiator and recever know each other handshake. Only ephemeral keys are exchanged. This handshake is useful in case the initiator needs to instantiate a new separate encrypted communication channel with the responder
func NewHandshake_WakuPairing_25519_ChaChaPoly_SHA256 ¶
func NewHandshake_WakuPairing_25519_ChaChaPoly_SHA256(myStaticKeypair Keypair, myEphemeralKeypair Keypair, initiator bool, prologue []byte, receiverEphemeralKey []byte) (*Handshake, error)
NewHandshake_WakuPairing_25519_ChaChaPoly_SHA256
func NewHandshake_XK1_25519_ChaChaPoly_SHA256 ¶
func NewHandshake_XK1_25519_ChaChaPoly_SHA256(myStaticKeypair Keypair, initiator bool, responderStaticKey []byte, prologue []byte) (*Handshake, error)
NewHandshake_XK1_25519_ChaChaPoly_SHA256 creates a handshake where the initiator knows the responder public static key. Within this handshake, the initiator and responder reciprocally authenticate their static keys using ephemeral keys. We note that while the responder's static key is assumed to be known to Alice (and hence is not transmitted), The initiator static key is sent to the responder encrypted with a key derived from both parties ephemeral keys and the responder's static key.
func NewHandshake_XX_25519_ChaChaPoly_SHA256 ¶
func NewHandshake_XX_25519_ChaChaPoly_SHA256(staticKeypair Keypair, initiator bool, prologue []byte) (*Handshake, error)
NewHandshake_XX_25519_ChaChaPoly_SHA256 creates a handshake where the initiator and responder are not aware of each other static keys
func NewHandshake_XXpsk0_25519_ChaChaPoly_SHA256 ¶
func NewHandshake_XXpsk0_25519_ChaChaPoly_SHA256(staticKeypair Keypair, initiator bool, presharedKey []byte, prologue []byte) (*Handshake, error)
NewHandshake_XXpsk0_25519_ChaChaPoly_SHA256 creates a handshake where the initiator and responder are not aware of each other static keys and use a preshared secret to strengthen their mutual authentication
func (*Handshake) Authcode ¶
Generates an 8 decimal digits authorization code using HKDF and the handshake state
func (*Handshake) FinalizeHandshake ¶
func (h *Handshake) FinalizeHandshake() (*HandshakeResult, error)
Finalizes the handshake by calling Split and assigning the proper Cipher States to users
func (*Handshake) IsComplete ¶
HandshakeComplete indicates whether the handshake process is complete or not
func (*Handshake) LocalEphemeralKeypair ¶ added in v0.0.2
func (*Handshake) RemoteEphemeralPublicKey ¶ added in v0.0.2
func (*Handshake) RemoteStaticPublicKey ¶ added in v0.0.2
func (*Handshake) Step ¶
func (h *Handshake) Step(readPayloadV2 *PayloadV2, transportMessage []byte, messageNametag MessageNametag) (*HandshakeStepResult, error)
Advances 1 step in handshake
Each user in a handshake alternates writing and reading of handshake messages.
If the user is writing the handshake message, the transport message (if not empty) and eventually a non-empty message nametag has to be passed to transportMessage and messageNametag and readPayloadV2 can be left to its default value It the user is reading the handshake message, the read payload v2 has to be passed to readPayloadV2 and the transportMessage can be left to its default values. Decryption is skipped if the PayloadV2 read doesn't have a message nametag equal to messageNametag (empty input nametags are converted to all-0 MessageNametagLength bytes arrays)
func (*Handshake) ToMessageNametag ¶
func (hs *Handshake) ToMessageNametag() (MessageNametag, error)
Uses the cryptographic information stored in the input handshake state to generate a random message nametag In current implementation the messageNametag = HKDF(handshake hash value), but other derivation mechanisms can be implemented
type HandshakePattern ¶
type HandshakePattern struct {
// contains filtered or unexported fields
}
The handshake pattern object. It stores the handshake protocol name, the handshake pre message patterns and the handshake message patterns
func GetHandshakePattern ¶
func GetHandshakePattern(protocol byte) (HandshakePattern, error)
func NewHandshakePattern ¶
func NewHandshakePattern(protocolID byte, name string, hashFn func() hash.Hash, cipherFn func([]byte) (cipher.AEAD, error), tagSize int, dhKey DHKey, preMessagePatterns []PreMessagePattern, messagePatterns []MessagePattern) HandshakePattern
func (HandshakePattern) Equals ¶
func (p HandshakePattern) Equals(b HandshakePattern) bool
type HandshakeResult ¶
type HandshakeResult struct {
// contains filtered or unexported fields
}
When a handshake is complete, the HandshakeResult will contain the two Cipher States used to encrypt/decrypt outbound/inbound messages The recipient static key rs and handshake hash values h are stored to address some possible future applications (channel-binding, session management, etc.). However, are not required by Noise specifications and are thus optional
func NewHandshakeResult ¶
func NewHandshakeResult(csOutbound *CipherState, csInbound *CipherState) *HandshakeResult
func (*HandshakeResult) ReadMessage ¶
func (hr *HandshakeResult) ReadMessage(readPayload2 *PayloadV2, inboundMessageNametagBuffer *MessageNametagBuffer) ([]byte, error)
Reads an encrypted message using the proper Cipher State Decryption is attempted only if the input PayloadV2 has a messageNametag equal to the one expected
func (*HandshakeResult) WriteMessage ¶
func (hr *HandshakeResult) WriteMessage(transportMessage []byte, outboundMessageNametagBuffer *MessageNametagBuffer) (*PayloadV2, error)
Writes an encrypted message using the proper Cipher State
type HandshakeState ¶
type HandshakeState struct {
// contains filtered or unexported fields
}
The Handshake State as in https://noiseprotocol.org/noise.html#the-handshakestate-object Contains
- the local and remote ephemeral/static keys e,s,re,rs (if any)
- the initiator flag (true if the user creating the state is the handshake initiator, false otherwise)
- the handshakePattern (containing the handshake protocol name, and (pre)message patterns)
This object is further extended from specifications by storing:
- a message pattern index msgPatternIdx indicating the next handshake message pattern to process
- the user's preshared psk, if any
func NewHandshakeState ¶
func NewHandshakeState(hsPattern HandshakePattern, psk []byte) *HandshakeState
func (*HandshakeState) Equals ¶
func (h *HandshakeState) Equals(b HandshakeState) bool
func (*HandshakeState) MessageNametag ¶
func (h *HandshakeState) MessageNametag() MessageNametag
Uses the cryptographic information stored in the input handshake state to generate a random message nametag In current implementation the messageNametag = HKDF(handshake hash value), but other derivation mechanisms can be implemented
type HandshakeStepResult ¶
HandshakeStepResult stores the intermediate result of processing messages patterns
type MessageDirection ¶
type MessageDirection string
The direction of a (pre)message pattern in canonical form (i.e. Alice-initiated form) as in http://www.noiseprotocol.org/noise.html#alice-and-bob
const ( Right MessageDirection = "->" Left MessageDirection = "<-" )
type MessageNametag ¶
type MessageNametag [MessageNametagLength]byte
func BytesToMessageNametag ¶
func BytesToMessageNametag(input []byte) MessageNametag
Converts a sequence or array (arbitrary size) to a MessageNametag
func (MessageNametag) String ¶
func (t MessageNametag) String() string
type MessageNametagBuffer ¶
type MessageNametagBuffer struct {
// contains filtered or unexported fields
}
func NewMessageNametagBuffer ¶
func NewMessageNametagBuffer(secret []byte) *MessageNametagBuffer
func (*MessageNametagBuffer) CheckNametag ¶
func (m *MessageNametagBuffer) CheckNametag(messageNametag MessageNametag) error
Checks if the input messageNametag is contained in the input MessageNametagBuffer
func (*MessageNametagBuffer) Delete ¶
func (m *MessageNametagBuffer) Delete(n int)
Deletes the first n elements in buffer and appends n new ones
func (*MessageNametagBuffer) Init ¶
func (m *MessageNametagBuffer) Init()
Initializes the empty Message nametag buffer. The n-th nametag is equal to HKDF( secret || n )
func (*MessageNametagBuffer) Pop ¶
func (m *MessageNametagBuffer) Pop() MessageNametag
type MessagePattern ¶
type MessagePattern struct {
// contains filtered or unexported fields
}
The message pattern consisting of a message direction and some Noise tokens All Noise tokens are allowed
func NewMessagePattern ¶
func NewMessagePattern(direction MessageDirection, tokens []NoiseTokens) MessagePattern
func (MessagePattern) Equals ¶
func (p MessagePattern) Equals(b MessagePattern) bool
type NoisePublicKey ¶
A Noise public key is a public key exchanged during Noise handshakes (no private part) This follows https://rfc.vac.dev/spec/35/#public-keys-serialization pk contains the X coordinate of the public key, if unencrypted (this implies flag = 0) or the encryption of the X coordinate concatenated with the authorization tag, if encrypted (this implies flag = 1) Note: besides encryption, flag can be used to distinguish among multiple supported Elliptic Curves
func NewNoisePublicKey ¶
func NewNoisePublicKey(flag byte, public []byte) *NoisePublicKey
func (*NoisePublicKey) Decrypt ¶
func (pk *NoisePublicKey) Decrypt(state *CipherState) error
Decrypts decrypts a Noise public key using a Cipher State
func (*NoisePublicKey) Encrypt ¶
func (pk *NoisePublicKey) Encrypt(state *CipherState) error
Encrypt encrypts a Noise public key using a Cipher State
func (*NoisePublicKey) Equals ¶
func (pk *NoisePublicKey) Equals(pk2 *NoisePublicKey) bool
Equals checks equality between two Noise public keys
func (*NoisePublicKey) Serialize ¶
func (pk *NoisePublicKey) Serialize() SerializedNoisePublicKey
Serialize converts a Noise public key to a stream of bytes as in https://rfc.vac.dev/spec/35/#public-keys-serialization
type NoiseTokens ¶
type NoiseTokens string
The Noise tokens appearing in Noise (pre)message patterns as in http://www.noiseprotocol.org/noise.html#handshake-pattern-basics
const ( E NoiseTokens = "e" S NoiseTokens = "s" ES NoiseTokens = "es" EE NoiseTokens = "ee" SE NoiseTokens = "se" SS NoiseTokens = "ss" PSK NoiseTokens = "psk" )
type PayloadV2 ¶
type PayloadV2 struct { ProtocolId byte HandshakeMessage []*NoisePublicKey TransportMessage []byte MessageNametag MessageNametag }
PayloadV2 defines an object for Waku payloads with version 2 as in https://rfc.vac.dev/spec/35/#public-keys-serialization It contains a protocol ID field, the handshake message (for Noise handshakes) and a transport message (for Noise handshakes and ChaChaPoly encryptions)
func DeserializePayloadV2 ¶
Deserializes a byte sequence to a PayloadV2 object according to https://rfc.vac.dev/spec/35/. The input serialized payload concatenates the output PayloadV2 object fields as payload = ( protocolId || serializedHandshakeMessageLen || serializedHandshakeMessage || transportMessageLen || transportMessage)
func (*PayloadV2) Serialize ¶
Serializes a PayloadV2 object to a byte sequences according to https://rfc.vac.dev/spec/35/ The output serialized payload concatenates the input PayloadV2 object fields as payload = ( protocolId || serializedHandshakeMessageLen || serializedHandshakeMessage || transportMessageLen || transportMessage) The output can be then passed to the payload field of a WakuMessage https://rfc.vac.dev/spec/14/
type PreMessagePattern ¶
type PreMessagePattern struct {
// contains filtered or unexported fields
}
The pre message pattern consisting of a message direction and some Noise tokens, if any. (if non empty, only tokens e and s are allowed: http://www.noiseprotocol.org/noise.html#handshake-pattern-basics)
func NewPreMessagePattern ¶
func NewPreMessagePattern(direction MessageDirection, tokens []NoiseTokens) PreMessagePattern
func (PreMessagePattern) Equals ¶
func (p PreMessagePattern) Equals(b PreMessagePattern) bool
type SerializedNoisePublicKey ¶
type SerializedNoisePublicKey []byte
func (SerializedNoisePublicKey) Unserialize ¶
func (s SerializedNoisePublicKey) Unserialize() (*NoisePublicKey, error)
Unserialize converts a serialized Noise public key to a NoisePublicKey object as in https://rfc.vac.dev/spec/35/#public-keys-serialization
type SymmetricState ¶
type SymmetricState struct {
// contains filtered or unexported fields
}
The Symmetric State as in https://noiseprotocol.org/noise.html#the-symmetricstate-object Contains a Cipher State cs, the chaining key ck and the handshake hash value h
func NewSymmetricState ¶
func NewSymmetricState(hsPattern HandshakePattern) *SymmetricState
func (*SymmetricState) Equals ¶
func (s *SymmetricState) Equals(b *SymmetricState) bool