Ejemplo n.º 1
0
func (ce *CryptEngine) verifyServerSig(
	uid *uid.Message,
	msgReply *uid.MessageReply,
	position uint64,
) error {
	// For the first keyserver message we do not need to verify the server signature
	if uid.Localpart() == "keyserver" && uid.UIDContent.MSGCOUNT == 0 {
		return nil
	}

	// Get keyserver UID
	srvUID, _, found, err := ce.keyDB.GetPublicUID("keyserver@"+uid.Domain(), position)
	if err != nil {
		return err
	}
	if !found {
		return log.Errorf("cryptengine: no keyserver signature key found for domain '%s'", uid.Domain())
	}

	// Verify server signature
	if err := msgReply.VerifySrvSig(uid, srvUID.UIDContent.SIGKEY.PUBKEY); err != nil {
		return log.Error(err)
	}
	return nil
}
Ejemplo n.º 2
0
// AddPrivateUIDReply adds the msgReply to the given UID message.
func (keyDB *KeyDB) AddPrivateUIDReply(
	msg *uid.Message,
	msgReply *uid.MessageReply,
) error {
	_, err := keyDB.addPrivateUIDReplyQuery.Exec(msgReply.JSON(), msg.JSON())
	if err != nil {
		return err
	}
	return nil
}
Ejemplo n.º 3
0
// AddPublicUID adds a public UID message and it's hash chain position to
// keyDB.
func (keyDB *KeyDB) AddPublicUID(msg *uid.Message, position uint64) error {
	_, err := keyDB.addPublicUIDQuery.Exec(
		msg.UIDContent.IDENTITY,
		msg.UIDContent.MSGCOUNT,
		position,
		msg.JSON(),
	)
	if err != nil {
		return err
	}
	return nil
}
Ejemplo n.º 4
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.º 5
0
// GetPublicKeyEntry implements corresponding method for msg.KeyStore interface.
func (ce *CryptEngine) GetPublicKeyEntry(uidMsg *uid.Message) (*uid.KeyEntry, string, error) {
	log.Debugf("ce.FindKeyEntry: uidMsg.Identity()=%s", uidMsg.Identity())
	// get KeyInit
	sigKeyHash, err := uidMsg.SigKeyHash()
	if err != nil {
		return nil, "", err
	}
	ki, err := ce.keyDB.GetPublicKeyInit(sigKeyHash)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, "", session.ErrNoKeyEntry
		}
		return nil, "", err
	}
	// decrypt SessionAnchor
	sa, err := ki.SessionAnchor(uidMsg.SigPubKey())
	if err != nil {
		return nil, "", err
	}
	// get KeyEntry message from SessionAnchor
	ke, err := sa.KeyEntry("ECDHE25519")
	if err != nil {
		return nil, "", err
	}
	return ke, sa.NymAddress(), nil
}
Ejemplo n.º 6
0
// AddPrivateUID adds a private uid to keyDB.
func (keyDB *KeyDB) AddPrivateUID(msg *uid.Message) error {
	_, err := keyDB.addPrivateUIDQuery.Exec(
		msg.UIDContent.IDENTITY,
		msg.UIDContent.MSGCOUNT,
		msg.JSON(),
		msg.PrivateSigKey(),
		msg.PrivateEncKey(),
		"",
	)
	if err != nil {
		return err
	}
	return nil
}
Ejemplo n.º 7
0
func TestPublicUID(t *testing.T) {
	tmpdir, keyDB, err := createDB()
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmpdir)
	defer keyDB.Close()
	a1, err := uid.Create("*****@*****.**", false, "", "", uid.Strict,
		hashchain.TestEntry, cipher.RandReader)
	if err != nil {
		t.Fatal(err)
	}
	a2, err := uid.Create("*****@*****.**", false, "", "", uid.Strict,
		hashchain.TestEntry, cipher.RandReader)
	if err != nil {
		t.Fatal(err)
	}
	if err := keyDB.AddPublicUID(a1, 10); err != nil {
		t.Fatal(err)
	}
	if err := keyDB.AddPublicUID(a2, 20); err != nil {
		t.Fatal(err)
	}
	var pos uint64
	var rA1 *uid.Message
	rA1, pos, _, err = keyDB.GetPublicUID("*****@*****.**", 10)
	if !bytes.Equal(rA1.JSON(), a1.JSON()) {
		t.Error("UID messages differ")
	}
	if pos != 10 {
		t.Error("a1 position should be 10")
	}
	var rA2 *uid.Message
	rA2, pos, _, err = keyDB.GetPublicUID("*****@*****.**", 30)
	if !bytes.Equal(rA2.JSON(), a2.JSON()) {
		t.Error("UID messages differ")
	}
	if pos != 20 {
		t.Error("a2 position should be 20")
	}
}
Ejemplo n.º 8
0
// DelPrivateUID deletes the given UID message from keyDB.
func (keyDB *KeyDB) DelPrivateUID(msg *uid.Message) error {
	if _, err := keyDB.delPrivateUIDQuery.Exec(msg.JSON()); err != nil {
		return err
	}
	return nil
}
Ejemplo n.º 9
0
func newHeader(
	sender, recipient *uid.Message,
	recipientTempHash string,
	senderSessionPub, nextSenderSessionPub,
	nextRecipientSessionPubSeen *uid.KeyEntry,
	nymAddress string,
	senderSessionCount, senderMessageCount uint64,
	senderLastKeychainHash string,
	rand io.Reader,
	statusCode StatusCode,
) (*header, error) {
	if len(senderLastKeychainHash) != hashchain.EntryBase64Len {
		return nil, log.Errorf("msg: last hashchain entry '%s' does not have base64 length %d (but %d)",
			senderLastKeychainHash, hashchain.EntryBase64Len, len(senderLastKeychainHash))
	}
	h := &header{
		Ciphersuite:                 uid.DefaultCiphersuite, // at the moment we only support one ciphersuite
		RecipientPubHash:            recipient.PubHash(),
		RecipientTempHash:           recipientTempHash,
		SenderIdentity:              sender.Identity(),
		SenderSessionPub:            *senderSessionPub,
		SenderIdentityPubHash:       sender.PubHash(),
		SenderIdentityPub:           *sender.PubKey(),
		NextSenderSessionPub:        nextSenderSessionPub,
		NextRecipientSessionPubSeen: nextRecipientSessionPubSeen,
		NymAddress:                  nymAddress,
		MaxDelay:                    0, // TODO
		SenderSessionCount:          senderSessionCount,
		SenderMessageCount:          senderMessageCount,
		SenderUID:                   string(sender.JSON()),
		SenderLastKeychainHash:      senderLastKeychainHash,
		Status:                      statusCode,
		Padding:                     "", // is set below
	}

	// calculate padding length
	padLen := wiggleRoom
	// pad sender identity
	if len(h.SenderIdentity) > identity.MaxLen {
		return nil, log.Error("msg: sender identity is too long")
	}
	padLen += identity.MaxLen - len(h.SenderIdentity)
	// pad nextSenderSessionPub
	if nextSenderSessionPub == nil {
		padLen += length.KeyEntryECDHE25519 - length.Nil
	}
	// pad nextRecipientSessionPubSeen
	if nextRecipientSessionPubSeen == nil {
		padLen += length.KeyEntryECDHE25519 - length.Nil
	}
	// pad nym address
	if len(h.NymAddress) > length.MaxNymAddress {
		return nil, log.Error("msg: nym address is too long")
	}
	padLen += length.MaxNymAddress - len(h.NymAddress)
	// pad integers
	padLen += 20 - digits.Count(h.MaxDelay)
	padLen += 20 - digits.Count(h.SenderSessionCount)
	padLen += 20 - digits.Count(h.SenderMessageCount)
	// pad sender UIDMessage
	if len(h.SenderUID) > length.MaxUIDMessage {
		return nil, log.Error("msg: sender UIDMesssage is too long")
	}
	padLen += length.MaxUIDMessage - len(h.SenderUID)
	// generate padding
	randLen := padLen/2 + padLen%2
	pad, err := padding.Generate(randLen, cipher.RandReader)
	if err != nil {
		return nil, err
	}
	// set padding
	p := hex.EncodeToString(pad)
	if padLen%2 == 1 {
		p = p[:len(p)-1]
	}
	h.Padding = p
	return h, nil
}