2021-02-15 14:51:49 +00:00
|
|
|
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"
|
|
|
|
)
|
|
|
|
|
2023-11-09 18:59:01 +00:00
|
|
|
var ErrCipherMessageAutentificationFailed = "cipher: message authentication failed"
|
|
|
|
|
2021-02-17 23:14:48 +00:00
|
|
|
func EncryptIdentityImagesWithContactPubKeys(iis map[string]*protobuf.IdentityImage, m *Messenger) (err error) {
|
2021-02-15 14:51:49 +00:00
|
|
|
// Make AES key
|
|
|
|
AESKey := make([]byte, 32)
|
2021-02-17 23:14:48 +00:00
|
|
|
_, err = crand.Read(AESKey)
|
2021-02-15 14:51:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ii := range iis {
|
|
|
|
// Encrypt image payload with the AES key
|
2021-02-17 23:14:48 +00:00
|
|
|
var encryptedPayload []byte
|
|
|
|
encryptedPayload, err = common.Encrypt(ii.Payload, AESKey, crand.Reader)
|
2021-02-15 14:51:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Overwrite the unencrypted payload with the newly encrypted payload
|
|
|
|
ii.Payload = encryptedPayload
|
|
|
|
ii.Encrypted = true
|
2021-02-17 23:14:48 +00:00
|
|
|
m.allContacts.Range(func(contactID string, contact *Contact) (shouldContinue bool) {
|
2023-01-20 14:28:30 +00:00
|
|
|
if !contact.added() {
|
2021-02-17 23:14:48 +00:00
|
|
|
return true
|
2021-02-15 14:51:49 +00:00
|
|
|
}
|
2021-02-17 23:14:48 +00:00
|
|
|
var pubK *ecdsa.PublicKey
|
|
|
|
var sharedKey []byte
|
|
|
|
var eAESKey []byte
|
2021-02-15 14:51:49 +00:00
|
|
|
|
2021-02-17 23:14:48 +00:00
|
|
|
pubK, err = contact.PublicKey()
|
2021-02-15 14:51:49 +00:00
|
|
|
if err != nil {
|
2021-02-17 23:14:48 +00:00
|
|
|
return false
|
2021-02-15 14:51:49 +00:00
|
|
|
}
|
|
|
|
// Generate a Diffie-Helman (DH) between the sender private key and the recipient's public key
|
2021-02-17 23:14:48 +00:00
|
|
|
sharedKey, err = common.MakeECDHSharedKey(m.identity, pubK)
|
2021-02-15 14:51:49 +00:00
|
|
|
if err != nil {
|
2021-02-17 23:14:48 +00:00
|
|
|
return false
|
2021-02-15 14:51:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Encrypt the main AES key with AES encryption using the DH key
|
2021-02-17 23:14:48 +00:00
|
|
|
eAESKey, err = common.Encrypt(AESKey, sharedKey, crand.Reader)
|
2021-02-15 14:51:49 +00:00
|
|
|
if err != nil {
|
2021-02-17 23:14:48 +00:00
|
|
|
return false
|
2021-02-15 14:51:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Append the the encrypted main AES key to the IdentityImage's EncryptionKeys slice.
|
|
|
|
ii.EncryptionKeys = append(ii.EncryptionKeys, eAESKey)
|
2021-02-17 23:14:48 +00:00
|
|
|
return true
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2021-02-15 14:51:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2023-11-09 18:59:01 +00:00
|
|
|
if err.Error() == ErrCipherMessageAutentificationFailed {
|
2021-02-15 14:51:49 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
2021-02-17 23:14:48 +00:00
|
|
|
if dAESKey == nil {
|
2021-02-15 14:51:49 +00:00
|
|
|
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
|
|
|
|
}
|