diff --git a/docs/man/rpmkeys.8.md b/docs/man/rpmkeys.8.md
index 1b27f06247..e56d6458fd 100644
--- a/docs/man/rpmkeys.8.md
+++ b/docs/man/rpmkeys.8.md
@@ -27,6 +27,8 @@ The general forms of rpm digital signature commands are
 
 **rpmkeys** {**-e\|\--erase\|-d\|\--delete**} *FINGERPRINT \...*
 
+**rpmkeys** {**\--rebuild**} \[*\--drop_backends*\] \[*--\include_backend_backend BACKEND*\] \[*--\include_backend_backend BACKEND*\]
+
 **rpmkeys** {**-K\|\--checksig**} *PACKAGE\_FILE \...*
 
 The **\--checksig** option checks all the digests and signatures
@@ -64,6 +66,22 @@ Erase the key(s) designated by *FINGERPRINT*. For example:
 
 **rpmkeys** **\--erase 771b18d3d7baa28734333c424344591e1964c5fc**
 
+Rebuild the key storage:
+
+**rpmkeys** **\--rebuild**
+
+Recreate the public key storage. Update to the latest format and drop
+unreadable keys. This will fail if there are public keys in other
+storage backends.
+
+Adding **\--drop_backends** will delete those keys during rebuilding.
+
+Adding **\--include_backend BACKEND** will keep the keys from the given
+backend and add it to the configured one during rebuilding.
+The parameter can be given more than once. Valid values for the backends
+are **rpmdb**, **fs**, **openpgp**. This can be used to convert from
+one key storage to another.
+
 SEE ALSO
 ========
 
diff --git a/include/rpm/rpmts.h b/include/rpm/rpmts.h
index 86ca62e0ef..162cfe26f4 100644
--- a/include/rpm/rpmts.h
+++ b/include/rpm/rpmts.h
@@ -754,6 +754,8 @@ rpmtsi rpmtsiInit(rpmts ts);
  */
 rpmte rpmtsiNext(rpmtsi tsi, rpmElementTypes types);
 
+rpmRC rpmtsRebuildKeystore(rpmts ts, char ** loadBackends, int flags);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/keystore.cc b/lib/keystore.cc
index bca10abfe2..112ecb140e 100644
--- a/lib/keystore.cc
+++ b/lib/keystore.cc
@@ -1,6 +1,8 @@
 #include "system.h"
 
+#include <filesystem>
 #include <string>
+#include <set>
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -18,11 +20,13 @@
 #include <rpm/rpmtypes.h>
 
 #include "rpmts_internal.hh"
+#include "rpmmacro_internal.hh"
 
 #include "debug.h"
 
 using std::string;
 using namespace rpm;
+namespace fs = std::filesystem;
 
 static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp);
 
@@ -118,6 +122,42 @@ rpmRC rpm::check_backends(rpmtxn txn, rpmts ts)
     return rc;
 }
 
+rpmRC rebuild_dir(rpmtxn txn, keystore * store, rpmKeyring keys)
+{
+
+    auto macros = rpm::macros();
+    std::string keyringpath = rpm::expand_path({"%{_keyringpath}"});
+    std::string path = rpm::expand_path({rpmtxnRootDir(txn), keyringpath});
+    std::string oldpath = path + ".rpmold/";
+    std::error_code ec = {};
+    rpmRC rc = RPMRC_OK;
+    macros.push("_keyringpath", "", (keyringpath + ".tmp/").c_str(), 0);
+
+    rpmPubkey key = NULL;
+    auto iter = rpmKeyringInitIterator(keys, 0);
+    while ((rc == RPMRC_OK) && (key = rpmKeyringIteratorNext(iter))) {
+	rc = store->import_key(txn, key, 0, 0);
+    }
+    rpmKeyringIteratorFree(iter);
+
+    if (rc != RPMRC_OK)
+	goto exit;
+
+    /* Ignore errors from (re)moving old directory as it might not exist */
+    fs::rename(path, oldpath, ec);
+    fs::rename(path + ".tmp", path, ec);
+    if (ec) {
+	rpmlog(RPMLOG_ERR, _("can't move new key store to %s: %s.\n"), path.c_str(), ec.message().c_str());
+	rc = RPMRC_FAIL;
+    }
+    fs::remove_all(oldpath);
+
+ exit:
+    macros.pop("_keyringpath");
+
+    return rc;
+}
+
 /*****************************************************************************/
 
 rpmRC keystore_fs::load_keys(rpmtxn txn, rpmKeyring keyring)
