encryption

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Nov 18, 2019 License: MPL-2.0 Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrDeviceNotFound = errors.New("device not found")
	// ErrNotPairedDevice means that we received a message signed with our public key
	// but from a device that has not been paired.
	// This should not happen because the protocol forbids sending a message to
	// non-paired devices, however, in theory it is possible to receive such a message.
	ErrNotPairedDevice = errors.New("received a message from not paired device")
)
View Source
var (
	// ErrNoPayload means that there was no payload found in the received protocol message.
	ErrNoPayload = errors.New("no payload")
)

Functions

func ExtractIdentity

func ExtractIdentity(bundle *Bundle) (*ecdsa.PublicKey, error)

ExtractIdentity extracts the identity key from a given bundle

func PerformActiveDH

func PerformActiveDH(publicKey *ecdsa.PublicKey) ([]byte, *ecdsa.PublicKey, error)

PerformActiveDH performs a Diffie-Hellman exchange using a public key and a generated ephemeral key. Returns the key resulting from the DH exchange as well as the ephemeral public key.

func PerformActiveX3DH

func PerformActiveX3DH(identity []byte, signedPreKey []byte, prv *ecdsa.PrivateKey) ([]byte, *ecdsa.PublicKey, error)

PerformActiveX3DH takes someone else's bundle and calculates shared secret. Returns the shared secret and the ephemeral key used.

func PerformDH

func PerformDH(privateKey *ecies.PrivateKey, publicKey *ecies.PublicKey) ([]byte, error)

PerformDH generates a shared key given a private and a public key

func PerformPassiveX3DH

func PerformPassiveX3DH(theirIdentityKey *ecdsa.PublicKey, mySignedPreKey *ecdsa.PrivateKey, theirEphemeralKey *ecdsa.PublicKey, myPrivateKey *ecdsa.PrivateKey) ([]byte, error)

PerformPassiveX3DH handles the part of the protocol where our interlocutor used our bundle, with ID of the signedPreKey, we loaded our identity key and the correct signedPreKey and we perform X3DH

func SignBundle

func SignBundle(identity *ecdsa.PrivateKey, bundleContainer *BundleContainer) error

SignBundle signs the bundle and refreshes the timestamps

func VerifyBundle

func VerifyBundle(bundle *Bundle) error

VerifyBundle checks that a bundle is valid

Types

type Bundle

