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 }
// 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 }
// 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 }
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 }
// 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 }
// 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 }
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") } }
// 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 }
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 }