@@ -171,6 +211,11 @@ rpmRC keystore_fs::import_key(rpmtxn txn, rpmPubkey key, int replace, rpmFlags f
     return rc;
 }
 
+rpmRC keystore_fs::rebuild(rpmtxn txn, rpmKeyring keys)
+{
+    return rebuild_dir(txn, this, keys);
+}
+
 /*****************************************************************************/
 
 static int acquire_write_lock(rpmtxn txn)
@@ -256,6 +301,12 @@ rpmRC keystore_openpgp_cert_d::import_key(rpmtxn txn, rpmPubkey key, int replace
     return rc;
 }
 
+rpmRC keystore_openpgp_cert_d::rebuild(rpmtxn txn, rpmKeyring keys)
+{
+    return rebuild_dir(txn, this, keys);
+}
+
+
 /*****************************************************************************/
 
 rpmRC keystore_rpmdb::load_keys(rpmtxn txn, rpmKeyring keyring)
@@ -357,6 +408,51 @@ rpmRC keystore_rpmdb::import_key(rpmtxn txn, rpmPubkey key, int replace, rpmFlag
     return rc;
 }
 
+rpmRC keystore_rpmdb::rebuild(rpmtxn txn, rpmKeyring keys)
+{
+    rpmRC rc = RPMRC_OK;
+    std::set<unsigned int> packages = {};
+    Header h = NULL;
+    rpmPubkey key = NULL;
+
+    auto iter = rpmKeyringInitIterator(keys, 0);
+    while ((key = rpmKeyringIteratorNext(iter))) {
+	if (makePubkeyHeader(rpmtxnTs(txn), key, &h) != 0) {
+	    rpmlog(RPMLOG_ERR, _("can't create header for key %s\n"),
+		   rpmPubkeyFingerprintAsHex(key));
+	    rc = RPMRC_FAIL;
+	    break;
+	}
+	if ((rc = rpmtsImportHeader(txn, h, 0)) != RPMRC_OK) {
+	    headerFree(h);
+	    rpmlog(RPMLOG_ERR, _("can't add header to rpmdb for key %s\n"),
+		   rpmPubkeyFingerprintAsHex(key));
+	    break;
+	}
+	packages.insert(headerGetInstance(h));
+	headerFree(h);
+    }
+    rpmKeyringIteratorFree(iter);
+
+    if (rc != RPMRC_OK) {
+	return rc;
+    }
+    
+    rpmdbMatchIterator mi = rpmtsInitIterator(rpmtxnTs(txn), RPMDBI_NAME, "gpg-pubkey", 0);
+    while ((h = rpmdbNextIterator(mi)) != NULL) {
+	if (!packages.count(headerGetInstance(h))) {
+	    rpmRC rrc = rpmdbRemove(rpmtsGetRdb(rpmtxnTs(txn)), headerGetInstance(h)) ?
+                RPMRC_FAIL : RPMRC_OK;
+	    if (rc != RPMRC_OK) {
+		rpmlog(RPMLOG_WARNING, "can't remove key %s", headerGetString(h, RPMTAG_NEVR));
+		rc = rrc;
+	    }
+	}
+    }
+    rpmdbFreeIterator(mi);
+    return rc;
+}
+
 static void addGpgProvide(Header h, const char *n, const char *v)
 {
     rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
diff --git a/lib/keystore.hh b/lib/keystore.hh
index e53ec91ff0..c17ecb6996 100644
--- a/lib/keystore.hh
+++ b/lib/keystore.hh
@@ -16,6 +16,7 @@ public:
     virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring) = 0;
     virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, int replace = 1, rpmFlags flags = 0) = 0;
     virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key) = 0;
