status-im/status-go

View on GitHub
server/pairing/payload_encryptor.go

Summary

Maintainability
A
0 mins
Test Coverage
B
89%
package pairing

import (
    "crypto/rand"

    "github.com/status-im/status-go/protocol/common"
)

// EncryptionPayload represents the plain text and encrypted text of payload data
type EncryptionPayload struct {
    plain     []byte
    encrypted []byte
    locked    bool
}

func (ep *EncryptionPayload) lock() {
    ep.locked = true
}

// PayloadEncryptor is responsible for encrypting and decrypting payload data
type PayloadEncryptor struct {
    aesKey  []byte
    payload *EncryptionPayload
}

func NewPayloadEncryptor(aesKey []byte) *PayloadEncryptor {
    return &PayloadEncryptor{
        aesKey,
        new(EncryptionPayload),
    }
}

// Renew regenerates the whole PayloadEncryptor and returns the new instance, only the aesKey is preserved
func (pem *PayloadEncryptor) Renew() *PayloadEncryptor {
    return &PayloadEncryptor{
        aesKey:  pem.aesKey,
        payload: new(EncryptionPayload),
    }
}

// encryptPlain encrypts any given plain text using the internal AES key and returns the encrypted value
// This function is different to Encrypt as the internal EncryptionPayload.encrypted value is not set
func (pem *PayloadEncryptor) encryptPlain(plaintext []byte) ([]byte, error) {
    return common.Encrypt(plaintext, pem.aesKey, rand.Reader)
}

// decryptPlain decrypts any given plain text using the internal AES key and returns the encrypted value
// This function is different to Decrypt as the internal EncryptionPayload.plain value is not set
func (pem *PayloadEncryptor) decryptPlain(plaintext []byte) ([]byte, error) {
    return common.Decrypt(plaintext, pem.aesKey)
}

func (pem *PayloadEncryptor) encrypt(data []byte) error {
    ep, err := common.Encrypt(data, pem.aesKey, rand.Reader)
    if err != nil {
        return err
    }

    pem.payload.plain = data
    pem.payload.encrypted = ep
    return nil
}

func (pem *PayloadEncryptor) decrypt(data []byte) error {
    pd, err := common.Decrypt(data, pem.aesKey)
    if err != nil {
        return err
    }

    pem.payload.encrypted = data
    pem.payload.plain = pd
    return nil
}

func (pem *PayloadEncryptor) getEncrypted() []byte {
    if pem.payload.locked {
        return nil
    }
    return pem.payload.encrypted
}

func (pem *PayloadEncryptor) getDecrypted() []byte {
    if pem.payload.locked {
        return nil
    }
    return pem.payload.plain
}

func (pem *PayloadEncryptor) lockPayload() {
    pem.payload.lock()
}

// PayloadLockPayload Embeds a *PayloadEncryptor to give all embedding structs EncryptionPayload Locking
type PayloadLockPayload struct {
    *PayloadEncryptor
}

func (pl *PayloadLockPayload) LockPayload() {
    pl.lockPayload()
}

// PayloadToSend Embeds a *PayloadEncryptor to give all embedding structs EncryptionPayload ToSend() functionality
// Useful to securely implement the PayloadMounter interface
type PayloadToSend struct {
    *PayloadEncryptor
}

func (pts *PayloadToSend) ToSend() []byte {
    return pts.getEncrypted()
}

// PayloadReceived Embeds a *PayloadEncryptor to give all embedding structs EncryptionPayload Received() functionality
// Useful to securely implement the PayloadReceiver interface
type PayloadReceived struct {
    *PayloadEncryptor
}

func (pr *PayloadReceived) Received() []byte {
    return pr.getDecrypted()
}