// SessionAnchor returns the decrypted and verified session anchor for KeyInit. func (ki *KeyInit) SessionAnchor(sigPubKey string) (*SessionAnchor, error) { // SIGKEYHASH corresponds to the SIGKEY of the Identity pubKey, err := base64.Decode(sigPubKey) if err != nil { return nil, err } keyHash := cipher.SHA512(pubKey) if ki.Contents.SIGKEYHASH != base64.Encode(cipher.SHA512(keyHash)) { log.Error(ErrWrongSigKeyHash) return nil, ErrWrongSigKeyHash } // verify that SESSIONANCHORHASH matches decrypted SESSIONANCHOR enc, err := base64.Decode(ki.Contents.SESSIONANCHOR) if err != nil { return nil, err } txt := cipher.AES256CTRDecrypt(keyHash[:32], enc) var sa SessionAnchor if err := json.Unmarshal(txt, &sa); err != nil { return nil, log.Error(err) } if ki.Contents.SESSIONANCHORHASH != base64.Encode(cipher.SHA512(sa.json())) { log.Error(ErrSessionAnchor) return nil, ErrSessionAnchor } return &sa, nil }
// VerifyUserSig verifies that the user-signature of UIDMessage is valid. func (msg *Message) VerifyUserSig(preMsg *Message) error { var ed25519Key cipher.Ed25519Key // check message counter if preMsg.UIDContent.MSGCOUNT+1 != msg.UIDContent.MSGCOUNT { return log.Error(ErrIncrement) } // get content content := msg.UIDContent.JSON() // get self-signature selfsig, err := base64.Decode(msg.USERSIGNATURE) if err != nil { return err } // create ed25519 key pubKey, err := base64.Decode(preMsg.UIDContent.SIGKEY.PUBKEY) if err != nil { return err } if err := ed25519Key.SetPublicKey(pubKey); err != nil { return err } // verify self-signature if !ed25519Key.Verify(content, selfsig) { return log.Error(ErrInvalidUserSig) } return nil }
// Verify verifies that the KeyInit is valid and contains a valid ECDHE25519 // key. func (ki *KeyInit) Verify(keyInitRepositoryURIs []string, sigPubKey string) error { // The REPOURI points to this KeyInit Repository if !util.ContainsString(keyInitRepositoryURIs, ki.Contents.REPOURI) { log.Error(ErrRepoURI) return ErrRepoURI } // verify that SESSIONANCHORHASH matches decrypted SESSIONANCHOR sa, err := ki.SessionAnchor(sigPubKey) if err != nil { return err } // get KeyEntry message from SessionAnchor ke, err := sa.KeyEntry("ECDHE25519") if err != nil { return err } // verify KeyEntry message if err := ke.Verify(); err != nil { return err } // NOTAFTER and NOTBEFORE are valid if ki.Contents.NOTBEFORE >= ki.Contents.NOTAFTER { log.Error(ErrInvalidTimes) return ErrInvalidTimes } // not expired if ki.Contents.NOTAFTER < uint64(times.Now()) { log.Error(ErrExpired) return ErrExpired } // SIGNATURE was made with UIDMessage.UIDContent.SIGKEY over Contents var ed25519Key cipher.Ed25519Key sig, err := base64.Decode(ki.SIGNATURE) if err != nil { return err } pubKey, err := base64.Decode(sigPubKey) if err != nil { return err } // create ed25519 key ed25519Key.SetPublicKey(pubKey) // verify self-signature if !ed25519Key.Verify(ki.Contents.json(), sig) { log.Error(ErrInvalidKeyInitSig) return ErrInvalidKeyInitSig } return nil }
// GetAccount returns the privkey and server of the account for myID. func (msgDB *MsgDB) GetAccount( myID, contactID string, ) ( privkey *[ed25519.PrivateKeySize]byte, server string, secret *[64]byte, minDelay, maxDelay int32, lastMessageTime int64, err error, ) { if err := identity.IsMapped(myID); err != nil { return nil, "", nil, 0, 0, 0, log.Error(err) } if contactID != "" { if err := identity.IsMapped(contactID); err != nil { return nil, "", nil, 0, 0, 0, log.Error(err) } } // get MyID var mID int if err := msgDB.getNymUIDQuery.QueryRow(myID).Scan(&mID); err != nil { return nil, "", nil, 0, 0, 0, log.Error(err) } // get ContactID var cID int if contactID != "" { err := msgDB.getContactUIDQuery.QueryRow(mID, contactID).Scan(&cID) if err != nil { return nil, "", nil, 0, 0, 0, log.Error(err) } } // get account data var pks string var scrts string err = msgDB.getAccountQuery.QueryRow(mID, cID).Scan(&pks, &server, &scrts, &minDelay, &maxDelay, &lastMessageTime) if err != nil { return nil, "", nil, 0, 0, 0, log.Error(err) } // decode private key pk, err := base64.Decode(pks) if err != nil { return nil, "", nil, 0, 0, 0, log.Error(err) } privkey = new([ed25519.PrivateKeySize]byte) copy(privkey[:], pk) // decode secret scrt, err := base64.Decode(scrts) if err != nil { return nil, "", nil, 0, 0, 0, log.Error(err) } secret = new([64]byte) copy(secret[:], scrt) return }
// SetPrivateKey sets the private key to the given base64 encoded privkey // string. func (sa *SessionAnchor) SetPrivateKey(privkey string) error { key, err := base64.Decode(privkey) if err != nil { return err } return sa.PFKEYS[0].setPrivateKey(key) }
func TestSigKeyHash(t *testing.T) { msg, err := Create("*****@*****.**", false, "", "", Strict, hashchain.TestEntry, cipher.RandReader) if err != nil { t.Fatal(err) } if msg.Identity() != "*****@*****.**" { t.Error("wrong identity") } sigKeyHash, err := msg.SigKeyHash() if err != nil { t.Fatal(err) } sigPubKey, err := base64.Decode(msg.SigPubKey()) if err != nil { t.Fatal(err) } if sigKeyHash != base64.Encode(cipher.SHA512(cipher.SHA512(sigPubKey))) { t.Fatal("SIGKEYHASHs differ") } privKey := msg.PrivateEncKey() if err := msg.SetPrivateEncKey(privKey); err != nil { t.Fatal(err) } if privKey != msg.PrivateEncKey() { t.Error("private keys differ") } }
// SigKeyHash returns the SIGKEYHASH which corresponds to the sigPubKey. func SigKeyHash(sigPubKey string) (string, error) { keyHash, err := base64.Decode(sigPubKey) if err != nil { return "", err } return base64.Encode(cipher.SHA512(keyHash)), nil }
// SetPrivateEncKey sets the private encryption key to the given base64 encoded // privkey string. func (msg *Message) SetPrivateEncKey(privkey string) error { key, err := base64.Decode(privkey) if err != nil { return err } return msg.UIDContent.PUBKEYS[0].setPrivateKey(key) }
func printWalletKey(w io.Writer, privkey string) error { pk, err := base64.Decode(privkey) if err != nil { return err } fmt.Fprintf(w, "WALLETPUBKEY:\t%s\n", base64.Encode(pk[32:])) return nil }
func decodeED25519PubKeyBase64(p string) (*[ed25519.PublicKeySize]byte, error) { ret := new([ed25519.PublicKeySize]byte) pd, err := base64.Decode(p) if err != nil { return nil, err } copy(ret[:], pd) return ret, nil }
// TODO: extract method func decodeWalletKey(p string) (*[ed25519.PrivateKeySize]byte, error) { var ret [ed25519.PrivateKeySize]byte pd, err := base64.Decode(p) if err != nil { return nil, err } copy(ret[:], pd) return &ret, nil }
// VerifyNonce verifies the nonce signature with the given sigPubKey. func VerifyNonce(sigPubKey string, nonce uint64, signature string) error { var ed25519Key cipher.Ed25519Key sig, err := base64.Decode(signature) if err != nil { return err } pubKey, err := base64.Decode(sigPubKey) if err != nil { return err } if err := ed25519Key.SetPublicKey(pubKey); err != nil { return err } if !ed25519Key.Verify(encode.ToByte8(nonce), sig) { return log.Error(ErrInvalidNonceSig) } return nil }
// KeyInit returns a new KeyInit message for the given UID message. It also // returns the pubKeyHash and privateKey for convenient further use. // msgcount must increase for each message of the same type and user. // notafter is the unixtime after which the key(s) should not be used anymore. // notbefore is the unixtime before which the key(s) should not be used yet. // fallback determines if the key may serve as a fallback key. // repoURI is URI of the corresponding KeyInit repository. // Necessary randomness is read from rand. func (msg *Message) KeyInit( msgcount, notafter, notbefore uint64, fallback bool, repoURI, mixaddress, nymaddress string, rand io.Reader, ) (ki *KeyInit, pubKeyHash, privateKey string, err error) { var keyInit KeyInit // time checks if notbefore >= notafter { log.Error(ErrInvalidTimes) return nil, "", "", ErrInvalidTimes } if notafter < uint64(times.Now()) { log.Error(ErrExpired) return nil, "", "", ErrExpired } if notafter > uint64(times.Now())+MaxNotAfter { log.Error(ErrFuture) return nil, "", "", ErrFuture } // init keyInit.Contents.VERSION = ProtocolVersion keyInit.Contents.MSGCOUNT = msgcount keyInit.Contents.NOTAFTER = notafter keyInit.Contents.NOTBEFORE = notbefore keyInit.Contents.FALLBACK = fallback keyHash, err := base64.Decode(msg.UIDContent.SIGKEY.HASH) if err != nil { return nil, "", "", err } keyInit.Contents.SIGKEYHASH = base64.Encode(cipher.SHA512(keyHash)) // make sure REPOURIS is set to the first REPOURI of UIDContent.REPOURIS // TODO: support different KeyInit repository configurations if repoURI != msg.UIDContent.REPOURIS[0] { return nil, "", "", log.Error("uri: repoURI differs from msg.UIDContent.REPOURIS[0]") } keyInit.Contents.REPOURI = repoURI // create SessionAnchor sa, sah, pubKeyHash, privateKey, err := msg.sessionAnchor(keyHash, mixaddress, nymaddress, rand) if err != nil { return nil, "", "", err } keyInit.Contents.SESSIONANCHOR = sa keyInit.Contents.SESSIONANCHORHASH = sah // sign KeyInit: the content doesn't have to be hashed, because Ed25519 is // already taking care of that. sig := msg.UIDContent.SIGKEY.ed25519Key.Sign(keyInit.Contents.json()) keyInit.SIGNATURE = base64.Encode(sig) ki = &keyInit return }
// VerifySrvSig verifies the signature with the srvPubKey. func (ki *KeyInit) VerifySrvSig(signature, srvPubKey string) error { var ed25519Key cipher.Ed25519Key // get server-signature sig, err := base64.Decode(signature) if err != nil { return err } // create ed25519 key pubKey, err := base64.Decode(srvPubKey) if err != nil { return err } ed25519Key.SetPublicKey(pubKey) // verify server-signature if !ed25519Key.Verify(ki.JSON(), sig) { log.Error(ErrInvalidSrvSig) return ErrInvalidSrvSig } return nil }
func (pe *ProtoEngine) create( w io.Writer, minDelay, maxDelay int32, tokenString, nymaddress string, r io.Reader, ) error { msg, err := ioutil.ReadAll(r) if err != nil { return log.Error(err) } message, err := base64.Decode(string(msg)) if err != nil { return log.Error(err) } token, err := base64.Decode(tokenString) if err != nil { return log.Error(err) } na, err := base64.Decode(nymaddress) if err != nil { return log.Error(err) } mo := client.MessageInput{ SenderMinDelay: minDelay, SenderMaxDelay: maxDelay, Token: token, NymAddress: na, Message: message, SMTPPort: 587, //SmartHost: "mix.serviceguard.chavpn.net", // TODO: allow to set SmartHost CACert: def.CACert, }.Create() if mo.Error != nil { return log.Error(mo.Error) } envelope := mo.Marshal() if _, err := io.WriteString(w, base64.Encode(envelope)); err != nil { return log.Error(err) } return nil }
func TestHMAC(t *testing.T) { key, err := base64.Decode(encKey) if err != nil { t.Fatal(err) } buf, err := base64.Decode(encBuf) if err != nil { t.Fatal(err) } mac, err := base64.Decode(encMac) if err != nil { t.Fatal(err) } nmac := HMAC(key, buf) if !hmac.Equal(nmac, mac) { t.Fatal("HMACs differ") } if len(nmac) != 64 { t.Errorf("HMAC has wrong length: %d", len(nmac)) } }
// PublicKey decodes the 32-byte public key from the given UID message and // returns it. func (msg *Message) PublicKey() (*[32]byte, error) { publicKey, err := base64.Decode(msg.PubKey().PUBKEY) if err != nil { return nil, err } // TODO: use other APIs from stdlib which do not require copy and panic var pk [32]byte if len(publicKey) != 32 { panic("uid: len(publicKey) != 32") } copy(pk[:], publicKey) return &pk, nil }
func decrypt(sender, recipient *uid.Message, r io.Reader, recipientTemp *uid.KeyEntry, privateKey string, sign bool, chkMsg bool) error { // decrypt var res bytes.Buffer identities := []*uid.Message{recipient} input := base64.NewDecoder(r) version, preHeader, err := ReadFirstOuterHeader(input) if err != nil { return err } if version != Version { return errors.New("wrong version") } ms := memstore.New() if err := recipientTemp.SetPrivateKey(privateKey); err != nil { return err } ms.AddPrivateKeyEntry(recipientTemp) args := &DecryptArgs{ Writer: &res, Identities: identities, PreHeader: preHeader, Reader: input, Rand: cipher.RandReader, KeyStore: ms, } _, sig, err := Decrypt(args) if err != nil { return err } // do not compare messages when fuzzing, because messages have to be different! if chkMsg && res.String() != msgs.Message1 { return errors.New("messages differ") } if sign { contentHash := cipher.SHA512(res.Bytes()) decSig, err := base64.Decode(sig) if err != nil { return err } if len(decSig) != ed25519.SignatureSize { return errors.New("signature has wrong length") } var sigBuf [ed25519.SignatureSize]byte copy(sigBuf[:], decSig) if !ed25519.Verify(sender.PublicSigKey32(), contentHash, &sigBuf) { return errors.New("signature verification failed") } } return nil }
// Decrypt decrypts the message reply and returns the resulting UIDIndex and // UIDMesssage. func (reply *MessageReply) Decrypt(UIDHash []byte) ([]byte, *Message, error) { UIDMessageEncrypted, err := base64.Decode(reply.ENTRY.UIDMESSAGEENCRYPTED) if err != nil { return nil, nil, log.Error(err) } UIDIndex := UIDMessageEncrypted[:sha256.Size] enc := UIDMessageEncrypted[sha256.Size:] Message := cipher.AES256CTRDecrypt(UIDHash, enc) uid, err := NewJSON(string(Message)) if err != nil { return nil, nil, log.Error(err) } return UIDIndex, uid, nil }
// VerifySelfSig verifies that the self-signature of UIDMessage is valid. func (msg *Message) VerifySelfSig() error { var ed25519Key cipher.Ed25519Key // get content content := msg.UIDContent.JSON() // get self-signature selfsig, err := base64.Decode(msg.SELFSIGNATURE) if err != nil { return err } // create ed25519 key pubKey, err := base64.Decode(msg.UIDContent.SIGKEY.PUBKEY) if err != nil { return err } if err := ed25519Key.SetPublicKey(pubKey); err != nil { return err } // verify self-signature if !ed25519Key.Verify(content, selfsig) { return log.Error(ErrInvalidSelfSig) } return nil }
// VerifySrvSig verifies that the server-signature of MessageReply is valid. func (reply *MessageReply) VerifySrvSig(msg *Message, srvPubKey string) error { // make sure messages match UIDHash, UIDIndex, _ := msg.Encrypt() idx, msg, err := reply.Decrypt(UIDHash) if err != nil { return err } if !bytes.Equal(idx, UIDIndex) { return log.Error(ErrMsgMismatch) } if !bytes.Equal(msg.JSON(), msg.JSON()) { return log.Error(ErrMsgMismatch) } // verify server signature var ed25519Key cipher.Ed25519Key // get content content := reply.ENTRY.json() // get server-signature sig, err := base64.Decode(reply.SERVERSIGNATURE) if err != nil { return log.Error(err) } // create ed25519 key pubKey, err := base64.Decode(srvPubKey) if err != nil { return log.Error(err) } if err := ed25519Key.SetPublicKey(pubKey); err != nil { return err } // verify server-signature if !ed25519Key.Verify(content, sig) { return log.Error(ErrInvalidSrvSig) } return nil }
// GetChainKey implements corresponding method for msg.KeyStore interface. func (ce *CryptEngine) GetChainKey(sessionKey string) (*[32]byte, error) { _, chainKey, _, err := ce.keyDB.GetSession(sessionKey) if err != nil { return nil, err } // decode chain key var key [32]byte k, err := base64.Decode(chainKey) if err != nil { return nil, log.Error("cryptengine: cannot decode chain key") } if copy(key[:], k) != 32 { return nil, log.Errorf("cryptengine: chain key has wrong length") } return &key, nil }
// GetRootKeyHash implements corresponding method for msg.KeyStore interface. func (ce *CryptEngine) GetRootKeyHash(sessionKey string) (*[64]byte, error) { rootKeyHash, _, _, err := ce.keyDB.GetSession(sessionKey) if err != nil { return nil, err } // decode root key hash var hash [64]byte k, err := base64.Decode(rootKeyHash) if err != nil { return nil, log.Error("cryptengine: cannot decode root key hash") } if copy(hash[:], k) != 64 { return nil, log.Errorf("cryptengine: root key hash has wrong length") } return &hash, nil }
func (ce *CtrlEngine) translateError(err error) error { switch err { case client.ErrNoUser: var walletPubkey string var pk []byte privkey, err := ce.msgDB.GetValue(msgdb.WalletKey) if err == nil { pk, err = base64.Decode(privkey) } if err == nil { walletPubkey = base64.Encode(pk[32:]) } return fmt.Errorf("Unfortunately, you do not have tokens, yet!\n"+ "Please send your \n"+ "WALLETPUBKEY\t%s\n"+ "per email to [email protected] and stay tuned!", walletPubkey) default: return err } }
func (pe *ProtoEngine) deliver(statusfp io.Writer, r io.Reader) error { enc, err := ioutil.ReadAll(r) if err != nil { return log.Error(err) } var mm client.MessageMarshalled mm, err = base64.Decode(string(enc)) if err != nil { return log.Error(err) } messageOut, err := mm.Unmarshal().Deliver() if err != nil { if messageOut.Resend { log.Info("write: RESEND:\t%s", err.Error()) fmt.Fprintf(statusfp, "RESEND:\t%s\n", err.Error()) return nil } return log.Error(err) } return nil }
// GetMessageKey implements corresponding method for msg.KeyStore interface. func (ce *CryptEngine) GetMessageKey( sessionKey string, sender bool, msgIndex uint64, ) (*[64]byte, error) { key, err := ce.keyDB.GetMessageKey(sessionKey, sender, msgIndex) if err != nil { return nil, err } // decode key var messageKey [64]byte k, err := base64.Decode(key) if err != nil { return nil, log.Errorf("cryptengine: cannot decode key for %s", sessionKey) } if copy(messageKey[:], k) != 64 { return nil, log.Errorf("cryptengine: key for %s has wrong length", sessionKey) } return &messageKey, nil }
// SplitEntry splits a base64 encoded key hashchain entry. Specification: // https://github.com/mutecomm/mute/blob/master/doc/keyserver.md#key-hashchain-operation func SplitEntry(entry string) (hash, typ, nonce, hashID, crUID, uidIndex []byte, err error) { e, err := base64.Decode(entry) if err != nil { return nil, nil, nil, nil, nil, nil, log.Error(err) } if len(e) != EntryByteLen { return nil, nil, nil, nil, nil, nil, log.Errorf("hashchain: entry '%s' does not have byte length %d (but %d)", entry, EntryByteLen, len(e)) } // HASH(entry[n]) | TYPE | NONCE | HashID | CrUID | UIDIndex hash = e[:32] typ = e[32:33] nonce = e[33:41] hashID = e[41:73] crUID = e[73:121] uidIndex = e[121:] // check type if !bytes.Equal(typ, Type) { return nil, nil, nil, nil, nil, nil, log.Errorf("hashchain: wrong type 0x%x (should be 0x%x)", typ, Type) } return }
func (pe *ProtoEngine) fetch( output io.Writer, status io.Writer, server string, lastMessageTime int64, command io.Reader, ) error { // read passphrase log.Infof("read private key from fd %d", pe.fileTable.PassphraseFD) pks, err := util.Readline(pe.fileTable.PassphraseFP) if err != nil { return err } log.Info("done") pk, err := base64.Decode(string(pks)) if err != nil { return log.Error(err) } var privkey [ed25519.PrivateKeySize]byte copy(privkey[:], pk) log.Debugf("lastMessageTime=%d", lastMessageTime) messages, err := client.ListMessages(&privkey, lastMessageTime, server, def.CACert) if err != nil { // TODO: handle this better if err.Error() == "accountdb: Nothing found" { // no messages found log.Info("write: NONE") fmt.Fprintln(status, "NONE") return nil } return log.Error(err) } /* for _, message := range messages { messageID := base64.Encode(message.MessageID) log.Debugf("messageID=%s, ReceiveTime=%d, ReadTime=%d", messageID, message.ReceiveTime, message.ReadTime) } */ scanner := bufio.NewScanner(command) for _, message := range messages { msg, err := client.FetchMessage(&privkey, message.MessageID, server, def.CACert) if err != nil { return log.Error(err) } messageID := base64.Encode(message.MessageID) log.Debugf("write: MESSAGEID:\t%s", messageID) fmt.Fprintf(status, "MESSAGEID:\t%s\n", messageID) var command string if scanner.Scan() { command = scanner.Text() } else { return log.Error("protoengine: expecting command input") } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "reading standard input:", err) } if command == "NEXT" { log.Debug("read: NEXT") enc := base64.Encode(msg) if _, err := io.WriteString(output, enc); err != nil { return log.Error(err) } log.Debugf("write: LENGTH:\t%d", len(enc)) fmt.Fprintf(status, "LENGTH:\t%d\n", len(enc)) log.Debugf("write: RECEIVETIME:\t%d", message.ReceiveTime) fmt.Fprintf(status, "RECEIVETIME:\t%d\n", message.ReceiveTime) } else if command == "QUIT" { log.Debug("read: QUIT") return nil } else { return log.Errorf("protoengine: unknown command '%s'", command) } } // no more messages log.Info("write: NONE") fmt.Fprintln(status, "NONE") return nil }
func (ce *CtrlEngine) procInQueue(c *cli.Context, host string) error { log.Debug("procInQueue()") for { // get message from msgDB iqIdx, myID, contactID, msg, envelope, err := ce.msgDB.GetInQueue() if err != nil { return err } if myID == "" { log.Debug("no more messages in inqueue") break // no more messages in inqueue } if envelope { log.Debugf("decrypt envelope (iqIdx=%d)", iqIdx) // decrypt envelope message, err := base64.Decode(msg) if err != nil { return log.Error(err) } privkey, server, secret, _, _, _, err := ce.msgDB.GetAccount(myID, contactID) if err != nil { return err } receiveTemplate := nymaddr.AddressTemplate{ Secret: secret[:], } var pubkey [32]byte copy(pubkey[:], privkey[32:]) dec, nym, err := mixcrypt.ReceiveFromMix(receiveTemplate, util.MailboxAddress(&pubkey, server), message) if err != nil { return log.Error(err) } if !bytes.Equal(nym, cipher.SHA256([]byte(myID))) { // discard message log.Warnf("ctrlengine: hashed nym does not match %s -> discard message", myID) if err := ce.msgDB.DelInQueue(iqIdx); err != nil { return err } } else { log.Info("envelope successfully decrypted") err := ce.msgDB.SetInQueue(iqIdx, base64.Encode(dec)) if err != nil { return err } } } else { log.Debugf("decrypt message (iqIdx=%d)", iqIdx) senderID, plainMsg, err := mutecryptDecrypt(c, ce.passphrase, []byte(msg), ce.fileTable.StatusFP) if err != nil { return err } if senderID == "" { // message could not be decrypted, but we do not want to fail if err := ce.msgDB.DelInQueue(iqIdx); err != nil { return err } continue } // check if contact exists contact, _, contactType, err := ce.msgDB.GetContact(myID, senderID) if err != nil { return log.Error(err) } // TODO: we do not have to do request UID message from server // here, but we should use the one contained in the message and // compare it with hash chain entry (doesn't compromise anonymity) var drop bool if contact == "" { err := ce.contactAdd(myID, senderID, "", host, msgdb.GrayList, c) if err != nil { return log.Error(err) } } else if contactType == msgdb.BlackList { // messages from black listed contacts are dropped directly log.Debug("message from black listed contact dropped") drop = true } err = ce.msgDB.RemoveInQueue(iqIdx, plainMsg, senderID, drop) if err != nil { return err } } } return nil }
func (ce *CtrlEngine) procOutQueue( c *cli.Context, nym string, failDelivery bool, ) error { log.Debug("procOutQueue()") for { oqIdx, msg, nymaddress, minDelay, maxDelay, envelope, err := ce.msgDB.GetOutQueue(nym) if err != nil { return err } if msg == "" { log.Debug("break") break // no more messages in outqueue } if !envelope { log.Debug("envelope") // parse nymaddress na, err := base64.Decode(nymaddress) if err != nil { return log.Error(na) } addr, err := nymaddr.ParseAddress(na) if err != nil { return err } // get token from wallet var pubkey [32]byte copy(pubkey[:], addr.TokenPubKey) token, err := wallet.GetToken(ce.client, "Message", &pubkey) if err != nil { return err } // `muteproto create` env, err := muteprotoCreate(c, msg, minDelay, maxDelay, base64.Encode(token.Token), nymaddress) if err != nil { return log.Error(err) } // update outqueue if err := ce.msgDB.SetOutQueue(oqIdx, env); err != nil { ce.client.UnlockToken(token.Hash) return err } ce.client.DelToken(token.Hash) msg = env } // `muteproto deliver` if failDelivery { return log.Error(ErrDeliveryFailed) } sendTime := times.Now() + int64(minDelay) // earliest resend, err := muteprotoDeliver(c, msg) if err != nil { // If the message delivery failed because the token expired in the // meantime we retract the message from the outqueue (setting it // back to 'ToSend') and start the delivery process for this // message all over again. // Matching the error message string is not optimal, but the best // available solution since the error results from calling another // binary (muteproto). if strings.HasSuffix(err.Error(), client.ErrFinal.Error()) { log.Debug("retract") if err := ce.msgDB.RetractOutQueue(oqIdx); err != nil { return err } continue } return log.Error(err) } if resend { // set resend status log.Debug("resend") if err := ce.msgDB.SetResendOutQueue(oqIdx); err != nil { return err } } else { // remove from outqueue log.Debug("remove") if err := ce.msgDB.RemoveOutQueue(oqIdx, sendTime); err != nil { return err } } } return nil }