status-go/protocol/identity_images.go

110 lines
3.0 KiB
Go

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"
)
var ErrCipherMessageAutentificationFailed = "cipher: message authentication failed"
func EncryptIdentityImagesWithContactPubKeys(iis map[string]*protobuf.IdentityImage, m *Messenger) (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
var encryptedPayload []byte
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, contact *Contact) (shouldContinue bool) {
if !contact.added() {
return true
}
var pubK *ecdsa.PublicKey
var sharedKey []byte
var eAESKey []byte
pubK, err = contact.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 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() == ErrCipherMessageAutentificationFailed {
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
}