Ejemplo n.º 1
0
// 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
}
Ejemplo n.º 2
0
// 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
}
Ejemplo n.º 3
0
// 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
}
Ejemplo n.º 4
0
// 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
}
Ejemplo n.º 5
0
// 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)
}
Ejemplo n.º 6
0
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")
	}
}
Ejemplo n.º 7
0
// 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
}
Ejemplo n.º 8
0
// 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)
}
Ejemplo n.º 9
0
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
}
Ejemplo n.º 10
0
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
}
Ejemplo n.º 11
0
// 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
}
Ejemplo n.º 12
0
// 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
}
Ejemplo n.º 13
0
// 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
}
Ejemplo n.º 14
0
// 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
}
Ejemplo n.º 15
0
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
}
Ejemplo n.º 16
0
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))
	}
}
Ejemplo n.º 17
0
// 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
}
Ejemplo n.º 18
0
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
}
Ejemplo n.º 19
0
// 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
}
Ejemplo n.º 20
0
// 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
}
Ejemplo n.º 21
0
// 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
}
Ejemplo n.º 22
0
// 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
}
Ejemplo n.º 23
0
// 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
}
Ejemplo n.º 24
0
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
	}
}
Ejemplo n.º 25
0
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
}
Ejemplo n.º 26
0
// 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
}
Ejemplo n.º 27
0
// 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
}
Ejemplo n.º 28
0
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
}
Ejemplo n.º 29
0
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
}
Ejemplo n.º 30
0
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
}