diff options
author | Wim <wim@42.be> | 2022-01-31 00:27:37 +0100 |
---|---|---|
committer | Wim <wim@42.be> | 2022-03-20 14:57:48 +0100 |
commit | e3cafeaf9292f67459ff1d186f68283bfaedf2ae (patch) | |
tree | b69c39620aa91dba695b3b935c6651c0fb37ce75 /vendor/go.mau.fi/libsignal/ratchet | |
parent | e7b193788a56ee7cdb02a87a9db0ad6724ef66d5 (diff) | |
download | matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.gz matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.bz2 matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.zip |
Add dependencies/vendor (whatsapp)
Diffstat (limited to 'vendor/go.mau.fi/libsignal/ratchet')
-rw-r--r-- | vendor/go.mau.fi/libsignal/ratchet/Ratchet.go | 197 | ||||
-rw-r--r-- | vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go | 106 | ||||
-rw-r--r-- | vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go | 106 | ||||
-rw-r--r-- | vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go | 18 |
4 files changed, 427 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/libsignal/ratchet/Ratchet.go b/vendor/go.mau.fi/libsignal/ratchet/Ratchet.go new file mode 100644 index 00000000..df25beb3 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/ratchet/Ratchet.go @@ -0,0 +1,197 @@ +// Package ratchet provides the methods necessary to establish a new double +// ratchet session. +package ratchet + +import ( + "encoding/base64" + "encoding/binary" + + "go.mau.fi/libsignal/ecc" + "go.mau.fi/libsignal/kdf" + "go.mau.fi/libsignal/keys/chain" + "go.mau.fi/libsignal/keys/root" + "go.mau.fi/libsignal/keys/session" +) + +var b64 = base64.StdEncoding.EncodeToString + +func genDiscontinuity() [32]byte { + var discontinuity [32]byte + for i := range discontinuity { + discontinuity[i] = 0xFF + } + return discontinuity +} + +// CalculateSenderSession calculates the key agreement for a recipient. This +// should be used when we are trying to send a message to someone for the +// first time. +func CalculateSenderSession(parameters *SenderParameters) (*session.KeyPair, error) { + var secret [32]byte + var publicKey [32]byte + var privateKey [32]byte + masterSecret := []byte{} // Create a master shared secret that is 5 different 32-byte values + discontinuity := genDiscontinuity() + masterSecret = append(masterSecret, discontinuity[:]...) + + // Calculate the agreement using their signed prekey and our identity key. + publicKey = parameters.TheirSignedPreKey().PublicKey() + privateKey = parameters.OurIdentityKey().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + // Calculate the agreement using their identity key and our base key. + publicKey = parameters.TheirIdentityKey().PublicKey().PublicKey() + privateKey = parameters.OurBaseKey().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + // Calculate the agreement using their signed prekey and our base key. + publicKey = parameters.TheirSignedPreKey().PublicKey() + privateKey = parameters.OurBaseKey().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + // If they have a one-time prekey, use it to calculate the shared secret with their + // one time key and our base key. + if parameters.TheirOneTimePreKey() != nil { + publicKey = parameters.TheirOneTimePreKey().PublicKey() + privateKey = parameters.OurBaseKey().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + } + + // Derive the root and chain keys based on the master secret. + derivedKeysBytes, err := kdf.DeriveSecrets(masterSecret, nil, []byte("WhisperText"), root.DerivedSecretsSize) + if err != nil { + return nil, err + } + derivedKeys := session.NewDerivedSecrets(derivedKeysBytes) + chainKey := chain.NewKey(kdf.DeriveSecrets, derivedKeys.ChainKey(), 0) + rootKey := root.NewKey(kdf.DeriveSecrets, derivedKeys.RootKey()) + + // Add the root and chain keys to a structure that will hold both keys. + sessionKeys := session.NewKeyPair(rootKey, chainKey) + + return sessionKeys, nil +} + +// CalculateReceiverSession calculates the key agreement for a sender. This should +// be used when we are receiving a message from someone for the first time. +func CalculateReceiverSession(parameters *ReceiverParameters) (*session.KeyPair, error) { + var secret [32]byte + var publicKey [32]byte + var privateKey [32]byte + masterSecret := []byte{} // Create a master shared secret that is 5 different 32-byte values + + discontinuity := genDiscontinuity() + masterSecret = append(masterSecret, discontinuity[:]...) + + // Calculate the agreement using their identity key and our signed pre key. + publicKey = parameters.TheirIdentityKey().PublicKey().PublicKey() + privateKey = parameters.OurSignedPreKey().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + // Calculate the agreement using their base key and our identity key. + publicKey = parameters.TheirBaseKey().PublicKey() + privateKey = parameters.OurIdentityKeyPair().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + // Calculate the agreement using their base key and our signed prekey. + publicKey = parameters.TheirBaseKey().PublicKey() + privateKey = parameters.OurSignedPreKey().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + // If we had a one-time prekey, use it to calculate the shared secret with our + // one time key and their base key. + if parameters.OurOneTimePreKey() != nil { + publicKey = parameters.TheirBaseKey().PublicKey() + privateKey = parameters.OurOneTimePreKey().PrivateKey().Serialize() + secret = kdf.CalculateSharedSecret( + publicKey, + privateKey, + ) + masterSecret = append(masterSecret, secret[:]...) + + } + + // Derive the root and chain keys based on the master secret. + derivedKeysBytes, err := kdf.DeriveSecrets(masterSecret, nil, []byte("WhisperText"), root.DerivedSecretsSize) + if err != nil { + return nil, err + } + derivedKeys := session.NewDerivedSecrets(derivedKeysBytes) + chainKey := chain.NewKey(kdf.DeriveSecrets, derivedKeys.ChainKey(), 0) + rootKey := root.NewKey(kdf.DeriveSecrets, derivedKeys.RootKey()) + + // Add the root and chain keys to a structure that will hold both keys. + sessionKeys := session.NewKeyPair(rootKey, chainKey) + + return sessionKeys, nil +} + +// CalculateSymmetricSession calculates the key agreement between two users. This +// works by both clients exchanging KeyExchange messages to first establish a session. +// This is useful for establishing a session if both users are online. +func CalculateSymmetricSession(parameters *SymmetricParameters) (*session.KeyPair, error) { + // Compare the base public keys so we can deterministically know whether we should + // be setting up a sender or receiver session. If our key converted to an integer is + // less than the other user's, act as a sender. + if isSender(parameters.OurBaseKey.PublicKey(), parameters.TheirBaseKey) { + senderParameters := &SenderParameters{ + ourBaseKey: parameters.OurBaseKey, + ourIdentityKeyPair: parameters.OurIdentityKeyPair, + theirRatchetKey: parameters.TheirRatchetKey, + theirIdentityKey: parameters.TheirIdentityKey, + theirSignedPreKey: parameters.TheirBaseKey, + } + + return CalculateSenderSession(senderParameters) + } + + // If our base public key was larger than the other user's, act as a receiver. + receiverParameters := &ReceiverParameters{ + ourIdentityKeyPair: parameters.OurIdentityKeyPair, + ourRatchetKey: parameters.OurRatchetKey, + ourSignedPreKey: parameters.OurBaseKey, + theirBaseKey: parameters.TheirBaseKey, + theirIdentityKey: parameters.TheirIdentityKey, + } + + return CalculateReceiverSession(receiverParameters) +} + +// isSender is a private method for determining if a symmetric session should +// be calculated as the sender or receiver. It does so by converting the given +// keys into integers and comparing the size of those integers. +func isSender(ourKey, theirKey ecc.ECPublicKeyable) bool { + ourKeyInt := binary.BigEndian.Uint32(ourKey.Serialize()) + theirKeyInt := binary.BigEndian.Uint32(theirKey.Serialize()) + + return ourKeyInt < theirKeyInt +} diff --git a/vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go b/vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go new file mode 100644 index 00000000..97822d19 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go @@ -0,0 +1,106 @@ +package ratchet + +import ( + "go.mau.fi/libsignal/ecc" + "go.mau.fi/libsignal/keys/identity" +) + +// NewReceiverParameters creates a structure with all the keys needed to construct +// a new session when we are receiving a message from a user for the first time. +func NewReceiverParameters(ourIdentityKey *identity.KeyPair, ourSignedPreKey *ecc.ECKeyPair, + ourOneTimePreKey *ecc.ECKeyPair, ourRatchetKey *ecc.ECKeyPair, + theirBaseKey ecc.ECPublicKeyable, theirIdentityKey *identity.Key) *ReceiverParameters { + + receiverParams := ReceiverParameters{ + ourIdentityKeyPair: ourIdentityKey, + ourSignedPreKey: ourSignedPreKey, + ourOneTimePreKey: ourOneTimePreKey, + ourRatchetKey: ourRatchetKey, + theirBaseKey: theirBaseKey, + theirIdentityKey: theirIdentityKey, + } + + return &receiverParams +} + +// NewEmptyReceiverParameters creates an empty structure with the receiver parameters +// needed to create a session. You should use the `set` functions to set all the +// necessary keys needed to build a session. +func NewEmptyReceiverParameters() *ReceiverParameters { + receiverParams := ReceiverParameters{} + + return &receiverParams +} + +// ReceiverParameters describes the session parameters if we are receiving +// a message from someone for the first time. These parameters are used as +// the basis for deriving a shared secret with the sender. +type ReceiverParameters struct { + ourIdentityKeyPair *identity.KeyPair + ourSignedPreKey *ecc.ECKeyPair + ourOneTimePreKey *ecc.ECKeyPair + ourRatchetKey *ecc.ECKeyPair + + theirBaseKey ecc.ECPublicKeyable + theirIdentityKey *identity.Key +} + +// OurIdentityKeyPair returns the identity key of the receiver. +func (r *ReceiverParameters) OurIdentityKeyPair() *identity.KeyPair { + return r.ourIdentityKeyPair +} + +// OurSignedPreKey returns the signed prekey of the receiver. +func (r *ReceiverParameters) OurSignedPreKey() *ecc.ECKeyPair { + return r.ourSignedPreKey +} + +// OurOneTimePreKey returns the one time prekey of the receiver. +func (r *ReceiverParameters) OurOneTimePreKey() *ecc.ECKeyPair { + return r.ourOneTimePreKey +} + +// OurRatchetKey returns the ratchet key of the receiver. +func (r *ReceiverParameters) OurRatchetKey() *ecc.ECKeyPair { + return r.ourRatchetKey +} + +// TheirBaseKey returns the base key of the sender. +func (r *ReceiverParameters) TheirBaseKey() ecc.ECPublicKeyable { + return r.theirBaseKey +} + +// TheirIdentityKey returns the identity key of the sender. +func (r *ReceiverParameters) TheirIdentityKey() *identity.Key { + return r.theirIdentityKey +} + +// SetOurIdentityKeyPair sets the identity key of the receiver. +func (r *ReceiverParameters) SetOurIdentityKeyPair(ourIdentityKey *identity.KeyPair) { + r.ourIdentityKeyPair = ourIdentityKey +} + +// SetOurSignedPreKey sets the signed prekey of the receiver. +func (r *ReceiverParameters) SetOurSignedPreKey(ourSignedPreKey *ecc.ECKeyPair) { + r.ourSignedPreKey = ourSignedPreKey +} + +// SetOurOneTimePreKey sets the one time prekey of the receiver. +func (r *ReceiverParameters) SetOurOneTimePreKey(ourOneTimePreKey *ecc.ECKeyPair) { + r.ourOneTimePreKey = ourOneTimePreKey +} + +// SetOurRatchetKey sets the ratchet key of the receiver. +func (r *ReceiverParameters) SetOurRatchetKey(ourRatchetKey *ecc.ECKeyPair) { + r.ourRatchetKey = ourRatchetKey +} + +// SetTheirBaseKey sets the base key of the sender. +func (r *ReceiverParameters) SetTheirBaseKey(theirBaseKey ecc.ECPublicKeyable) { + r.theirBaseKey = theirBaseKey +} + +// SetTheirIdentityKey sets the identity key of the sender. +func (r *ReceiverParameters) SetTheirIdentityKey(theirIdentityKey *identity.Key) { + r.theirIdentityKey = theirIdentityKey +} diff --git a/vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go b/vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go new file mode 100644 index 00000000..ca972956 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go @@ -0,0 +1,106 @@ +package ratchet + +import ( + "go.mau.fi/libsignal/ecc" + "go.mau.fi/libsignal/keys/identity" +) + +// NewSenderParameters creates a structure with all the keys needed to construct +// a new session when we are sending a message to a recipient for the first time. +func NewSenderParameters(ourIdentityKey *identity.KeyPair, ourBaseKey *ecc.ECKeyPair, + theirIdentityKey *identity.Key, theirSignedPreKey ecc.ECPublicKeyable, + theirRatchetKey ecc.ECPublicKeyable, theirOneTimePreKey ecc.ECPublicKeyable) *SenderParameters { + + senderParams := SenderParameters{ + ourIdentityKeyPair: ourIdentityKey, + ourBaseKey: ourBaseKey, + theirIdentityKey: theirIdentityKey, + theirSignedPreKey: theirSignedPreKey, + theirOneTimePreKey: theirOneTimePreKey, + theirRatchetKey: theirRatchetKey, + } + + return &senderParams +} + +// NewEmptySenderParameters creates an empty structure with the sender parameters +// needed to create a session. You should use the `set` functions to set all the +// necessary keys needed to build a session. +func NewEmptySenderParameters() *SenderParameters { + senderParams := SenderParameters{} + + return &senderParams +} + +// SenderParameters describes the session parameters if we are sending the +// recipient a message for the first time. These parameters are used as the +// basis for deriving a shared secret with a recipient. +type SenderParameters struct { + ourIdentityKeyPair *identity.KeyPair + ourBaseKey *ecc.ECKeyPair + + theirIdentityKey *identity.Key + theirSignedPreKey ecc.ECPublicKeyable + theirOneTimePreKey ecc.ECPublicKeyable + theirRatchetKey ecc.ECPublicKeyable +} + +// OurIdentityKey returns the identity key pair of the sender. +func (s *SenderParameters) OurIdentityKey() *identity.KeyPair { + return s.ourIdentityKeyPair +} + +// OurBaseKey returns the base ECC key pair of the sender. +func (s *SenderParameters) OurBaseKey() *ecc.ECKeyPair { + return s.ourBaseKey +} + +// TheirIdentityKey returns the identity public key of the receiver. +func (s *SenderParameters) TheirIdentityKey() *identity.Key { + return s.theirIdentityKey +} + +// TheirSignedPreKey returns the signed pre key of the receiver. +func (s *SenderParameters) TheirSignedPreKey() ecc.ECPublicKeyable { + return s.theirSignedPreKey +} + +// TheirOneTimePreKey returns the receiver's one time prekey. +func (s *SenderParameters) TheirOneTimePreKey() ecc.ECPublicKeyable { + return s.theirOneTimePreKey +} + +// TheirRatchetKey returns the receiver's ratchet key. +func (s *SenderParameters) TheirRatchetKey() ecc.ECPublicKeyable { + return s.theirRatchetKey +} + +// SetOurIdentityKey sets the identity key pair of the sender. +func (s *SenderParameters) SetOurIdentityKey(ourIdentityKey *identity.KeyPair) { + s.ourIdentityKeyPair = ourIdentityKey +} + +// SetOurBaseKey sets the base ECC key pair of the sender. +func (s *SenderParameters) SetOurBaseKey(ourBaseKey *ecc.ECKeyPair) { + s.ourBaseKey = ourBaseKey +} + +// SetTheirIdentityKey sets the identity public key of the receiver. +func (s *SenderParameters) SetTheirIdentityKey(theirIdentityKey *identity.Key) { + s.theirIdentityKey = theirIdentityKey +} + +// SetTheirSignedPreKey sets the signed pre key of the receiver. +func (s *SenderParameters) SetTheirSignedPreKey(theirSignedPreKey ecc.ECPublicKeyable) { + s.theirSignedPreKey = theirSignedPreKey +} + +// SetTheirOneTimePreKey sets the receiver's one time prekey. +func (s *SenderParameters) SetTheirOneTimePreKey(theirOneTimePreKey ecc.ECPublicKeyable) { + s.theirOneTimePreKey = theirOneTimePreKey +} + +// SetTheirRatchetKey sets the receiver's ratchet key. +func (s *SenderParameters) SetTheirRatchetKey(theirRatchetKey ecc.ECPublicKeyable) { + s.theirRatchetKey = theirRatchetKey +} diff --git a/vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go b/vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go new file mode 100644 index 00000000..e7811de5 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go @@ -0,0 +1,18 @@ +package ratchet + +import ( + "go.mau.fi/libsignal/ecc" + "go.mau.fi/libsignal/keys/identity" +) + +// SymmetricParameters describes the session parameters for sessions where +// both users are online, which doesn't use prekeys for setup. +type SymmetricParameters struct { + OurBaseKey *ecc.ECKeyPair + OurRatchetKey *ecc.ECKeyPair + OurIdentityKeyPair *identity.KeyPair + + TheirBaseKey ecc.ECPublicKeyable + TheirRatchetKey ecc.ECPublicKeyable + TheirIdentityKey *identity.Key +} |