func CreateMessage(privateKey *easyecc.PrivateKey, body []byte, sender, receiver string,
	receiverKey *easyecc.PublicKey) (*pb.DMSMessage, error) {
	headers := map[string]string{
		"X-Ubikom-Sender":       sender,
		"X-Ubikom-Sender-Key":   privateKey.PublicKey().Address(),
		"X-Ubikom-Receiver":     receiver,
		"X-Ubikom-Receiver-Key": receiverKey.Address()}
	withHeaders := mail.AddHeaders(string(body), headers)
	encryptedBody, err := privateKey.Encrypt([]byte(withHeaders), receiverKey)
	if err != nil {
		return nil, fmt.Errorf("failed to encrypt message: %w", err)
	}
	hash := util.Hash256(encryptedBody)
	sig, err := privateKey.Sign(hash)
	if err != nil {
		return nil, fmt.Errorf("failed to sign message, %w", err)
	}
	return &pb.DMSMessage{
		Sender:   sender,
		Receiver: receiver,
		Content:  encryptedBody,
		Signature: &pb.Signature{
			R: sig.R.Bytes(),
			S: sig.S.Bytes(),
		},
	}, nil
}
CreateMessages creates a new DMSMessage, signed and encrypted.
package protoutil
import (
	"context"
	"fmt"
	"math/big"
	"time"
	"github.com/regnull/easyecc"
	"github.com/regnull/ubikom/mail"
	"github.com/regnull/ubikom/pb"
	"github.com/regnull/ubikom/pow"
	"github.com/regnull/ubikom/util"
	"github.com/rs/zerolog/log"
	"google.golang.org/grpc"
)
func CreateSignedWithPOW(privateKey *easyecc.PrivateKey, content []byte, powStrength int) (*pb.SignedWithPow, error) {
	log.Debug().Msg("generating POW...")
	reqPow := pow.Compute(content, powStrength)
	log.Debug().Hex("pow", reqPow).Msg("POW found")
	signed, err := CreateSigned(privateKey, content)
	if err != nil {
		return nil, err
	}
	req := &pb.SignedWithPow{
		Content:   content,
		Pow:       reqPow,
		Signature: signed.Signature,
		Key:       signed.Key,
	}
	return req, nil
}
func CreateSigned(privateKey *easyecc.PrivateKey, content []byte) (*pb.Signed, error) {
	compressedKey := privateKey.PublicKey().SerializeCompressed()
	hash := util.Hash256(content)
	sig, err := privateKey.Sign(hash)
	if err != nil {
		return nil, fmt.Errorf("failed to sign request, %w", err)
	}
	req := &pb.Signed{
		Content: content,
		Signature: &pb.Signature{
			R: sig.R.Bytes(),
			S: sig.S.Bytes(),
		},
		Key: compressedKey,
	}
	return req, nil
}
func VerifySignature(sig *pb.Signature, serializedKey []byte, content []byte) bool {
	key, err := easyecc.NewPublicFromSerializedCompressed(serializedKey)
	if err != nil {
		log.Printf("invalid serialized compressed key")
		return false
	}
	eccSig := &easyecc.Signature{
		R: new(big.Int).SetBytes(sig.R),
		S: new(big.Int).SetBytes(sig.S)}
	if !eccSig.Verify(key, util.Hash256(content)) {
		log.Printf("signature verification failed")
		return false
	}
	return true
}