+    virtual rpmRC rebuild(rpmtxn txn, rpmKeyring keys) = 0;
 
     virtual ~keystore() = default;
 };
@@ -26,6 +27,7 @@ public:
     virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring);
     virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, int replace = 1, rpmFlags flags = 0);
     virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key);
+    virtual rpmRC rebuild(rpmtxn txn, rpmKeyring keys);
 
 private:
     rpmRC delete_key(rpmtxn txn, const std::string & keyid, const std::string & newname = "");
@@ -37,6 +39,7 @@ public:
     virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring);
     virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, int replace = 1, rpmFlags flags = 0);
     virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key);
+    virtual rpmRC rebuild(rpmtxn txn, rpmKeyring keys);
 
 private:
     rpmRC delete_key(rpmtxn txn, const std::string & keyid, unsigned int newinstance = 0);
@@ -48,6 +51,7 @@ public:
     virtual rpmRC load_keys(rpmtxn txn, rpmKeyring keyring);
     virtual rpmRC import_key(rpmtxn txn, rpmPubkey key, int replace = 1, rpmFlags flags = 0);
     virtual rpmRC delete_key(rpmtxn txn, rpmPubkey key);
+    virtual rpmRC rebuild(rpmtxn txn, rpmKeyring keys);
 };
 
 }; /* namespace */
diff --git a/lib/rpmts.cc b/lib/rpmts.cc
index 701fca131b..e604ed4e70 100644
--- a/lib/rpmts.cc
+++ b/lib/rpmts.cc
@@ -9,6 +9,8 @@
 #include <fcntl.h>
 #include <errno.h>
 
+#include <filesystem>
+
 #include <rpm/rpmtypes.h>
 #include <rpm/rpmlib.h>			/* rpmReadPackage etc */
 #include <rpm/rpmmacro.h>
@@ -31,6 +33,7 @@
 #include "rpmts_internal.hh"
 #include "rpmte_internal.hh"
 #include "rpmlog_internal.hh"
+#include "rpmmacro_internal.hh"
 #include "misc.hh"
 #include "rpmtriggers.hh"
 
@@ -38,6 +41,7 @@
 
 using std::string;
 using namespace rpm;
+namespace fs = std::filesystem;
 
 /**
  * Iterator across transaction elements, forward on install, backward on erase.
@@ -396,6 +400,95 @@ rpmRC rpmtxnDeletePubkey(rpmtxn txn, rpmPubkey key)
     return rc;
 }
 
+rpmRC rpmtsRebuildKeystore(rpmts ts,  char ** loadBackends, int flags)
+{
+    rpmRC rc = RPMRC_OK;
+    rpmtxn txn = rpmtxnBegin(ts, RPMTXN_WRITE);
+    rpmVSFlags oflags = rpmtsVSFlags(ts);
+
+    rpmtsOpenDB(ts, O_RDWR);
+
+    /* XXX keyring wont load if sigcheck disabled, force it temporarily */
+    rpmtsSetVSFlags(ts, (oflags & ~RPMVSF_MASK_NOSIGNATURES));
+
+    keystore * ts_keystore = getKeystore(ts);
+    rpmKeyring keyring = rpmKeyringNew();
+
+    keystore_fs ks_fs = {};
+    keystore_rpmdb ks_rpmdb = {};
+    keystore_openpgp_cert_d ks_opengpg = {};
+
+    for (keystore * ks: std::vector<keystore *>{&ks_fs, &ks_rpmdb, &ks_opengpg}) {
+	rpmKeyring kr = rpmKeyringNew();
+	ks->load_keys(txn, kr);
+
+	char ** name = loadBackends;
+	if (name) {
+	    for (;*name; name++) {
+		if (!strcmp(*name, ks->get_name().c_str()))
+		    break;
+
+	    }
+	}
+
+	/* backend not to be included */
+	if (ks->get_name() != ts->keystore->get_name() && (!name || !*name)) {
+	    if (!rpmKeyringIsEmpty(kr) && !flags) {
+		rpmlog(RPMLOG_ERR, _("public key backend %s is not empty\n"),
+		       ks->get_name().c_str());
+		rpmKeyringFree(kr);
+		rc = RPMRC_FAIL;
+		goto exit;
+	    }
+	    rpmKeyringFree(kr);
+	    continue;
+	}
+
+	rpmKeyringIterator iter = rpmKeyringInitIterator(kr, 0);
+	rpmPubkey key = NULL;
+	while ((key = rpmKeyringIteratorNext(iter)) != NULL) {
+	    const unsigned char * pkt = NULL;
+	    size_t pktlen = 0;
+	    char *lints = NULL;
+
+	    rpmPubkeyRawData(key, &pkt, &pktlen);
+	    int lrc = pgpPubKeyLint(pkt, pktlen, &lints) ;
+	    if (lints) {
+		if (lrc != RPMRC_OK)
+		    rpmlog(RPMLOG_WARNING, "dropping public key %s:\n", rpmPubkeyFingerprintAsHex(key));
+		rpmlog(RPMLOG_WARNING, "%s\n", lints);
+		free(lints);
+		if (lrc != RPMRC_OK)
+		    continue;
+	    }
+	    rpmKeyringModify(keyring, key, RPMKEYRING_MERGE);
+	}
+	rpmKeyringIteratorFree(iter);
+	rpmKeyringFree(kr);
+    }
+
+    rc = ts_keystore->rebuild(txn, keyring);
+
+    if (dynamic_cast<keystore_rpmdb*>(ts_keystore)) {
+	fs::remove_all(rpm::expand_path({rpmtxnRootDir(txn),
+		    "%{_keyringpath}"}));
+    } else {
+	/* remove all gpg-pubkey packages */
+	rpmKeyring kr = rpmKeyringNew();
+	ks_rpmdb.rebuild(txn, kr);
+	rpmKeyringFree(kr);
+    }
+
+ exit:
+
+    ts->keyring = rpmKeyringFree(ts->keyring);
+    rpmKeyringFree(keyring);
+    rpmtxnEnd(txn);
+    rpmtsSetVSFlags(ts, oflags);
+
+    return rc;
+}
+
 rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen)
 {
     rpmRC rc = RPMRC_FAIL;
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
index c07c712b82..8198f0316d 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -1924,3 +1924,171 @@ hello-1.0.tar.gz:(none)
 ],
 [])
 RPMTEST_CLEANUP
+
+AT_SETUP([keyring rebuild rpmdb])
+AT_KEYWORDS([rpmkeys signature])
+RPMDB_INIT
+
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-ed25519-test.pub
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring openpgp" \
+        --import /data/keys/rpm.org-rsa-2048-add-subkey.asc
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/alice.asc
+
+RPMTEST_CHECK([[
+runroot rpmkeys --define "_keyring rpmdb" --rebuild
+]],
+[2],
+[],
+[error: public key backend fs is not empty
+])
+
+RPMTEST_CHECK([[
+runroot rpmkeys --define "_keyring rpmdb" --rebuild --include_backend fs --include_backend openpgp
+runroot rpm -qa gpg-pubkey
+runroot rpmkeys --define "_keyring rpmdb" --list
+echo "==============================================="
+runroot rpmkeys --define "_keyring fs" --list
+runroot rpmkeys --define "_keyring openpgp" --list
+runroot rpmkeys --define "_keyring rpmdb" -Kv /data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm | grep "Header OpenPGP"
+]],
+[0],
+[gpg-pubkey-771b18d3d7baa28734333c424344591e1964c5fc-58e63918
+gpg-pubkey-152bb32fd9ca982797e835cfb0645aec757bf69e-661d22a8
+gpg-pubkey-b6542f92f30650c36b6f41bcb3a771bfeb04e625-62521e00
+771b18d3d7baa28734333c424344591e1964c5fc rpm.org RSA testkey <rsa@rpm.org> public key
+152bb32fd9ca982797e835cfb0645aec757bf69e rpm.org ed25519 testkey <ed25519@rpm.org> public key
+b6542f92f30650c36b6f41bcb3a771bfeb04e625 Alice <alice@example.org> public key
+===============================================
+    Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK
+],
+[ignore])
+RPMTEST_CLEANUP
+
+AT_SETUP([keyring rebuild rpmdb 2])
+AT_KEYWORDS([rpmkeys signature])
+RPMDB_INIT
+
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-ed25519-test.pub
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring openpgp" \
+        --import /data/keys/rpm.org-rsa-2048-add-subkey.asc
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/alice.asc
+
+RPMTEST_CHECK([[
+runroot rpmkeys --define "_keyring rpmdb" --rebuild --include_backend openpgp --drop_backends
+runroot rpm -qa gpg-pubkey
+runroot rpmkeys --define "_keyring rpmdb" --list
+echo "==============================================="
+runroot rpmkeys --define "_keyring fs" --list
+runroot rpmkeys --define "_keyring openpgp" --list
+runroot rpmkeys --define "_keyring rpmdb" -Kv /data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm | grep "Header OpenPGP"
+]],
+[0],
+[gpg-pubkey-771b18d3d7baa28734333c424344591e1964c5fc-58e63918
+gpg-pubkey-152bb32fd9ca982797e835cfb0645aec757bf69e-661d22a8
+771b18d3d7baa28734333c424344591e1964c5fc rpm.org RSA testkey <rsa@rpm.org> public key
+152bb32fd9ca982797e835cfb0645aec757bf69e rpm.org ed25519 testkey <ed25519@rpm.org> public key
+===============================================
+    Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK
+],
+[ignore])
+RPMTEST_CLEANUP
+
+AT_SETUP([keyring rebuild fs])
+AT_KEYWORDS([rpmkeys signature])
+RPMDB_INIT
+
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-ed25519-test.pub
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring openpgp" \
+        --import /data/keys/rpm.org-rsa-2048-add-subkey.asc
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/alice.asc
+
+RPMTEST_CHECK([[
+runroot rpmkeys --define "_keyring fs" --rebuild --include_backend rpmdb --include_backend openpgp
+runroot rpmkeys --define "_keyring fs" --list
+echo "==============================================="
+runroot rpmkeys --define "_keyring rpmdb" --list
+runroot rpmkeys --define "_keyring openpgp" --list
+runroot rpmkeys --define "_keyring fs" -Kv /data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm | grep "Header OpenPGP"
+]],
+[0],
+[771b18d3d7baa28734333c424344591e1964c5fc rpm.org RSA testkey <rsa@rpm.org> public key
+152bb32fd9ca982797e835cfb0645aec757bf69e rpm.org ed25519 testkey <ed25519@rpm.org> public key
+b6542f92f30650c36b6f41bcb3a771bfeb04e625 Alice <alice@example.org> public key
+===============================================
+    Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK
+],
+[ignore])
+
+RPMTEST_CLEANUP
+
+AT_SETUP([keyring rebuild openpgp])
+AT_KEYWORDS([rpmkeys signature])
+RPMDB_INIT
+
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring rpmdb" \
+        --import /data/keys/rpm.org-ed25519-test.pub
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/rpm.org-rsa-2048-test.pub
+runroot rpmkeys \
+        --define "_keyring openpgp" \
+        --import /data/keys/rpm.org-rsa-2048-add-subkey.asc
+runroot rpmkeys \
+        --define "_keyring fs" \
+        --import /data/keys/alice.asc
+
+RPMTEST_CHECK([[
+runroot rpmkeys --define "_keyring openpgp" --rebuild --include_backend fs --include_backend rpmdb
+runroot rpmkeys --define "_keyring openpgp" --list
+echo "==============================================="
+runroot rpmkeys --define "_keyring fs" --list
+runroot rpmkeys --define "_keyring rpmdb" --list
+runroot rpmkeys --define "_keyring openpgp" -Kv /data/RPMS/hello-2.0-1.x86_64-signed-with-new-subkey.rpm | grep "Header OpenPGP"
+]],
+[0],
+[771b18d3d7baa28734333c424344591e1964c5fc rpm.org RSA testkey <rsa@rpm.org> public key
+152bb32fd9ca982797e835cfb0645aec757bf69e rpm.org ed25519 testkey <ed25519@rpm.org> public key
+b6542f92f30650c36b6f41bcb3a771bfeb04e625 Alice <alice@example.org> public key
+===============================================
+    Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 771b18d3d7baa28734333c424344591e1964c5fc: OK
+],
+[ignore])
+
+RPMTEST_CLEANUP
diff --git a/tools/rpmkeys.cc b/tools/rpmkeys.cc
index 89a2a7131e..98e23a1214 100644
--- a/tools/rpmkeys.cc
+++ b/tools/rpmkeys.cc
@@ -15,10 +15,13 @@ enum modes {
     MODE_DELKEY		= (1 << 2),
     MODE_LISTKEY	= (1 << 3),
     MODE_EXPORTKEY	= (1 << 4),
+    MODE_REBUILD	= (1 << 5),
 };
 
 static int mode = 0;
 static int test = 0;
