diff --git a/src/smartcard/card.cpp b/src/smartcard/card.cpp
index c321c4b3f..dbcda8813 100644
--- a/src/smartcard/card.cpp
+++ b/src/smartcard/card.cpp
@@ -1,208 +1,246 @@
 /*  smartcard/card.h
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
     SPDX-FileContributor: Intevation GmbH
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include "card.h"
 
 #include "readerstatus.h"
 
+#include "kleopatra_debug.h"
+
 using namespace Kleo;
 using namespace Kleo::SmartCard;
 
 namespace {
 static QString formatVersion(int value)
 {
     if (value < 0) {
         return QString();
     }
 
     const unsigned int a = ((value >> 24) & 0xff);
     const unsigned int b = ((value >> 16) & 0xff);
     const unsigned int c = ((value >>  8) & 0xff);
     const unsigned int d = ((value      ) & 0xff);
     if (a) {
         return QStringLiteral("%1.%2.%3.%4").arg(QString::number(a), QString::number(b), QString::number(c), QString::number(d));
     } else if (b) {
         return QStringLiteral("%1.%2.%3").arg(QString::number(b), QString::number(c), QString::number(d));
     } else if (c) {
         return QStringLiteral("%1.%2").arg(QString::number(c), QString::number(d));
     }
     return QString::number(d);
 }
 }
 
 Card::Card()
 {
 }
 
 Card::~Card()
 {
 }
 
 void Card::setStatus(Status s)
 {
     mStatus = s;
 }
 
 Card::Status Card::status() const
 {
     return mStatus;
 }
 
 void Card::setSerialNumber(const std::string &sn)
 {
     mSerialNumber = sn;
 }
 
 std::string Card::serialNumber() const
 {
     return mSerialNumber;
 }
 
 QString Card::displaySerialNumber() const
 {
     return mDisplaySerialNumber;
 }
 
 void Card::setDisplaySerialNumber(const QString &serialNumber)
 {
     mDisplaySerialNumber = serialNumber;
 }
 
 std::string Card::appName() const
 {
     return mAppName;
 }
 
 void Card::setAppName(const std::string &name)
 {
     mAppName = name;
 }
 
 void Card::setAppVersion(int version)
 {
     mAppVersion = version;
 }
 
 int Card::appVersion() const
 {
     return mAppVersion;
 }
 
 QString Card::displayAppVersion() const
 {
     return formatVersion(mAppVersion);
 }
 
 std::string Card::cardType() const
 {
     return mCardType;
 }
 
 int Card::cardVersion() const
 {
     return mCardVersion;
 }
 
 QString Card::displayCardVersion() const
 {
     return formatVersion(mCardVersion);
 }
 
 QString Card::cardHolder() const
 {
     return mCardHolder;
 }
 
 std::vector<Card::PinState> Card::pinStates() const
 {
     return mPinStates;
 }
 
 void Card::setPinStates(const std::vector<PinState> &pinStates)
 {
     mPinStates = pinStates;
 }
 
 bool Card::hasNullPin() const
 {
     return mHasNullPin;
 }
 
 void Card::setHasNullPin(bool value)
 {
     mHasNullPin = value;
 }
 
 bool Card::canLearnKeys() const
 {
     return mCanLearn;
 }
 
 void Card::setCanLearnKeys(bool value)
 {
     mCanLearn = value;
 }
 
 bool Card::operator == (const Card &other) const
 {
     return mStatus == other.status()
         && mSerialNumber == other.serialNumber()
         && mAppName == other.appName()
         && mAppVersion == other.appVersion()
         && mPinStates == other.pinStates()
         && mCanLearn == other.canLearnKeys()
         && mHasNullPin == other.hasNullPin();
 }
 
 bool Card::operator != (const Card &other) const
 {
     return !operator==(other);
 }
 
 void Card::setErrorMsg(const QString &msg)
 {
     mErrMsg = msg;
 }
 
 QString Card::errorMsg() const
 {
     return mErrMsg;
 }
 
+const std::vector<KeyPairInfo> & Card::keyInfos() const
+{
+    return mKeyInfos;
+}
+
+const KeyPairInfo & Card::keyInfo(const std::string &keyRef) const
+{
+    static const KeyPairInfo nullKey;
+    for (const KeyPairInfo &k : mKeyInfos) {
+        if (k.keyRef == keyRef) {
+            return k;
+        }
+    }
+    return nullKey;
+}
+
 namespace {
 static int parseHexEncodedVersionTuple(const std::string &s) {
     // s is a hex-encoded, unsigned int-packed version tuple,
     // i.e. each byte represents one part of the version tuple
     bool ok;
     const auto version = QByteArray::fromStdString(s).toUInt(&ok, 16);
     return ok ? version : -1;
 }
 }
 
 bool Card::parseCardInfo(const std::string &name, const std::string &value)
 {
     if (name == "APPVERSION") {
         mAppVersion = parseHexEncodedVersionTuple(value);
         return true;
     } else if (name == "CARDTYPE") {
         mCardType = value;
         return true;
     } else if (name == "CARDVERSION") {
         mCardVersion = parseHexEncodedVersionTuple(value);
         return true;
     } else if (name == "DISP-NAME") {
         auto list = QString::fromUtf8(QByteArray::fromStdString(value)).
                     split(QStringLiteral("<<"), Qt::SkipEmptyParts);
         std::reverse(list.begin(), list.end());
         mCardHolder = list.join(QLatin1Char(' '));
         return true;
+    } else if (name == "KEYPAIRINFO") {
+        const KeyPairInfo info = KeyPairInfo::fromStatusLine(value);
+        if (info.grip.empty()) {
+            qCWarning(KLEOPATRA_LOG) << "Invalid KEYPAIRINFO status line" << QString::fromStdString(value);
+            setStatus(Card::CardError);
+        } else {
+            updateKeyInfo(info);
+        }
+        return true;
     }
 
     return false;
 }
+
+void Card::updateKeyInfo(const KeyPairInfo& keyPairInfo)
+{
+    for (KeyPairInfo &k : mKeyInfos) {
+        if (k.keyRef == keyPairInfo.keyRef) {
+            k.update(keyPairInfo);
+            return;
+        }
+    }
+    mKeyInfos.push_back(keyPairInfo);
+}
diff --git a/src/smartcard/card.h b/src/smartcard/card.h
index 376deff73..d6bba4a19 100644
--- a/src/smartcard/card.h
+++ b/src/smartcard/card.h
@@ -1,110 +1,120 @@
 #ifndef SMARTCARD_CARD_H
 #define SMARTCARD_CARD_H
 /*  smartcard/card.h
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
     SPDX-FileContributor: Intevation GmbH
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
+#include "keypairinfo.h"
+
 #include <string>
 #include <vector>
 
 #include <QString>
 
 namespace Kleo
 {
 namespace SmartCard
 {
+
 /** Class representing an application on a smartcard or similar hardware token. */
 class Card
 {
 public:
     enum PinState {
         UnknownPinState,
         NullPin,
         PinBlocked,
         NoPin,
         PinOk,
 
         NumPinStates
     };
 
     enum Status {
         NoCard,
         CardPresent,
         CardActive,
         CardUsable,
 
         _NumScdStates,
 
         CardError = _NumScdStates,
 
         NumStates
     };
 
     Card();
     virtual ~Card();
 
     virtual bool operator == (const Card &other) const;
     bool operator != (const Card &other) const;
 
     void setStatus(Status s);
     Status status() const;
 
     void setSerialNumber(const std::string &sn);
     std::string serialNumber() const;
 
     QString displaySerialNumber() const;
     void setDisplaySerialNumber(const QString &sn);
 
     std::string appName() const;
 
     void setAppVersion(int version);
     int appVersion() const;
     QString displayAppVersion() const;
 
     std::string cardType() const;
 
     int cardVersion() const;
     QString displayCardVersion() const;
 
     QString cardHolder() const;
 
     std::vector<PinState> pinStates() const;
     void setPinStates(const std::vector<PinState> &pinStates);
 
     bool hasNullPin() const;
     void setHasNullPin(bool value);
 
     bool canLearnKeys() const;
     void setCanLearnKeys(bool value);
 
     QString errorMsg() const;
     void setErrorMsg(const QString &msg);
 
+    const std::vector<KeyPairInfo> & keyInfos() const;
+    const KeyPairInfo & keyInfo(const std::string &keyRef) const;
+
 protected:
     void setAppName(const std::string &name);
 
     bool parseCardInfo(const std::string &name, const std::string &value);
 
+private:
+    void updateKeyInfo(const KeyPairInfo &keyPairInfo);
+
 private:
     bool mCanLearn = false;
     bool mHasNullPin = false;
     Status mStatus = NoCard;
     std::string mSerialNumber;
     QString mDisplaySerialNumber;
     std::string mAppName;
     int mAppVersion = -1;
     std::string mCardType;
     int mCardVersion = -1;
     QString mCardHolder;
     std::vector<PinState> mPinStates;
     QString mErrMsg;
+    std::vector<KeyPairInfo> mKeyInfos;
 };
 } // namespace Smartcard
 } // namespace Kleopatra
 
 #endif // SMARTCARD_CARD_H
diff --git a/src/smartcard/keypairinfo.cpp b/src/smartcard/keypairinfo.cpp
index 64c2ebd76..ab8d18b8d 100644
--- a/src/smartcard/keypairinfo.cpp
+++ b/src/smartcard/keypairinfo.cpp
@@ -1,39 +1,64 @@
 /*  smartcard/keypairinfo.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2020 g10 Code GmbH
     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include "keypairinfo.h"
 
 #include <QString>
 #include <QStringList>
 
 using namespace Kleo::SmartCard;
 
 // static
 KeyPairInfo KeyPairInfo::fromStatusLine(const std::string &s) {
     // The format of a KEYPAIRINFO line is
     //   KEYPAIRINFO <hexgrip> <keyref> [usage] [keytime] [algostr]
     // The string s does not contain the leading "KEYPAIRINFO ".
     KeyPairInfo info;
     const auto values = QString::fromStdString(s).split(QLatin1Char(' '));
     if (values.size() < 2) {
         return info;
     }
     info.grip = values[0].toStdString();
     info.keyRef = values[1].toStdString();
     if (values.size() >= 3) {
         info.usage = values[2].toStdString();
     }
     if (values.size() >= 4) {
         info.keyTime = values[3].toStdString();
     }
     if (values.size() >= 5) {
         info.algorithm = values[4].toStdString();
     }
     return info;
 }
+
+void KeyPairInfo::update(const KeyPairInfo &other)
+{
+    Q_ASSERT(keyRef == other.keyRef);
+    if (keyRef != other.keyRef) {
+        return;
+    }
+    if (grip != other.grip) {
+        // reset all infos if the grip changed
+        grip = other.grip;
+        usage = std::string();
+        keyTime = std::string();
+        algorithm = std::string();
+    }
+    // now update all infos from other's infos unless other's infos are empty or not specified
+    if (!other.usage.empty() && other.usage != "-") {
+        usage = other.usage;
+    }
+    if (!other.keyTime.empty() && other.keyTime != "-") {
+        keyTime = other.keyTime;
+    }
+    if (!other.algorithm.empty() && other.algorithm != "-") {
+        algorithm = other.algorithm;
+    }
+}
diff --git a/src/smartcard/keypairinfo.h b/src/smartcard/keypairinfo.h
index 3e3e8bc09..3b83cf9b8 100644
--- a/src/smartcard/keypairinfo.h
+++ b/src/smartcard/keypairinfo.h
@@ -1,30 +1,32 @@
 /*  smartcard/keypairinfo.h
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2020 g10 Code GmbH
     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 #ifndef SMARTCARD_KEYPAIRINFO_H
 #define SMARTCARD_KEYPAIRINFO_H
 
 #include <string>
 
 namespace Kleo
 {
 namespace SmartCard
 {
 struct KeyPairInfo {
     static KeyPairInfo fromStatusLine(const std::string &s);
 
+    void update(const KeyPairInfo &other);
+
     std::string grip;
     std::string keyRef;
     std::string usage;
     std::string keyTime;
     std::string algorithm;
 };
 } // namespace Smartcard
 } // namespace Kleopatra
 
 #endif // SMARTCARD_PIVCARD_H
diff --git a/src/smartcard/openpgpcard.cpp b/src/smartcard/openpgpcard.cpp
index 2472d7ef9..043625752 100644
--- a/src/smartcard/openpgpcard.cpp
+++ b/src/smartcard/openpgpcard.cpp
@@ -1,156 +1,136 @@
 /*  smartcard/openpgpcard.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
     SPDX-FileContributor: Intevation GmbH
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 /* Code in this file is partly based on the GNU Privacy Assistant
  * (cm-openpgp.c) git rev. 0a78795146661234070681737b3e08228616441f
  *
  * Whis is:
  * SPDX-FileCopyrightText: 2008, 2009 g 10 Code GmbH
  *
  * And may be licensed under the GNU General Public License
  * as published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  */
 
 #include "openpgpcard.h"
 
 #include "kleopatra_debug.h"
 
 
 using namespace Kleo;
 using namespace Kleo::SmartCard;
 
 // static
 const std::string OpenPGPCard::AppName = "openpgp";
 
 OpenPGPCard::OpenPGPCard(const Card &card)
     : Card(card)
 {
     setAppName(AppName);
 }
 
 // static
 std::string OpenPGPCard::pinKeyRef()
 {
     return std::string("OPENPGP.1");
 }
 
 // static
 std::string OpenPGPCard::adminPinKeyRef()
 {
     return std::string("OPENPGP.3");
 }
 
 // static
 std::string OpenPGPCard::resetCodeKeyRef()
 {
     return std::string("OPENPGP.2");
 }
 
 std::string OpenPGPCard::sigFpr() const
 {
     return mMetaInfo.value("SIGKEY-FPR");
 }
 
 std::string OpenPGPCard::encFpr() const
 {
     return mMetaInfo.value("ENCKEY-FPR");
 }
 
 std::string OpenPGPCard::authFpr() const
 {
     return mMetaInfo.value("AUTHKEY-FPR");
 }
 
 void OpenPGPCard::setCardInfo(const std::vector< std::pair<std::string, std::string> > &infos)
 {
     qCDebug(KLEOPATRA_LOG) << "Card" << serialNumber().c_str() << "info:";
     for (const auto &pair: infos) {
         qCDebug(KLEOPATRA_LOG) << pair.first.c_str() << ":" << pair.second.c_str();
         if (parseCardInfo(pair.first, pair.second)) {
             continue;
         }
         if (pair.first == "KEY-FPR" ||
             pair.first == "KEY-TIME") {
             // Key fpr and key time need to be distinguished, the number
             // of the key decides the usage.
             const auto values = QString::fromStdString(pair.second).split(QLatin1Char(' '));
             if (values.size() < 2) {
                 qCWarning(KLEOPATRA_LOG) << "Invalid entry.";
                 setStatus(Card::CardError);
                 continue;
             }
             const auto usage = values[0];
             const auto fpr = values[1].toStdString();
             if (usage == QLatin1Char('1')) {
                 mMetaInfo.insert(std::string("SIG") + pair.first, fpr);
             } else if (usage == QLatin1Char('2')) {
                 mMetaInfo.insert(std::string("ENC") + pair.first, fpr);
             } else if (usage == QLatin1Char('3')) {
                 mMetaInfo.insert(std::string("AUTH") + pair.first, fpr);
             } else {
                 // Maybe more keyslots in the future?
                 qCDebug(KLEOPATRA_LOG) << "Unhandled keyslot";
             }
-        } else if (pair.first == "KEYPAIRINFO") {
-            // Fun, same as above but the other way around.
-            const auto values = QString::fromStdString(pair.second).split(QLatin1Char(' '));
-            if (values.size() < 2) {
-                qCWarning(KLEOPATRA_LOG) << "Invalid entry.";
-                setStatus(Card::CardError);
-                continue;
-            }
-            const auto usage = values[1];
-            const auto grip = values[0].toStdString();
-            if (usage == QLatin1String("OPENPGP.1")) {
-                mMetaInfo.insert(std::string("SIG") + pair.first, grip);
-            } else if (usage == QLatin1String("OPENPGP.2")) {
-                mMetaInfo.insert(std::string("ENC") + pair.first, grip);
-            } else if (usage == QLatin1String("OPENPGP.3")) {
-                mMetaInfo.insert(std::string("AUTH") + pair.first, grip);
-            } else {
-                // Maybe more keyslots in the future?
-                qCDebug(KLEOPATRA_LOG) << "Unhandled keyslot";
-            }
         } else {
             mMetaInfo.insert(pair.first, pair.second);
         }
     }
 }
 
 bool OpenPGPCard::operator == (const Card& rhs) const
 {
     const OpenPGPCard *other = dynamic_cast<const OpenPGPCard *>(&rhs);
     if (!other) {
         return false;
     }
 
     return Card::operator ==(rhs)
         && sigFpr() == other->sigFpr()
         && encFpr() == other->encFpr()
         && authFpr() == other->authFpr()
         && manufacturer() == other->manufacturer()
         && cardHolder() == other->cardHolder()
         && pubkeyUrl() == other->pubkeyUrl();
 }
 
 void OpenPGPCard::setManufacturer(const std::string &manufacturer)
 {
     mManufacturer = manufacturer;
 }
 
 std::string OpenPGPCard::manufacturer() const
 {
     return mManufacturer;
 }
 
 std::string OpenPGPCard::pubkeyUrl() const
 {
     return mMetaInfo.value("PUBKEY-URL");
 }
diff --git a/src/smartcard/pivcard.cpp b/src/smartcard/pivcard.cpp
index 136b1ea69..f918c05eb 100644
--- a/src/smartcard/pivcard.cpp
+++ b/src/smartcard/pivcard.cpp
@@ -1,173 +1,162 @@
 /*  smartcard/pivcard.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2020 g10 Code GmbH
     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include "pivcard.h"
 
 #include "keypairinfo.h"
 
 #include <KLocalizedString>
 
 #include "kleopatra_debug.h"
 
 using namespace Kleo;
 using namespace Kleo::SmartCard;
 
 // static
 const std::string PIVCard::AppName = "piv";
 
 PIVCard::PIVCard(const Card &card)
     : Card(card)
 {
     setAppName(AppName);
 }
 
 // static
 std::string PIVCard::pivAuthenticationKeyRef()
 {
     return std::string("PIV.9A");
 }
 
 // static
 std::string PIVCard::cardAuthenticationKeyRef()
 {
     return std::string("PIV.9E");
 }
 
 // static
 std::string PIVCard::digitalSignatureKeyRef()
 {
     return std::string("PIV.9C");
 }
 
 // static
 std::string PIVCard::keyManagementKeyRef()
 {
     return std::string("PIV.9D");
 }
 
 // static
 std::string PIVCard::pinKeyRef()
 {
     return std::string("PIV.80");
 }
 
 // static
 std::string PIVCard::pukKeyRef()
 {
     return std::string("PIV.81");
 }
 
 // static
 const std::vector<std::string> & PIVCard::supportedKeys()
 {
     static const std::vector<std::string> keyRefs = {
         PIVCard::pivAuthenticationKeyRef(),
         PIVCard::cardAuthenticationKeyRef(),
         PIVCard::digitalSignatureKeyRef(),
         PIVCard::keyManagementKeyRef()
     };
 
     return keyRefs;
 }
 
 // static
 QString PIVCard::keyDisplayName(const std::string &keyRef)
 {
     static const QMap<std::string, QString> displayNames = {
         { PIVCard::pivAuthenticationKeyRef(), i18n("PIV Authentication Key") },
         { PIVCard::cardAuthenticationKeyRef(), i18n("Card Authentication Key") },
         { PIVCard::digitalSignatureKeyRef(), i18n("Digital Signature Key") },
         { PIVCard::keyManagementKeyRef(), i18n("Key Management Key") },
     };
 
     return displayNames.value(keyRef);
 }
 
 // static
 std::vector< std::pair<std::string, QString> > PIVCard::supportedAlgorithms(const std::string &keyRef)
 {
     if (keyRef == PIVCard::keyManagementKeyRef()) {
         return {
             { "rsa2048", i18n("RSA key transport (2048 bits)") },
             { "nistp256", i18n("ECDH (Curve P-256)") },
             { "nistp384", i18n("ECDH (Curve P-384)") }
         };
     } else if (keyRef == PIVCard::digitalSignatureKeyRef()) {
         return {
             { "rsa2048", i18n("RSA (2048 bits)") },
             { "nistp256", i18n("ECDSA (Curve P-256)") },
             { "nistp384", i18n("ECDSA (Curve P-384)") }
         };
     }
 
     // NIST SP 800-78-4 does not allow Curve P-384 for PIV Authentication key or Card Authentication key
     return {
         { "rsa2048", i18n("RSA (2048 bits)") },
         { "nistp256", i18n("ECDSA (Curve P-256)") },
     };
 }
 
 std::string PIVCard::keyGrip(const std::string& keyRef) const
 {
-    return mMetaInfo.value("KEYPAIRINFO-" + keyRef);
+    return keyInfo(keyRef).grip;
 }
 
 void PIVCard::setCardInfo(const std::vector< std::pair<std::string, std::string> > &infos)
 {
     qCDebug(KLEOPATRA_LOG) << "Card" << serialNumber().c_str() << "info:";
     for (const auto &pair: infos) {
         qCDebug(KLEOPATRA_LOG) << pair.first.c_str() << ":" << pair.second.c_str();
         if (parseCardInfo(pair.first, pair.second)) {
             continue;
         }
-        if (pair.first == "KEYPAIRINFO") {
-            const KeyPairInfo info = KeyPairInfo::fromStatusLine(pair.second);
-            if (info.grip.empty()) {
-                qCWarning(KLEOPATRA_LOG) << "Invalid KEYPAIRINFO status line"
-                        << QString::fromStdString(pair.second);
-                setStatus(Card::CardError);
-                continue;
-            }
-            mMetaInfo.insert("KEYPAIRINFO-" + info.keyRef, info.grip);
-        } else {
-            mMetaInfo.insert(pair.first, pair.second);
-        }
+        mMetaInfo.insert(pair.first, pair.second);
     }
 }
 
 std::string PIVCard::keyAlgorithm(const std::string &keyRef) const
 {
     return mMetaInfo.value("KLEO-KEYALGO-" + keyRef);
 }
 
 void PIVCard::setKeyAlgorithm(const std::string &keyRef, const std::string &algorithm)
 {
     mMetaInfo.insert("KLEO-KEYALGO-" + keyRef, algorithm);
 }
 
 std::string PIVCard::certificateData(const std::string &keyRef) const
 {
     return mMetaInfo.value("KLEO-CERTIFICATE-" + keyRef);
 }
 
 void PIVCard::setCertificateData(const std::string &keyRef, const std::string &data)
 {
     mMetaInfo.insert("KLEO-CERTIFICATE-" + keyRef, data);
 }
 
 bool PIVCard::operator == (const Card& rhs) const
 {
     const PIVCard *other = dynamic_cast<const PIVCard *>(&rhs);
     if (!other) {
         return false;
     }
 
     return Card::operator ==(rhs)
         && mMetaInfo == other->mMetaInfo;
 }