func (msg *ObjectMessage) GenerateForeignIdentity() (*identity.Foreign, error) {
	id := new(identity.Foreign)
	switch payload := msg.Payload.(type) {
	case *objects.PubkeyV2:
		id.EncryptionKey, _ = elliptic.PublicKeyFromUncompressedBytes(
			constants.Curve, append([]byte{0x04}, payload.PubEncryptionKey[:]...))
		id.SigningKey, _ = elliptic.PublicKeyFromUncompressedBytes(
			constants.Curve, append([]byte{0x04}, payload.PubSigningKey[:]...))
		id.CreateAddress(2, msg.Stream)
		id.SetDefaultPOWParams()
		return id, nil
	case *objects.PubkeyV3:
		id.EncryptionKey, _ = elliptic.PublicKeyFromUncompressedBytes(
			constants.Curve, append([]byte{0x04}, payload.PubEncryptionKey[:]...))
		id.SigningKey, _ = elliptic.PublicKeyFromUncompressedBytes(
			constants.Curve, append([]byte{0x04}, payload.PubSigningKey[:]...))
		id.CreateAddress(3, msg.Stream)
		id.NonceTrialsPerByte = payload.NonceTrialsPerByte
		id.ExtraBytes = payload.ExtraBytes
		return id, nil
	case *objects.PubkeyUnencryptedV4:
		id.EncryptionKey, _ = elliptic.PublicKeyFromUncompressedBytes(
			constants.Curve, append([]byte{0x04}, payload.PubEncryptionKey[:]...))
		id.SigningKey, _ = elliptic.PublicKeyFromUncompressedBytes(
			constants.Curve, append([]byte{0x04}, payload.PubSigningKey[:]...))
		id.CreateAddress(4, msg.Stream)
		id.NonceTrialsPerByte = payload.NonceTrialsPerByte
		id.ExtraBytes = payload.ExtraBytes
		return id, nil
	}
	return nil, InvalidPayloadOperationError
}
GenerateForeignIdentity generates an identity.Foreign object based on the
type of public key that we have (if it is a public key).
package protocol
import (
	"bytes"
	"crypto/sha512"
	"encoding/binary"
	"errors"
	"io"
	"math/rand"
	"time"
	"github.com/ishbir/elliptic"
	"github.com/ishbir/bmgo/bitmessage/constants"
	"github.com/ishbir/bmgo/bitmessage/identity"
	"github.com/ishbir/bmgo/bitmessage/pow"
	"github.com/ishbir/bmgo/bitmessage/protocol/objects"
	"github.com/ishbir/bmgo/bitmessage/protocol/types"
)
func (msg *ObjectMessage) HeaderSerialize() []byte {
	var b bytes.Buffer
	binary.Write(&b, binary.BigEndian, msg.expiresTime)
	binary.Write(&b, binary.BigEndian, uint32(msg.ObjectType))
	b.Write(msg.Version.Serialize())
	b.Write(msg.Stream.Serialize())
	return b.Bytes()
}
func (msg *ObjectMessage) Serialize() []byte {
	var b bytes.Buffer
	binary.Write(&b, binary.BigEndian, msg.Nonce)
	b.Write(msg.HeaderSerialize())
	b.Write(msg.Payload.Serialize())
	return CreateMessage("object", b.Bytes())
}
func (msg *ObjectMessage) DeserializeReader(b io.Reader) error {
	err := binary.Read(b, binary.BigEndian, &msg.Nonce)
	if err != nil {
		return types.DeserializeFailedError("nonce: " + err.Error())
	}
	err = binary.Read(b, binary.BigEndian, &msg.expiresTime)
	if err != nil {
		return types.DeserializeFailedError("expiresTime: " + err.Error())
	}
	var objType uint32
	err = binary.Read(b, binary.BigEndian, &objType)
	if err != nil {
		return types.DeserializeFailedError("objectType: " + err.Error())
	}
	msg.ObjectType = ObjectType(objType)
	err = msg.Version.DeserializeReader(b)
	if err != nil {
		return types.DeserializeFailedError("version: " + err.Error())
	}
	err = msg.Stream.DeserializeReader(b)
	if err != nil {
		return types.DeserializeFailedError("stream: " + err.Error())
	}
	msg.setPayloadType()  
	err = msg.Payload.DeserializeReader(b)
	if err != nil {
		return types.DeserializeFailedError("payload" + err.Error())
	}
	return nil
}
func random(min, max int) int {
	return rand.Intn(max-min) + min
}
func (msg *ObjectMessage) Preserialize(id *identity.Own,
	target *identity.Foreign) error {
	msg.TTL += time.Second * time.Duration(random(
		-int(time.Duration(constants.ObjectTTLRandRange).Seconds()),
		int(time.Duration(constants.ObjectTTLRandRange).Seconds())))
	ttl := int(msg.TTL.Seconds())
	msg.expiresTime = uint64(time.Now().Add(msg.TTL).Unix())
	if keysetter, ok := msg.Payload.(PublicKeysAddablePayload); ok {
		keysetter.SetSigningAndEncryptionKeys(
			id.SigningKey.PublicKey.SerializeUncompressed()[1:],  
			id.EncryptionKey.PublicKey.SerializeUncompressed()[1:],
		)
	}
	if signer, ok := msg.Payload.(SignablePayload); ok {
		var b bytes.Buffer
		b.Write(msg.HeaderSerialize())
		b.Write(signer.SignatureSerialize())
		signature, err := id.SigningKey.Sign(b.Bytes())
		if err != nil {
			return errors.New("signing failed: " + err.Error())
		}
		signer.SetSignature(signature)
	}
	var tag []byte
	switch msg.Payload.(type) {
	case *objects.PubkeyUnencryptedV4, *objects.BroadcastUnencryptedV5:
		hash := id.Address.CalcDoubleHash()
		privKey, err := elliptic.PrivateKeyFromRawBytes(constants.Curve,
			hash[:32])
		if err != nil {
			return errors.New("failed to create private key from address: " +
				err.Error())
		}
		target = new(identity.Foreign)
		target.EncryptionKey = &privKey.PublicKey
		tag = hash[32:]  
	case *objects.BroadcastUnencryptedV4AddressV2,
		*objects.BroadcastUnencryptedV4AddressV3:
		sha := sha512.New()
		sha.Write(id.Address.Version.Serialize())
		sha.Write(id.Address.Stream.Serialize())
		sha.Write(id.Address.Ripe[:])
		hash := sha.Sum(nil)
		privKey, err := elliptic.PrivateKeyFromRawBytes(constants.Curve,
			hash[:32])
		if err != nil {
			return errors.New("failed to create private key from address: " +
				err.Error())
		}
		target = new(identity.Foreign)
		target.EncryptionKey = &privKey.PublicKey
	case *objects.PubkeyV2, *objects.PubkeyV3,
		*objects.GetpubkeyV3, *objects.GetpubkeyV4:
		target = new(identity.Foreign)
	}
	if target.NonceTrialsPerByte < constants.POWDefaultNonceTrialsPerByte {
		target.NonceTrialsPerByte = constants.POWDefaultNonceTrialsPerByte
	}
	if target.ExtraBytes < constants.POWDefaultNonceTrialsPerByte {
		target.ExtraBytes = constants.POWDefaultNonceTrialsPerByte
	}
	if unenc, ok := msg.Payload.(EncryptablePayload); ok {
		enc, err := unenc.Encrypt(target.EncryptionKey)
		if err != nil {
			return errors.New("payload encryption failed: " + err.Error())
		}
		msg.Payload = enc  
	}
	if taggable, ok := msg.Payload.(TaggableEncryptedPayload); ok {
		taggable.SetTag(tag)
	}
	payload := msg.Payload.Serialize()
	objHeader := msg.HeaderSerialize()
	payloadLength := len(payload) + len(objHeader) + 8  
	powTarget := pow.CalculateTarget(payloadLength, ttl,
		int(target.NonceTrialsPerByte), int(target.ExtraBytes))
	hash := sha512.New()
	hash.Write(msg.HeaderSerialize())
	hash.Write(payload)
	msg.Nonce = pow.DoSequential(powTarget, hash.Sum(nil))
	return nil
}
func (msg *ObjectMessage) setPayloadType() {
	msg.Payload = &objects.Unrecognized{}
	corrupt := &objects.Corrupt{}
	switch msg.ObjectType {
	case GetpubkeyObject:
		switch msg.Version {
		case 2:
			fallthrough
		case 3:
			msg.Payload = &objects.GetpubkeyV3{}
		case 4:
			msg.Payload = &objects.GetpubkeyV4{}
		default:
			msg.Payload = corrupt
		}
	case PubkeyObject:
		switch msg.Version {
		case 2:
			msg.Payload = &objects.PubkeyV2{}
		case 3:
			msg.Payload = &objects.PubkeyV3{}
		case 4:
			msg.Payload = &objects.PubkeyEncryptedV4{}
		default:
			msg.Payload = corrupt
		}
	case MsgObject:
		if int(msg.Version) == 1 {  
			msg.Payload = &objects.MsgEncrypted{}
		} else {
			msg.Payload = corrupt
		}
	case BroadcastObject:
		switch msg.Version {
		case 4:
			msg.Payload = &objects.BroadcastEncryptedV4{}
		case 5:
			msg.Payload = &objects.BroadcastEncryptedV5{}
		default:
			msg.Payload = corrupt
		}
	}
}
var InvalidPayloadOperationError = errors.New("intended operation not defined" +
	" for this payload")