diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7b8b26907e8559f01f508d6de8b89115db105d12
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+
+*.out
+*.gi
+bin/unlock_keyrings
+
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..e1e0a82086172e85ef0bf84f80a235c006649ed0
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "src/lib/rlib"]
+	path = src/lib/rlib
+	url = https://github.com/recolic/rlib.git
diff --git a/create_secret_file.sh b/create_secret_file.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ca22cb44a4956a538f6f18fcec439a55dd0be5b4
--- /dev/null
+++ b/create_secret_file.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+filename="$1"
+gpg_pubkey_id="$2" # leave empty to use default receipt.
+
+echo '>>> Please type keyring_name and password in the following format:
+
+keyring1:password1
+keyring2:password2
+
+# Comment: This is a comment
+login:12345678
+
+>>> When you are done, use Ctrl-D to end.'
+
+gpg --encrypt -o "$filename" -a -r "$gpg_pubkey_id"
+exit $?
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..a0b203b5e9621b72520b78e88eb75a67420b2dcd
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,11 @@
+
+CXX ?= g++
+CXXFLAGS := $(shell pkg-config --cflags --libs gnome-keyring-1) -I ./lib -I .
+EXTRA_FLAGS ?=
+
+secret: rlib
+	$(CXX) $(CXXFLAGS) $(EXTRA_FLAGS) unlock_keyrings.cc ./lib/rlib/libr.a -o ../bin/unlock_keyrings
+
+rlib:
+	cd ./lib/rlib && make
+
diff --git a/src/keyring_op.hpp b/src/keyring_op.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..de9d1da0c84e68c7fe2baab98a5f5a9d0efda442
--- /dev/null
+++ b/src/keyring_op.hpp
@@ -0,0 +1,27 @@
+#include <gnome-keyring-1/gnome-keyring.h>
+#include <string>
+#include <rlib/macro.hpp>
+
+inline GnomeKeyringResult do_unlock(std::string keyring, std::string password) {
+    return gnome_keyring_unlock_sync(keyring.c_str(), password.c_str());
+}
+
+inline std::string keyringResultToString(GnomeKeyringResult res) {
+    switch(res) {
+#define RLIB_IMPL_GEN_RESULT(value) RLIB_IMPL_GEN_RESULT_1(value, RLIB_MACRO_TO_CSTR(value))
+#define RLIB_IMPL_GEN_RESULT_1(value, cstr) case (value): return (cstr)
+
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_OK);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_DENIED);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_ALREADY_UNLOCKED);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_NO_SUCH_KEYRING);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_IO_ERROR);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_CANCELLED);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_KEYRING_ALREADY_EXISTS);
+        RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_NO_MATCH);
+        default:
+            return std::string("Unknown Result Code: ") + std::to_string(res);
+    }
+}
diff --git a/src/lib/rlib b/src/lib/rlib
new file mode 160000
index 0000000000000000000000000000000000000000..3a442c6dd8661d45cfe7528112b93c42ffa5d591
--- /dev/null
+++ b/src/lib/rlib
@@ -0,0 +1 @@
+Subproject commit 3a442c6dd8661d45cfe7528112b93c42ffa5d591
diff --git a/src/unlock_keyrings.cc b/src/unlock_keyrings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3425f6c8ef313b3deec29274e634efe9cac52ee8
--- /dev/null
+++ b/src/unlock_keyrings.cc
@@ -0,0 +1,57 @@
+#include <rlib/log.hpp>
+#include <rlib/opt.hpp>
+#include <rlib/stream.hpp>
+#include "keyring_op.hpp"
+
+
+int main(int argc, char **argv) {
+    rlib::opt_parser args(argc, argv);
+    rlib::logger rlog(std::cout);
+
+    if(args.getBoolArg("-h", "--help")) {
+        rlog.info("Usage: {} [-h/--help] [-q/--quiet] --secret-file <filename> # use `-` as stdin.");
+        return 0;
+    }
+    if(args.getBoolArg("-q", "--quiet")) {
+        rlog = rlib::logger(rlib::null_stream);
+    }
+
+    auto secret_file_name = args.getValueArg("--secret-file");
+    if(secret_file_name == "-")
+        secret_file_name = "/dev/fd/0";
+    
+    std::ifstream secret_input (secret_file_name);
+    if(not secret_input) {
+        rlog.error("Unable to open file {}. Exiting...", secret_file_name);
+        return 2;
+    }
+    size_t line_num = 0;
+    bool no_error = true;
+    while(not secret_input.eof()) {
+        auto line = rlib::scanln(secret_input).strip("\t\n\r");
+        auto line_removed_space = line;
+        line_removed_space.strip(' '); // Remove space may break keyring_name or password.
+        if(line_removed_space.empty() or line_removed_space[0] == '#')
+            continue; // Skip comments.
+        
+        auto keyring_and_pswd = line.split(':');
+        if(keyring_and_pswd.size() != 2) {
+            rlog.error("Secret file line {} has wrong format. Expecting `${keyring}:${password}`", line_num);
+            return 3;
+        }
+
+        auto res = do_unlock(keyring_and_pswd.at(0), keyring_and_pswd.at(1));
+        auto msg = keyringResultToString(res);
+        if(res == GNOME_KEYRING_RESULT_OK)
+            rlog.verbose("line {}: {}.", line_num, msg);
+        else {
+            rlog.error("line {}: {}.", line_num, msg);
+            no_error = false;
+        }
+
+        ++line_num;
+    }
+
+    return no_error ? 0 : 4;
+}
+