mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-05 20:44:04 +00:00
Add dependencies/vendor (whatsapp)
This commit is contained in:
141
vendor/go.mau.fi/libsignal/groups/GroupCipher.go
vendored
Normal file
141
vendor/go.mau.fi/libsignal/groups/GroupCipher.go
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
package groups
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/cipher"
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/groups/ratchet"
|
||||
"go.mau.fi/libsignal/groups/state/record"
|
||||
"go.mau.fi/libsignal/groups/state/store"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
)
|
||||
|
||||
// NewGroupCipher will return a new group message cipher that can be used for
|
||||
// encrypt/decrypt operations.
|
||||
func NewGroupCipher(builder *SessionBuilder, senderKeyID *protocol.SenderKeyName,
|
||||
senderKeyStore store.SenderKey) *GroupCipher {
|
||||
|
||||
return &GroupCipher{
|
||||
senderKeyID: senderKeyID,
|
||||
senderKeyStore: senderKeyStore,
|
||||
sessionBuilder: builder,
|
||||
}
|
||||
}
|
||||
|
||||
// GroupCipher is the main entry point for group encrypt/decrypt operations.
|
||||
// Once a session has been established, this can be used for
|
||||
// all encrypt/decrypt operations within that session.
|
||||
type GroupCipher struct {
|
||||
senderKeyID *protocol.SenderKeyName
|
||||
senderKeyStore store.SenderKey
|
||||
sessionBuilder *SessionBuilder
|
||||
}
|
||||
|
||||
// Encrypt will take the given message in bytes and return encrypted bytes.
|
||||
func (c *GroupCipher) Encrypt(plaintext []byte) (protocol.GroupCiphertextMessage, error) {
|
||||
// Load the sender key based on id from our store.
|
||||
keyRecord := c.senderKeyStore.LoadSenderKey(c.senderKeyID)
|
||||
senderKeyState, err := keyRecord.SenderKeyState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the message key from the senderkey state.
|
||||
senderKey, err := senderKeyState.SenderChainKey().SenderMessageKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Encrypt the plaintext.
|
||||
ciphertext, err := cipher.EncryptCbc(senderKey.Iv(), senderKey.CipherKey(), plaintext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
senderKeyMessage := protocol.NewSenderKeyMessage(
|
||||
senderKeyState.KeyID(),
|
||||
senderKey.Iteration(),
|
||||
ciphertext,
|
||||
senderKeyState.SigningKey().PrivateKey(),
|
||||
c.sessionBuilder.serializer.SenderKeyMessage,
|
||||
)
|
||||
|
||||
senderKeyState.SetSenderChainKey(senderKeyState.SenderChainKey().Next())
|
||||
c.senderKeyStore.StoreSenderKey(c.senderKeyID, keyRecord)
|
||||
|
||||
return senderKeyMessage, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts the given message using an existing session that
|
||||
// is stored in the senderKey store.
|
||||
func (c *GroupCipher) Decrypt(senderKeyMessage *protocol.SenderKeyMessage) ([]byte, error) {
|
||||
keyRecord := c.senderKeyStore.LoadSenderKey(c.senderKeyID)
|
||||
|
||||
if keyRecord.IsEmpty() {
|
||||
return nil, fmt.Errorf("%w for %s in %s", signalerror.ErrNoSenderKeyForUser, c.senderKeyID.Sender().String(), c.senderKeyID.GroupID())
|
||||
}
|
||||
|
||||
// Get the senderkey state by id.
|
||||
senderKeyState, err := keyRecord.GetSenderKeyStateByID(senderKeyMessage.KeyID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify the signature of the senderkey message.
|
||||
verified := c.verifySignature(senderKeyState.SigningKey().PublicKey(), senderKeyMessage)
|
||||
if !verified {
|
||||
return nil, signalerror.ErrSenderKeyStateVerificationFailed
|
||||
}
|
||||
|
||||
senderKey, err := c.getSenderKey(senderKeyState, senderKeyMessage.Iteration())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Decrypt the message ciphertext.
|
||||
plaintext, err := cipher.DecryptCbc(senderKey.Iv(), senderKey.CipherKey(), senderKeyMessage.Ciphertext())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Store the sender key by id.
|
||||
c.senderKeyStore.StoreSenderKey(c.senderKeyID, keyRecord)
|
||||
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// verifySignature will verify the signature of the senderkey message with
|
||||
// the given public key.
|
||||
func (c *GroupCipher) verifySignature(signingPubKey ecc.ECPublicKeyable,
|
||||
senderKeyMessage *protocol.SenderKeyMessage) bool {
|
||||
|
||||
return ecc.VerifySignature(signingPubKey, senderKeyMessage.Serialize(), senderKeyMessage.Signature())
|
||||
}
|
||||
|
||||
func (c *GroupCipher) getSenderKey(senderKeyState *record.SenderKeyState, iteration uint32) (*ratchet.SenderMessageKey, error) {
|
||||
senderChainKey := senderKeyState.SenderChainKey()
|
||||
if senderChainKey.Iteration() > iteration {
|
||||
if senderKeyState.HasSenderMessageKey(iteration) {
|
||||
return senderKeyState.RemoveSenderMessageKey(iteration), nil
|
||||
}
|
||||
return nil, fmt.Errorf("%w (current: %d, received: %d)", signalerror.ErrOldCounter, senderChainKey.Iteration(), iteration)
|
||||
}
|
||||
|
||||
if iteration-senderChainKey.Iteration() > 2000 {
|
||||
return nil, signalerror.ErrTooFarIntoFuture
|
||||
}
|
||||
|
||||
for senderChainKey.Iteration() < iteration {
|
||||
senderMessageKey, err := senderChainKey.SenderMessageKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
senderKeyState.AddSenderMessageKey(senderMessageKey)
|
||||
senderChainKey = senderChainKey.Next()
|
||||
}
|
||||
|
||||
senderKeyState.SetSenderChainKey(senderChainKey.Next())
|
||||
return senderChainKey.SenderMessageKey()
|
||||
}
|
Reference in New Issue
Block a user