Refactor so both Messenger and MessageHandler could use code from a shsared source
This commit is contained in:
parent
33487d64de
commit
3a1349141a
|
@ -0,0 +1,100 @@
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
crand "crypto/rand"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EncryptIdentityImagesWithContactPubKeys(iis map[string]*protobuf.IdentityImage, m *Messenger) error {
|
||||||
|
// Make AES key
|
||||||
|
AESKey := make([]byte, 32)
|
||||||
|
_, err := crand.Read(AESKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ii := range iis {
|
||||||
|
// Encrypt image payload with the AES key
|
||||||
|
encryptedPayload, err := common.Encrypt(ii.Payload, AESKey, crand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite the unencrypted payload with the newly encrypted payload
|
||||||
|
ii.Payload = encryptedPayload
|
||||||
|
ii.Encrypted = true
|
||||||
|
for _, c := range m.allContacts {
|
||||||
|
if !c.IsAdded() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pubK, err := c.PublicKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Generate a Diffie-Helman (DH) between the sender private key and the recipient's public key
|
||||||
|
sharedKey, err := common.MakeECDHSharedKey(m.identity, pubK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt the main AES key with AES encryption using the DH key
|
||||||
|
eAESKey, err := common.Encrypt(AESKey, sharedKey, crand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the the encrypted main AES key to the IdentityImage's EncryptionKeys slice.
|
||||||
|
ii.EncryptionKeys = append(ii.EncryptionKeys, eAESKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecryptIdentityImagesWithIdentityPrivateKey(iis map[string]*protobuf.IdentityImage, recipientIdentity *ecdsa.PrivateKey, senderPubKey *ecdsa.PublicKey) error {
|
||||||
|
image:
|
||||||
|
for _, ii := range iis {
|
||||||
|
for _, empk := range ii.EncryptionKeys {
|
||||||
|
// Generate a Diffie-Helman (DH) between the recipient's private key and the sender's public key
|
||||||
|
sharedKey, err := common.MakeECDHSharedKey(recipientIdentity, senderPubKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt the main encryption AES key with AES encryption using the DH key
|
||||||
|
dAESKey, err := common.Decrypt(empk, sharedKey)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "cipher: message authentication failed" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dAESKey == nil{
|
||||||
|
return errors.New("decrypting the payload encryption key resulted in no error and a nil key")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt the payload with the newly decrypted main encryption AES key
|
||||||
|
payload, err := common.Decrypt(ii.Payload, dAESKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if payload == nil {
|
||||||
|
// TODO should this be a logger warn? A payload could theoretically be validly empty
|
||||||
|
return errors.New("decrypting the payload resulted in no error and a nil payload")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite the payload with the decrypted data
|
||||||
|
ii.Payload = payload
|
||||||
|
ii.Encrypted = false
|
||||||
|
continue image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
crand "crypto/rand"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -820,7 +819,7 @@ func (m *Messenger) attachIdentityImagesToChatIdentity(context chatContext, ci *
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.ProfilePicturesShowTo == accounts.ProfilePicturesShowToContactsOnly {
|
if s.ProfilePicturesShowTo == accounts.ProfilePicturesShowToContactsOnly {
|
||||||
err := m.encryptIdentityImagesWithContactPubKeys(ci.Images)
|
err := EncryptIdentityImagesWithContactPubKeys(ci.Images, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -829,101 +828,6 @@ func (m *Messenger) attachIdentityImagesToChatIdentity(context chatContext, ci *
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) encryptIdentityImagesWithContactPubKeys(iis map[string]*protobuf.IdentityImage) (err error) {
|
|
||||||
// Make AES key
|
|
||||||
AESKey := make([]byte, 32)
|
|
||||||
_, err = crand.Read(AESKey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ii := range iis {
|
|
||||||
// Encrypt image payload with the AES key
|
|
||||||
encryptedPayload, err := common.Encrypt(ii.Payload, AESKey, crand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite the unencrypted payload with the newly encrypted payload
|
|
||||||
ii.Payload = encryptedPayload
|
|
||||||
ii.Encrypted = true
|
|
||||||
m.allContacts.Range(func(contactID string, c *Contact) (shouldContinue bool) {
|
|
||||||
if !c.IsAdded() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
pubK, err := c.PublicKey()
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Generate a Diffie-Helman (DH) between the sender private key and the recipient's public key
|
|
||||||
sharedKey, err := common.MakeECDHSharedKey(m.identity, pubK)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt the main AES key with AES encryption using the DH key
|
|
||||||
eAESKey, err := common.Encrypt(AESKey, sharedKey, crand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the the encrypted main AES key to the IdentityImage's EncryptionKeys slice.
|
|
||||||
ii.EncryptionKeys = append(ii.EncryptionKeys, eAESKey)
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Messenger) decryptIdentityImagesWithIdentityPrivateKey(iis map[string]*protobuf.IdentityImage, senderPubKey *ecdsa.PublicKey) error {
|
|
||||||
image:
|
|
||||||
for _, ii := range iis {
|
|
||||||
for _, empk := range ii.EncryptionKeys {
|
|
||||||
// Generate a Diffie-Helman (DH) between the recipient's private key and the sender's public key
|
|
||||||
sharedKey, err := common.MakeECDHSharedKey(m.identity, senderPubKey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt the main encryption AES key with AES encryption using the DH key
|
|
||||||
dAESKey, err := common.Decrypt(empk, sharedKey)
|
|
||||||
if err != nil {
|
|
||||||
if err.Error() == "cipher: message authentication failed" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if dAESKey == nil{
|
|
||||||
return errors.New("decrypting the payload encryption key resulted in no error and a nil key")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt the payload with the newly decrypted main encryption AES key
|
|
||||||
payload, err := common.Decrypt(ii.Payload, dAESKey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if payload == nil {
|
|
||||||
// TODO should this be a logger warn? A payload could theoretically be validly empty
|
|
||||||
return errors.New("decrypting the payload resulted in no error and a nil payload")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite the payload with the decrypted data
|
|
||||||
ii.Payload = payload
|
|
||||||
ii.Encrypted = false // TODO handle the encryption state in the consuming code
|
|
||||||
continue image
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleSharedSecrets process the negotiated secrets received from the encryption layer
|
// handleSharedSecrets process the negotiated secrets received from the encryption layer
|
||||||
func (m *Messenger) handleSharedSecrets(secrets []*sharedsecret.Secret) error {
|
func (m *Messenger) handleSharedSecrets(secrets []*sharedsecret.Secret) error {
|
||||||
for _, secret := range secrets {
|
for _, secret := range secrets {
|
||||||
|
|
|
@ -1320,6 +1320,18 @@ func (m *Messenger) HandleChatIdentity(state *ReceivedMessageState, ci protobuf.
|
||||||
}
|
}
|
||||||
contact := state.CurrentMessageState.Contact
|
contact := state.CurrentMessageState.Contact
|
||||||
|
|
||||||
|
err := DecryptIdentityImagesWithIdentityPrivateKey(ci.Images, m.identity, state.CurrentMessageState.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any images still encrypted after the decryption process
|
||||||
|
for name, image := range ci.Images {
|
||||||
|
if image.Encrypted {
|
||||||
|
delete(ci.Images, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.Info("Handling contact update")
|
logger.Info("Handling contact update")
|
||||||
newImages, err := m.persistence.SaveContactChatIdentity(contact.ID, &ci)
|
newImages, err := m.persistence.SaveContactChatIdentity(contact.ID, &ci)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue