Esempio n. 1
0
// Domain returns the domain of the uid identity.
func (msg *Message) Domain() string {
	_, domain, err := identity.Split(msg.UIDContent.IDENTITY)
	if err != nil {
		// UID messages have to be valid
		panic(log.Critical(err))
	}
	return domain
}
Esempio n. 2
0
// Localpart returns the localpart of the uid identity.
func (msg *Message) Localpart() string {
	lp, _, err := identity.Split(msg.UIDContent.IDENTITY)
	if err != nil {
		// UID messages have to be valid
		panic(log.Critical(err))
	}
	return lp
}
Esempio n. 3
0
// Check that the content of the UID message is consistent with it's version.
func (msg *Message) Check() error {
	// we only support version 1.0 at this stage
	if msg.UIDContent.VERSION != "1.0" {
		return log.Errorf("uid: unknown UIDContent.VERSION: %s",
			msg.UIDContent.VERSION)
	}
	// generic checks
	optional := Optional.String()
	if msg.UIDContent.PREFERENCES.FORWARDSEC != optional {
		if msg.UIDContent.MIXADDRESS != "" {
			return log.Errorf("uid: MIXADDRESS must be null, if FORWARDSEC is not %q",
				optional)
		}
		if msg.UIDContent.NYMADDRESS != "" {
			return log.Errorf("uid: NYMADDRESS must be null, if FORWARDSEC is not %q",
				optional)
		}
	}
	if err := identity.IsMapped(msg.UIDContent.IDENTITY); err != nil {
		return log.Error(err)
	}
	// check SIGKEY
	if msg.UIDContent.SIGKEY.CIPHERSUITE != DefaultCiphersuite {
		return log.Error("uid: UIDContent.SIGKEY.CIPHERSUITE != DefaultCiphersuite")
	}
	if msg.UIDContent.SIGKEY.FUNCTION != "ED25519" {
		return log.Error("uid: UIDContent.SIGKEY.FUNCTION != \"ED25519\"")
	}
	// make sure LASTENTRY is parseable for a non-keyserver localpart.
	// For keyservers the LASTENTRY can be empty, iff this is the first entry
	// in the hashchain.
	lp, _, _ := identity.Split(msg.UIDContent.IDENTITY)
	if lp != "keyserver" {
		_, _, _, _, _, _, err := hashchain.SplitEntry(msg.UIDContent.LASTENTRY)
		if err != nil {
			return err
		}
	}
	// make sure ESCROWSIGNATURE and USERSIGNATURE are not set at the same time
	if msg.ESCROWSIGNATURE != "" && msg.USERSIGNATURE != "" {
		return log.Error("uid: USERSIGNATURE and ESCROWSIGNATURE cannot be set at the same time")
	}

	// version 1.0 specific checks
	return msg.checkV1_0()
}
Esempio n. 4
0
// GetPrivateIdentitiesForDomain returns all private identities for the given
// domain from keyDB.
func (keyDB *KeyDB) GetPrivateIdentitiesForDomain(domain string) ([]string, error) {
	var identities []string
	all, err := keyDB.GetPrivateIdentities()
	if err != nil {
		return nil, err
	}
	dmn := identity.MapDomain(domain)
	for _, id := range all {
		_, idDomain, err := identity.Split(id)
		if err != nil {
			return nil, err
		}
		if idDomain == dmn {
			identities = append(identities, id)
		}
	}
	return identities, nil
}
Esempio n. 5
0
func (msg *Message) checkV1_0() error {
	// UIDContent.PREFERENCES.FORWARDSEC must be "strict"
	strict := Strict.String()
	if msg.UIDContent.PREFERENCES.FORWARDSEC != strict {
		return log.Errorf("uid: FORWARDSEC must be %q", strict)
	}
	// UIDContent.PUBKEYS contains exactly one ECDHE25519 key for the default
	// ciphersuite
	if len(msg.UIDContent.PUBKEYS) != 1 {
		return log.Error("uid: UIDContent.PUBKEYS must contain exactly one key")
	}
	if msg.UIDContent.PUBKEYS[0].CIPHERSUITE != DefaultCiphersuite {
		return log.Error("uid: UIDContent.PUBKEYS[0].CIPHERSUITE != DefaultCiphersuite")
	}
	if msg.UIDContent.PUBKEYS[0].FUNCTION != "ECDHE25519" {
		return log.Error("uid: UIDContent.PUBKEYS[0].FUNCTION != \"ECDHE25519\"")
	}
	// UIDContent.SIGESCROW must be zero-value.
	if msg.UIDContent.SIGESCROW != nil {
		if msg.UIDContent.SIGESCROW.CIPHERSUITE != "" ||
			msg.UIDContent.SIGESCROW.FUNCTION != "" ||
			msg.UIDContent.SIGESCROW.HASH != "" ||
			msg.UIDContent.SIGESCROW.PUBKEY != "" {
			return log.Error("uid: UIDContent.SIGESCROW must be zero-value")
		}
	}
	// UIDContent.REPOURIS contains one entry which is the domain of
	// UIDContent.IDENTITY
	_, domain, _ := identity.Split(msg.UIDContent.IDENTITY)
	if len(msg.UIDContent.REPOURIS) != 1 ||
		msg.UIDContent.REPOURIS[0] != domain {
		return log.Error("uid: UIDContent.REPOURIS must contain one entry (domain of identity)")
	}

	// UIDContent.CHAINLINK must be zero-value
	if msg.UIDContent.CHAINLINK != nil {
		if !reflect.DeepEqual(msg.UIDContent.CHAINLINK, chainlink{}) {
			return log.Error("uid: UIDContent.CHAINLINK must be zero-value")
		}
	}
	return nil
}
Esempio n. 6
0
// Create creates a new UID message for the given userID and self-signs it.
// It automatically creates all necessary keys. If sigescrow is true,  an
// escrow key is included in the created UID message.
// Necessary randomness is read from rand.
func Create(
	userID string,
	sigescrow bool,
	mixaddress, nymaddress string,
	pfsPreference PFSPreference,
	lastEntry string,
	rand io.Reader,
) (*Message, error) {
	var msg Message
	var err error
	// check user ID (identity)
	if err := identity.IsMapped(userID); err != nil {
		return nil, log.Error(err)
	}
	msg.UIDContent.VERSION = ProtocolVersion
	msg.UIDContent.MSGCOUNT = 0                            // this is the first UIDMessage
	msg.UIDContent.NOTAFTER = uint64(times.OneYearLater()) // TODO: make this settable!
	msg.UIDContent.NOTBEFORE = 0                           // TODO: make this settable
	if pfsPreference == Optional {
		msg.UIDContent.MIXADDRESS = mixaddress
		msg.UIDContent.NYMADDRESS = nymaddress
	} else {
		msg.UIDContent.MIXADDRESS = ""
		msg.UIDContent.NYMADDRESS = ""
	}
	msg.UIDContent.IDENTITY = userID
	if err = msg.UIDContent.SIGKEY.initSigKey(rand); err != nil {
		return nil, err
	}
	msg.UIDContent.PUBKEYS = make([]KeyEntry, 1)
	if err := msg.UIDContent.PUBKEYS[0].InitDHKey(rand); err != nil {
		return nil, err
	}
	if sigescrow {
		msg.UIDContent.SIGESCROW = new(KeyEntry)
		if err = msg.UIDContent.SIGESCROW.initSigKey(rand); err != nil {
			return nil, err
		}
	}
	// make sure LASTENTRY is parseable for a non-keyserver localpart.
	// For keyservers the LASTENTRY can be empty, iff this is the first entry
	// in the hashchain.
	lp, domain, _ := identity.Split(msg.UIDContent.IDENTITY)
	if lp != "keyserver" {
		if _, _, _, _, _, _, err := hashchain.SplitEntry(lastEntry); err != nil {
			return nil, err
		}
	}
	msg.UIDContent.LASTENTRY = lastEntry

	// set REPOURIS to the domain of UIDContent.IDENTITY
	// TODO: support different KeyInit repository configurations
	msg.UIDContent.REPOURIS = []string{domain}

	msg.UIDContent.PREFERENCES.FORWARDSEC = pfsPreference.String()
	msg.UIDContent.PREFERENCES.CIPHERSUITES = []string{DefaultCiphersuite}

	// TODO: CHAINLINK (later protocol version)

	// theses signatures are always empty for messages the first UIDMessage
	msg.ESCROWSIGNATURE = ""
	msg.USERSIGNATURE = ""

	selfsig := msg.UIDContent.SIGKEY.ed25519Key.Sign(msg.UIDContent.JSON())
	msg.SELFSIGNATURE = base64.Encode(selfsig)

	// TODO: LINKAUTHORITY

	return &msg, nil
}
Esempio n. 7
0
func (ce *CtrlEngine) msgSend(
	c *cli.Context,
	id string,
	all bool,
	failDelivery bool,
) error {
	nyms, err := ce.getNyms(id, all)
	if err != nil {
		return err
	}
	for _, nym := range nyms {
		// clear resend status for old messages in outqueue
		if err := ce.msgDB.ClearResendOutQueue(nym); err != nil {
			return err
		}

		// process old messages in outqueue
		if err := ce.procOutQueue(c, nym, failDelivery); err != nil {
			return err
		}

		/*
			ids, err := ce.msgDB.GetMsgIDs(nym)
			if err != nil {
				return err
			}
			for _, id := range ids {
				log.Debugf("id=%d, to=%s", id.MsgID, id.To)
			}
		*/

		// add all undelivered messages to outqueue
		var recvNymAddress string
		for {
			msgID, peer, msg, sign, minDelay, maxDelay, err :=
				ce.msgDB.GetUndeliveredMessage(nym)
			if err != nil {
				return err
			}
			if peer == "" {
				log.Debug("break")
				break // no more undelivered messages
			}

			// determine recipient nymaddress for encryption, if necessary
			if recvNymAddress == "" {
				// TODO! (implement more accounts? delay settings?)
				privkey, server, secret, minDelay, maxDelay, _, err :=
					ce.msgDB.GetAccount(nym, "")
				if err != nil {
					return err
				}
				_, domain, err := identity.Split(nym)
				if err != nil {
					return err
				}
				expire := times.ThirtyDaysLater() // TODO: make this settable
				singleUse := false                // TODO correct?
				var pubkey [ed25519.PublicKeySize]byte
				copy(pubkey[:], privkey[32:])
				_, recvNymAddress, err = util.NewNymAddress(domain, secret[:],
					expire, singleUse, minDelay, maxDelay, nym, &pubkey, server,
					def.CACert)
				if err != nil {
					return err
				}
			}

			// encrypt
			enc, nymaddress, err := mutecryptEncrypt(c, nym, peer,
				ce.passphrase, msg, sign, recvNymAddress)
			if err != nil {
				return log.Error(err)
			}
			// add to outqueue
			log.Debug("add")
			err = ce.msgDB.AddOutQueue(nym, msgID, enc, nymaddress,
				minDelay, maxDelay)
			if err != nil {
				return log.Error(err)
			}
		}

		// process new messages in outqueue
		if err := ce.procOutQueue(c, nym, failDelivery); err != nil {
			return err
		}
	}
	return nil
}