Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/HibpOffline.cpp')
-rw-r--r--src/core/HibpOffline.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/core/HibpOffline.cpp b/src/core/HibpOffline.cpp
new file mode 100644
index 000000000..ebc5d9a46
--- /dev/null
+++ b/src/core/HibpOffline.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "HibpOffline.h"
+
+#include <QCryptographicHash>
+#include <QMultiHash>
+
+#include "core/Database.h"
+#include "core/Group.h"
+
+namespace HibpOffline
+{
+ const std::size_t SHA1_BYTES = 20;
+
+ enum class ParseResult
+ {
+ Ok,
+ Eof,
+ Error
+ };
+
+ ParseResult parseHibpLine(QIODevice& input, QByteArray& sha1, int& count)
+ {
+ QByteArray hexSha1(SHA1_BYTES * 2, '\0');
+ const qint64 rc = input.read(hexSha1.data(), hexSha1.size());
+ if (rc == 0) {
+ return ParseResult::Eof;
+ } else if (rc != hexSha1.size()) {
+ return ParseResult::Error;
+ }
+
+ sha1 = QByteArray::fromHex(hexSha1);
+
+ char c;
+ if (!input.getChar(&c) || c != ':') {
+ return ParseResult::Error;
+ }
+
+ count = 0;
+ while (true) {
+ if (!input.getChar(&c)) {
+ return ParseResult::Error;
+ }
+
+ if (c == '\n' || c == '\r') {
+ break;
+ }
+
+ if (!('0' <= c && c <= '9')) {
+ return ParseResult::Error;
+ }
+
+ count *= 10;
+ count += (c - '0');
+ }
+
+ while (1 == input.peek(&c, 1) && (c == '\n' || c == '\r')) {
+ input.getChar(&c);
+ }
+
+ return ParseResult::Ok;
+ }
+
+ bool
+ report(QSharedPointer<Database> db, QIODevice& hibpInput, QList<QPair<const Entry*, int>>& findings, QString* error)
+ {
+ QMultiHash<QByteArray, const Entry*> entriesBySha1;
+ for (const auto* entry : db->rootGroup()->entriesRecursive()) {
+ if (!entry->isRecycled()) {
+ const auto sha1 = QCryptographicHash::hash(entry->password().toUtf8(), QCryptographicHash::Sha1);
+ entriesBySha1.insert(sha1, entry);
+ }
+ }
+
+ QByteArray sha1;
+ for (quint64 lineNum = 1;; ++lineNum) {
+ int count = 0;
+
+ switch (parseHibpLine(hibpInput, sha1, count)) {
+ case ParseResult::Eof:
+ return true;
+ case ParseResult::Error:
+ *error = QObject::tr("HIBP file, line %1: parse error").arg(lineNum);
+ return false;
+ default:
+ break;
+ }
+
+ for (const auto* entry : entriesBySha1.values(sha1)) {
+ findings.append({entry, count});
+ }
+ }
+ }
+} // namespace HibpOffline