+static char ** backends = NULL;
+static int rebuildflags = 0;
 
 static struct poptOption keyOptsTable[] = {
     { "checksig", 'K', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_CHECKSIG,
@@ -35,6 +38,12 @@ static struct poptOption keyOptsTable[] = {
 	N_("Erase keys from RPM keyring"), NULL },
     { "list", 'l', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_LISTKEY,
 	N_("list keys from RPM keyring"), NULL },
+    { "rebuild", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_REBUILD,
+	N_("rebuild the keyring - convert to current backend"), NULL },
+    { "include_backend", '\0', POPT_ARG_ARGV, &backends, 0,
+	N_("include other backends when rebuilding current backend"), NULL },
+    { "drop_backends", '\0', POPT_ARG_NONE, &rebuildflags, 0,
+	N_("drop keys from other backends when rebuilding"), NULL },
     POPT_TABLEEND
 };
 
@@ -149,7 +158,8 @@ int main(int argc, char *argv[])
 
     args = (ARGV_const_t) poptGetArgs(optCon);
 
-    if (args == NULL && mode != MODE_LISTKEY && mode != MODE_EXPORTKEY)
+    if (args == NULL && mode != MODE_LISTKEY && mode != MODE_EXPORTKEY &&
+	mode != MODE_REBUILD)
 	argerror(_("no arguments given"));
 
     ts = rpmtsCreate();
@@ -183,6 +193,23 @@ int main(int argc, char *argv[])
 	ec = matchingKeys(ts, args, printKey);
 	break;
     }
+    case MODE_REBUILD:
+    {
+
+	if (backends) {
+	    for (char** strptr = backends; *strptr; strptr++) {
+		if (!strcmp(*strptr, "rpmdb") &&
+		    !strcmp(*strptr, "fs") &&
+		    !strcmp(*strptr, "rpmpgp")) {
+		    rpmlog(RPMLOG_ERR, _("unknown backend: %s\n"), *strptr);
+		    ec = -1;
+		    break;
+		}
+	    }
+	}
+	ec = rpmtsRebuildKeystore(ts, backends, rebuildflags);
+	break;
+    }
     default:
 	argerror(_("only one major mode may be specified"));
     }
@@ -192,6 +219,10 @@ int main(int argc, char *argv[])
     rpmcliFini(optCon);
     fflush(stderr);
     fflush(stdout);
+    if (backends)
+	for (char** strptr = backends; *strptr; strptr++)
+	    free(*strptr);
+    free(backends);
     if (ferror(stdout) || ferror(stderr))
 	return 255; /* I/O error */
     return ec;