github.com/status-im/status-go@v1.1.0/protocol/identity_images.go (about)

     1  package protocol
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	crand "crypto/rand"
     6  	"errors"
     7  
     8  	"github.com/status-im/status-go/protocol/common"
     9  	"github.com/status-im/status-go/protocol/protobuf"
    10  )
    11  
    12  var ErrCipherMessageAutentificationFailed = "cipher: message authentication failed"
    13  
    14  func EncryptIdentityImagesWithContactPubKeys(iis map[string]*protobuf.IdentityImage, m *Messenger) (err error) {
    15  	// Make AES key
    16  	AESKey := make([]byte, 32)
    17  	_, err = crand.Read(AESKey)
    18  	if err != nil {
    19  		return err
    20  	}
    21  
    22  	for _, ii := range iis {
    23  		// Encrypt image payload with the AES key
    24  		var encryptedPayload []byte
    25  		encryptedPayload, err = common.Encrypt(ii.Payload, AESKey, crand.Reader)
    26  		if err != nil {
    27  			return err
    28  		}
    29  
    30  		// Overwrite the unencrypted payload with the newly encrypted payload
    31  		ii.Payload = encryptedPayload
    32  		ii.Encrypted = true
    33  		m.allContacts.Range(func(contactID string, contact *Contact) (shouldContinue bool) {
    34  			if !contact.added() {
    35  				return true
    36  			}
    37  			var pubK *ecdsa.PublicKey
    38  			var sharedKey []byte
    39  			var eAESKey []byte
    40  
    41  			pubK, err = contact.PublicKey()
    42  			if err != nil {
    43  				return false
    44  			}
    45  			// Generate a Diffie-Helman (DH) between the sender private key and the recipient's public key
    46  			sharedKey, err = common.MakeECDHSharedKey(m.identity, pubK)
    47  			if err != nil {
    48  				return false
    49  			}
    50  
    51  			// Encrypt the main AES key with AES encryption using the DH key
    52  			eAESKey, err = common.Encrypt(AESKey, sharedKey, crand.Reader)
    53  			if err != nil {
    54  				return false
    55  			}
    56  
    57  			// Append the the encrypted main AES key to the IdentityImage's EncryptionKeys slice.
    58  			ii.EncryptionKeys = append(ii.EncryptionKeys, eAESKey)
    59  			return true
    60  		})
    61  		if err != nil {
    62  			return err
    63  		}
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  func DecryptIdentityImagesWithIdentityPrivateKey(iis map[string]*protobuf.IdentityImage, recipientIdentity *ecdsa.PrivateKey, senderPubKey *ecdsa.PublicKey) error {
    70  image:
    71  	for _, ii := range iis {
    72  		for _, empk := range ii.EncryptionKeys {
    73  			// Generate a Diffie-Helman (DH) between the recipient's private key and the sender's public key
    74  			sharedKey, err := common.MakeECDHSharedKey(recipientIdentity, senderPubKey)
    75  			if err != nil {
    76  				return err
    77  			}
    78  
    79  			// Decrypt the main encryption AES key with AES encryption using the DH key
    80  			dAESKey, err := common.Decrypt(empk, sharedKey)
    81  			if err != nil {
    82  				if err.Error() == ErrCipherMessageAutentificationFailed {
    83  					continue
    84  				}
    85  				return err
    86  			}
    87  			if dAESKey == nil {
    88  				return errors.New("decrypting the payload encryption key resulted in no error and a nil key")
    89  			}
    90  
    91  			// Decrypt the payload with the newly decrypted main encryption AES key
    92  			payload, err := common.Decrypt(ii.Payload, dAESKey)
    93  			if err != nil {
    94  				return err
    95  			}
    96  			if payload == nil {
    97  				// TODO should this be a logger warn? A payload could theoretically be validly empty
    98  				return errors.New("decrypting the payload resulted in no error and a nil payload")
    99  			}
   100  
   101  			// Overwrite the payload with the decrypted data
   102  			ii.Payload = payload
   103  			ii.Encrypted = false
   104  			continue image
   105  		}
   106  	}
   107  
   108  	return nil
   109  }