type Bundle struct {
	// Identity key
	Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
	// Installation id
	SignedPreKeys map[string]*SignedPreKey `` /* 190-byte string literal not displayed */
	// Prekey signature
	Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"`
	// When the bundle was created locally
	Timestamp            int64    `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

X3DH prekey bundle

func (*Bundle) Descriptor

func (*Bundle) Descriptor() ([]byte, []int)

func (*Bundle) GetIdentity

func (m *Bundle) GetIdentity() []byte

func (*Bundle) GetSignature

func (m *Bundle) GetSignature() []byte

func (*Bundle) GetSignedPreKeys

func (m *Bundle) GetSignedPreKeys() map[string]*SignedPreKey

func (*Bundle) GetTimestamp

func (m *Bundle) GetTimestamp() int64

func (*Bundle) ProtoMessage

func (*Bundle) ProtoMessage()

func (*Bundle) Reset

func (m *Bundle) Reset()

func (*Bundle) String

func (m *Bundle) String() string

func (*Bundle) XXX_DiscardUnknown

func (m *Bundle) XXX_DiscardUnknown()

func (*Bundle) XXX_Marshal

func (m *Bundle) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*Bundle) XXX_Merge

func (m *Bundle) XXX_Merge(src proto.Message)

func (*Bundle) XXX_Size

func (m *Bundle) XXX_Size() int

func (*Bundle) XXX_Unmarshal

func (m *Bundle) XXX_Unmarshal(b []byte) error

type BundleContainer

type BundleContainer struct {
	// X3DH prekey bundle
	Bundle *Bundle `protobuf:"bytes,1,opt,name=bundle,proto3" json:"bundle,omitempty"`
	// Private signed prekey
	PrivateSignedPreKey  []byte   `protobuf:"bytes,2,opt,name=private_signed_pre_key,json=privateSignedPreKey,proto3" json:"private_signed_pre_key,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func NewBundleContainer

func NewBundleContainer(identity *ecdsa.PrivateKey, installationID string) (*BundleContainer, error)

NewBundleContainer creates a new BundleContainer from an identity private key

func (*BundleContainer) Descriptor

func (*BundleContainer) Descriptor() ([]byte, []int)

func (*BundleContainer) GetBundle

func (m *BundleContainer) GetBundle() *Bundle

func (*BundleContainer) GetPrivateSignedPreKey

func (m *BundleContainer) GetPrivateSignedPreKey() []byte

func (*BundleContainer) ProtoMessage

func (*BundleContainer) ProtoMessage()

func (*BundleContainer) Reset

func (m *BundleContainer) Reset()

func (*BundleContainer) String

func (m *BundleContainer) String() string

func (*BundleContainer) XXX_DiscardUnknown

func (m *BundleContainer) XXX_DiscardUnknown()

func (*BundleContainer) XXX_Marshal

func (m *BundleContainer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*BundleContainer) XXX_Merge

func (m *BundleContainer) XXX_Merge(src proto.Message)

func (*BundleContainer) XXX_Size

func (m *BundleContainer) XXX_Size() int

func (*BundleContainer) XXX_Unmarshal

func (m *BundleContainer) XXX_Unmarshal(b []byte) error

type DHHeader

type DHHeader struct {
	// Compressed ephemeral public key
	Key                  []byte   `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (*DHHeader) Descriptor

func (*DHHeader) Descriptor() ([]byte, []int)

func (*DHHeader) GetKey

func (m *DHHeader) GetKey() []byte

func (*DHHeader) ProtoMessage

func (*DHHeader) ProtoMessage()

func (*DHHeader) Reset

func (m *DHHeader) Reset()

func (*DHHeader) String

func (m *DHHeader) String() string

func (*DHHeader) XXX_DiscardUnknown

func (m *DHHeader) XXX_DiscardUnknown()

func (*DHHeader) XXX_Marshal

func (m *DHHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*DHHeader) XXX_Merge

func (m *DHHeader) XXX_Merge(src proto.Message)

func (*DHHeader) XXX_Size

func (m *DHHeader) XXX_Size() int

func (*DHHeader) XXX_Unmarshal

func (m *DHHeader) XXX_Unmarshal(b []byte) error

type DRHeader

type DRHeader struct {
	// Current ratchet public key
	Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
	// Number of the message in the sending chain
	N uint32 `protobuf:"varint,2,opt,name=n,proto3" json:"n,omitempty"`
	// Length of the previous sending chain
	Pn uint32 `protobuf:"varint,3,opt,name=pn,proto3" json:"pn,omitempty"`
	// Bundle ID
	Id                   []byte   `protobuf:"bytes,4,opt,name=id,proto3" json:"id,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (*DRHeader) Descriptor

func (*DRHeader) Descriptor() ([]byte, []int)

func (*DRHeader) GetId

func (m *DRHeader) GetId() []byte

func (*DRHeader) GetKey

func (m *DRHeader) GetKey() []byte

func (*DRHeader) GetN

func (m *DRHeader) GetN() uint32

func (*DRHeader) GetPn

func (m *DRHeader) GetPn() uint32

func (*DRHeader) ProtoMessage

func (*DRHeader) ProtoMessage()

func (*DRHeader) Reset

func (m *DRHeader) Reset()

func (*DRHeader) String

func (m *DRHeader) String() string

func (*DRHeader) XXX_DiscardUnknown

func (m *DRHeader) XXX_DiscardUnknown()

func (*DRHeader) XXX_Marshal

func (m *DRHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*DRHeader) XXX_Merge

func (m *DRHeader) XXX_Merge(src proto.Message)

func (*DRHeader) XXX_Size

func (m *DRHeader) XXX_Size() int

func (*DRHeader) XXX_Unmarshal

func (m *DRHeader) XXX_Unmarshal(b []byte) error

type DirectMessageProtocol

type DirectMessageProtocol struct {
	X3DHHeader *X3DHHeader `protobuf:"bytes,1,opt,name=X3DH_header,json=X3DHHeader,proto3" json:"X3DH_header,omitempty"`
	DRHeader   *DRHeader   `protobuf:"bytes,2,opt,name=DR_header,json=DRHeader,proto3" json:"DR_header,omitempty"`
	DHHeader   *DHHeader   `protobuf:"bytes,101,opt,name=DH_header,json=DHHeader,proto3" json:"DH_header,omitempty"`
	// Encrypted payload
	Payload              []byte   `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

Direct message value

func (*DirectMessageProtocol) Descriptor

func (*DirectMessageProtocol) Descriptor() ([]byte, []int)

func (*DirectMessageProtocol) GetDHHeader

func (m *DirectMessageProtocol) GetDHHeader() *DHHeader

func (*DirectMessageProtocol) GetDRHeader

func (m *DirectMessageProtocol) GetDRHeader() *DRHeader

func (*DirectMessageProtocol) GetPayload

func (m *DirectMessageProtocol) GetPayload() []byte

func (*DirectMessageProtocol) GetX3DHHeader

func (m *DirectMessageProtocol) GetX3DHHeader() *X3DHHeader

func (*DirectMessageProtocol) ProtoMessage

func (*DirectMessageProtocol) ProtoMessage()

func (*DirectMessageProtocol) Reset

func (m *DirectMessageProtocol) Reset()

func (*DirectMessageProtocol) String

func (m *DirectMessageProtocol) String() string

func (*DirectMessageProtocol) XXX_DiscardUnknown

func (m *DirectMessageProtocol) XXX_DiscardUnknown()

func (*DirectMessageProtocol) XXX_Marshal

func (m *DirectMessageProtocol) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*DirectMessageProtocol) XXX_Merge

func (m *DirectMessageProtocol) XXX_Merge(src proto.Message)

func (*DirectMessageProtocol) XXX_Size

func (m *DirectMessageProtocol) XXX_Size() int

func (*DirectMessageProtocol) XXX_Unmarshal

func (m *DirectMessageProtocol) XXX_Unmarshal(b []byte) error

type PartitionTopicMode

type PartitionTopicMode int
const (
	PartitionTopicNoSupport PartitionTopicMode = iota
	PartitionTopicV1
)

type Protocol

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

func New

func New(
	db *sql.DB,
	installationID string,
	addedBundlesHandler func([]*multidevice.Installation),
	onNewSharedSecretHandler func([]*sharedsecret.Secret),
	onSendContactCodeHandler func(*ProtocolMessageSpec),
	logger *zap.Logger,
) *Protocol

New creates a new ProtocolService instance

func NewWithEncryptorConfig

func NewWithEncryptorConfig(
	db *sql.DB,
	installationID string,
	encryptorConfig encryptorConfig,
	addedBundlesHandler func([]*multidevice.Installation),
	onNewSharedSecretHandler func([]*sharedsecret.Secret),
	onSendContactCodeHandler func(*ProtocolMessageSpec),
	logger *zap.Logger,
) *Protocol

DB and migrations are shared between encryption package and its sub-packages.

func (*Protocol) BuildBundleAdvertiseMessage

func (p *Protocol) BuildBundleAdvertiseMessage(myIdentityKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey) (*ProtocolMessageSpec, error)

func (*Protocol) BuildDHMessage

func (p *Protocol) BuildDHMessage(myIdentityKey *ecdsa.PrivateKey, destination *ecdsa.PublicKey, payload []byte) (*ProtocolMessageSpec, error)

BuildDHMessage builds a message with DH encryption so that it can be decrypted by any other device.

func (*Protocol) BuildDirectMessage

func (p *Protocol) BuildDirectMessage(myIdentityKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, payload []byte) (*ProtocolMessageSpec, error)

BuildDirectMessage returns a 1:1 chat message and optionally a negotiated topic given the user identity private key, the recipient's public key, and a payload

func (*Protocol) BuildPublicMessage

func (p *Protocol) BuildPublicMessage(myIdentityKey *ecdsa.PrivateKey, payload []byte) (*ProtocolMessageSpec, error)

BuildPublicMessage marshals a public chat message given the user identity private key and a payload

func (*Protocol) ConfirmBundleAdvertisement

func (p *Protocol) ConfirmBundleAdvertisement(publicKey *ecdsa.PublicKey, time int64)

func (*Protocol) ConfirmMessageProcessed

func (p *Protocol) ConfirmMessageProcessed(messageID []byte) error

ConfirmMessageProcessed confirms and deletes message keys for the given messages

func (*Protocol) DisableInstallation

func (p *Protocol) DisableInstallation(myIdentityKey *ecdsa.PublicKey, installationID string) error

DisableInstallation disables an installation for multi-device sync.

func (*Protocol) EnableInstallation

func (p *Protocol) EnableInstallation(myIdentityKey *ecdsa.PublicKey, installationID string) error

EnableInstallation enables an installation for multi-device sync.

func (*Protocol) GetBundle

func (p *Protocol) GetBundle(myIdentityKey *ecdsa.PrivateKey) (*Bundle, error)

GetBundle retrieves or creates a X3DH bundle, given a private identity key.

func (*Protocol) GetOurInstallations

func (p *Protocol) GetOurInstallations(myIdentityKey *ecdsa.PublicKey) ([]*multidevice.Installation, error)

GetOurInstallations returns all the installations available given an identity

func (*Protocol) GetPublicBundle

func (p *Protocol) GetPublicBundle(theirIdentityKey *ecdsa.PublicKey) (*Bundle, error)

GetPublicBundle retrieves a public bundle given an identity

func (*Protocol) HandleMessage

func (p *Protocol) HandleMessage(
	myIdentityKey *ecdsa.PrivateKey,
	theirPublicKey *ecdsa.PublicKey,
	protocolMessage *ProtocolMessage,
	messageID []byte,
) ([]byte, error)

HandleMessage unmarshals a message and processes it, decrypting it if it is a 1:1 message.

func (*Protocol) ProcessPublicBundle

func (p *Protocol) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, bundle *Bundle) ([]*multidevice.Installation, error)

ProcessPublicBundle processes a received X3DH bundle.

func (*Protocol) SetInstallationMetadata

func (p *Protocol) SetInstallationMetadata(myIdentityKey *ecdsa.PublicKey, installationID string, data *multidevice.InstallationMetadata) error

SetInstallationMetadata sets the metadata for our own installation

func (*Protocol) ShouldAdvertiseBundle

func (p *Protocol) ShouldAdvertiseBundle(publicKey *ecdsa.PublicKey, time int64) (bool, error)

func (*Protocol) Start

func (p *Protocol) Start(myIdentity *ecdsa.PrivateKey) error

type ProtocolMessage

type ProtocolMessage struct {
	// The device id of the sender
	InstallationId string `protobuf:"bytes,2,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
	// List of bundles
	Bundles []*Bundle `protobuf:"bytes,3,rep,name=bundles,proto3" json:"bundles,omitempty"`
	// One to one message, encrypted, indexed by installation_id
	DirectMessage map[string]*DirectMessageProtocol `` /* 190-byte string literal not displayed */
	// Public chats, not encrypted
	PublicMessage        []byte   `protobuf:"bytes,102,opt,name=public_message,json=publicMessage,proto3" json:"public_message,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

Top-level protocol message

func (*ProtocolMessage) Descriptor

func (*ProtocolMessage) Descriptor() ([]byte, []int)

func (*ProtocolMessage) GetBundles

func (m *ProtocolMessage) GetBundles() []*Bundle

func (*ProtocolMessage) GetDirectMessage

func (m *ProtocolMessage) GetDirectMessage() map[string]*DirectMessageProtocol

func (*ProtocolMessage) GetInstallationId

func (m *ProtocolMessage) GetInstallationId() string

func (*ProtocolMessage) GetPublicMessage

func (m *ProtocolMessage) GetPublicMessage() []byte

func (*ProtocolMessage) ProtoMessage

func (*ProtocolMessage) ProtoMessage()

func (*ProtocolMessage) Reset

func (m *ProtocolMessage) Reset()

func (*ProtocolMessage) String

func (m *ProtocolMessage) String() string

func (*ProtocolMessage) XXX_DiscardUnknown

func (m *ProtocolMessage) XXX_DiscardUnknown()

func (*ProtocolMessage) XXX_Marshal

func (m *ProtocolMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*ProtocolMessage) XXX_Merge

func (m *ProtocolMessage) XXX_Merge(src proto.Message)

func (*ProtocolMessage) XXX_Size

func (m *ProtocolMessage) XXX_Size() int

func (*ProtocolMessage) XXX_Unmarshal

func (m *ProtocolMessage) XXX_Unmarshal(b []byte) error

type ProtocolMessageSpec

type ProtocolMessageSpec struct {
	Message *ProtocolMessage
	// Installations is the targeted devices
	Installations []*multidevice.Installation
	// SharedSecret is a shared secret established among the installations
	SharedSecret []byte
	// Public means that the spec contains a public wrapped message
	Public bool
}

func (*ProtocolMessageSpec) MinVersion

func (p *ProtocolMessageSpec) MinVersion() uint32

func (*ProtocolMessageSpec) PartitionedTopicMode

func (p *ProtocolMessageSpec) PartitionedTopicMode() PartitionTopicMode

type RatchetInfo

type RatchetInfo struct {
	ID             []byte
	Sk             []byte
	PrivateKey     []byte
	PublicKey      []byte
	Identity       []byte
	BundleID       []byte
	EphemeralKey   []byte
	InstallationID string
}

RatchetInfo holds the current ratchet state.

type SignedPreKey

type SignedPreKey struct {
	SignedPreKey         []byte   `protobuf:"bytes,1,opt,name=signed_pre_key,json=signedPreKey,proto3" json:"signed_pre_key,omitempty"`
	Version              uint32   `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
	ProtocolVersion      uint32   `protobuf:"varint,3,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (*SignedPreKey) Descriptor

func (*SignedPreKey) Descriptor() ([]byte, []int)

func (*SignedPreKey) GetProtocolVersion

func (m *SignedPreKey) GetProtocolVersion() uint32

func (*SignedPreKey) GetSignedPreKey

func (m *SignedPreKey) GetSignedPreKey() []byte

func (*SignedPreKey) GetVersion

func (m *SignedPreKey) GetVersion() uint32

func (*SignedPreKey) ProtoMessage

func (*SignedPreKey) ProtoMessage()

func (*SignedPreKey) Reset

func (m *SignedPreKey) Reset()

func (*SignedPreKey) String

func (m *SignedPreKey) String() string

func (*SignedPreKey) XXX_DiscardUnknown

func (m *SignedPreKey) XXX_DiscardUnknown()

func (*SignedPreKey) XXX_Marshal

func (m *SignedPreKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*SignedPreKey) XXX_Merge

func (m *SignedPreKey) XXX_Merge(src proto.Message)

func (*SignedPreKey) XXX_Size

func (m *SignedPreKey) XXX_Size() int

func (*SignedPreKey) XXX_Unmarshal

func (m *SignedPreKey) XXX_Unmarshal(b []byte) error

type X3DHHeader

type X3DHHeader struct {
	// Ephemeral key used
	Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
	// Used bundle's signed prekey
	Id                   []byte   `protobuf:"bytes,4,opt,name=id,proto3" json:"id,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (*X3DHHeader) Descriptor

func (*X3DHHeader) Descriptor() ([]byte, []int)

func (*X3DHHeader) GetId

func (m *X3DHHeader) GetId() []byte

func (*X3DHHeader) GetKey

func (m *X3DHHeader) GetKey() []byte

func (*X3DHHeader) ProtoMessage

func (*X3DHHeader) ProtoMessage()

func (*X3DHHeader) Reset

func (m *X3DHHeader) Reset()

func (*X3DHHeader) String

func (m *X3DHHeader) String() string

func (*X3DHHeader) XXX_DiscardUnknown

func (m *X3DHHeader) XXX_DiscardUnknown()

func (*X3DHHeader) XXX_Marshal

func (m *X3DHHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*X3DHHeader) XXX_Merge

func (m *X3DHHeader) XXX_Merge(src proto.Message)

func (*X3DHHeader) XXX_Size

func (m *X3DHHeader) XXX_Size() int

func (*X3DHHeader) XXX_Unmarshal

func (m *X3DHHeader) XXX_Unmarshal(b []byte) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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