func TestMessage(t *testing.T) { log := make(chan string, 100) priv, x, y := encryption.CreateKey(log) pub := elliptic.Marshal(elliptic.P256(), x, y) address := encryption.GetAddress(log, x, y) msg := new(Message) msg.AddrHash = MakeHash(address) msg.TxidHash = MakeHash([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}) msg.Timestamp = time.Now().Round(time.Second) msg.Content = *encryption.Encrypt(log, pub, "Hello World!") mBytes := msg.GetBytes() if mBytes == nil { fmt.Println("Error Encoding Message!") t.FailNow() } msg2 := new(Message) msg2.FromBytes(mBytes) if string(msg2.AddrHash.GetBytes()) != string(msg.AddrHash.GetBytes()) || string(msg2.TxidHash.GetBytes()) != string(msg.TxidHash.GetBytes()) || msg2.Timestamp.Unix() != msg.Timestamp.Unix() { fmt.Println("Message Header incorrect: ", msg2) t.FailNow() } if string(encryption.Decrypt(log, priv, &msg.Content)[:12]) != "Hello World!" { fmt.Println("Message content incorrect: ", string(encryption.Decrypt(log, priv, &msg.Content)[:12])) t.Fail() } }
// Handle Pubkey, Message, and Purge Registration func register(config *api.ApiConfig) { var message objects.Message var txid [16]byte for { select { case pubHash := <-config.PubkeyRegister: // Check if pubkey is in database... pubkey := checkPubkey(config, pubHash) if pubkey == nil { break } outbox := localdb.GetBox(localdb.OUTBOX) for _, metamsg := range outbox { recvHash := objects.MakeHash([]byte(metamsg.Recipient)) if string(pubHash.GetBytes()) == string(recvHash.GetBytes()) { // Send message and move to sendbox msg, err := localdb.GetMessageDetail(metamsg.TxidHash) if err != nil { config.Log <- err.Error() break } msg.Encrypted = encryption.Encrypt(config.Log, pubkey, string(msg.Decrypted.GetBytes())) msg.MetaMessage.Timestamp = time.Now().Round(time.Second) err = localdb.AddUpdateMessage(msg, localdb.SENDBOX) if err != nil { config.Log <- err.Error() break } sendMsg := new(objects.Message) sendMsg.Timestamp = msg.MetaMessage.Timestamp sendMsg.TxidHash = msg.MetaMessage.TxidHash sendMsg.AddrHash = recvHash sendMsg.Content = *msg.Encrypted config.RecvQueue <- *objects.MakeFrame(objects.MSG, objects.BROADCAST, sendMsg) } } case message = <-config.MessageRegister: // If address is registered, store message in inbox detail, err := localdb.GetAddressDetail(message.AddrHash) if err != nil { config.Log <- "Message address not in database..." break } if !detail.IsRegistered { config.Log <- "Message not for registered address..." break } config.Log <- "Registering new encrypted message..." msg := new(objects.FullMessage) msg.MetaMessage.TxidHash = message.TxidHash msg.MetaMessage.Timestamp = message.Timestamp msg.MetaMessage.Recipient = detail.String msg.Encrypted = &message.Content err = localdb.AddUpdateMessage(msg, localdb.INBOX) if err != nil { config.Log <- err.Error() } case message = <-config.PubRegister: // If address is registered, store message in inbox detail, err := localdb.GetAddressDetail(message.AddrHash) if err != nil { config.Log <- "Message address not in database..." break } if !detail.IsSubscribed { config.Log <- "Not Subscribed to Address..." break } config.Log <- "Registering new publication..." msg := new(objects.FullMessage) msg.MetaMessage.TxidHash = message.TxidHash msg.MetaMessage.Timestamp = message.Timestamp msg.MetaMessage.Sender = detail.String msg.MetaMessage.Recipient = "<Subscription Message>" msg.Encrypted = &message.Content msg.Decrypted = new(objects.DecryptedMessage) msg.Decrypted.FromBytes(encryption.DecryptPub(config.Log, detail.Pubkey, msg.Encrypted)) err = localdb.AddUpdateMessage(msg, localdb.INBOX) if err != nil { config.Log <- err.Error() } case txid = <-config.PurgeRegister: // If Message in database, mark as purged detail, err := localdb.GetMessageDetail(objects.MakeHash(txid[:])) if err != nil { break } detail.MetaMessage.Purged = true err = localdb.AddUpdateMessage(detail, -1) if err != nil { config.Log <- fmt.Sprintf("Error registering purge: %s", err) } } // End select } // End for } // End register
func (service *EMPService) SendMessage(r *http.Request, args *SendMsg, reply *SendResponse) error { if !basicAuth(service.Config, r) { service.Config.Log <- fmt.Sprintf("Unauthorized RPC Request from: %s", r.RemoteAddr) return errors.New("Unauthorized") } // Nil Check if len(args.Sender) == 0 || len(args.Recipient) == 0 || len(args.Plaintext) == 0 { return errors.New("All fields required except signature.") } var err error // Get Addresses sendAddr := encryption.StringToAddress(args.Sender) if len(sendAddr) == 0 { return errors.New("Invalid sender address!") } recvAddr := encryption.StringToAddress(args.Recipient) if len(recvAddr) == 0 { return errors.New("Invalid recipient address!") } sender, err := localdb.GetAddressDetail(objects.MakeHash(sendAddr)) if err != nil { return errors.New(fmt.Sprintf("Error pulling send address from Database: %s", err)) } if sender.Pubkey == nil { sender.Pubkey = checkPubkey(service.Config, objects.MakeHash(sendAddr)) if sender.Pubkey == nil { return errors.New("Sender's Public Key is required to send message!") } } if sender.Privkey == nil { return errors.New("SendMsg() requires a stored private key. Use SendRawMsg() instead.") } recipient, err := localdb.GetAddressDetail(objects.MakeHash(recvAddr)) if err != nil { return errors.New(fmt.Sprintf("Error pulling recipient address from Database: %s", err)) } // Create New Message msg := new(objects.FullMessage) msg.Decrypted = new(objects.DecryptedMessage) msg.Encrypted = nil // Fill out decrypted message n, err := rand.Read(msg.Decrypted.Txid[:]) if n < len(msg.Decrypted.Txid[:]) || err != nil { return errors.New(fmt.Sprintf("Problem with random reader: %s", err)) } copy(msg.Decrypted.Pubkey[:], sender.Pubkey) msg.Decrypted.Subject = args.Subject msg.Decrypted.MimeType = "text/plain" msg.Decrypted.Content = args.Plaintext msg.Decrypted.Length = uint32(len(msg.Decrypted.Content)) // Fill Out Meta Message (save timestamp) msg.MetaMessage.Purged = false msg.MetaMessage.TxidHash = objects.MakeHash(msg.Decrypted.Txid[:]) msg.MetaMessage.Sender = sender.String msg.MetaMessage.Recipient = recipient.String // Get Signature priv := new(ecdsa.PrivateKey) priv.PublicKey.Curve = encryption.GetCurve() priv.D = new(big.Int) priv.D.SetBytes(sender.Privkey) sign := msg.Decrypted.GetBytes() sign = sign[:len(sign)-65] signHash := objects.MakeHash(sign) x, y, err := ecdsa.Sign(rand.Reader, priv, signHash.GetBytes()) if err != nil { return err } copy(msg.Decrypted.Signature[:], encryption.MarshalPubkey(x, y)) // Check for pubkey if recipient.Pubkey == nil { recipient.Pubkey = checkPubkey(service.Config, objects.MakeHash(recipient.Address)) } if recipient.Pubkey == nil { reply.IsSent = false // Add message to outbox... err = localdb.AddUpdateMessage(msg, localdb.OUTBOX) if err != nil { return err } } else { // Send message and add to sendbox... msg.Encrypted = encryption.Encrypt(service.Config.Log, recipient.Pubkey, string(msg.Decrypted.GetBytes())) msg.MetaMessage.Timestamp = time.Now().Round(time.Second) err = localdb.AddUpdateMessage(msg, localdb.SENDBOX) if err != nil { return err } sendMsg := new(objects.Message) sendMsg.TxidHash = msg.MetaMessage.TxidHash sendMsg.AddrHash = objects.MakeHash(recipient.Address) sendMsg.Timestamp = msg.MetaMessage.Timestamp sendMsg.Content = *msg.Encrypted service.Config.RecvQueue <- *objects.MakeFrame(objects.MSG, objects.BROADCAST, sendMsg) reply.IsSent = true } // Finish by setting msg's txid reply.TxidHash = msg.MetaMessage.TxidHash.GetBytes() return nil }