diff --git a/.gitignore b/.gitignore index a2d8c41..fd0a05e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ build/ /.project +/.vscode + *.user *.log *.err diff --git a/KeePit/KeePit.pro b/KeePit/KeePit.pro index 7f253fb..d58e2a9 100644 --- a/KeePit/KeePit.pro +++ b/KeePit/KeePit.pro @@ -11,6 +11,7 @@ SOURCES += main.cpp \ hashedblockstream.cpp \ passwordentry.cpp \ readxmlfile.cpp \ + writexmlfile.cpp \ salsa20.cpp \ sha256.cpp \ tinyxml2.cpp \ @@ -147,6 +148,7 @@ SOURCES += main.cpp \ aes.cpp \ filehandler.cpp \ bytestream.cpp \ + hexx.cpp RESOURCES += KeePit.qrc @@ -176,6 +178,7 @@ HEADERS += \ hashedblockstream.h \ passwordentry.h \ readxmlfile.h \ + writexmlfile.h \ salsa20.h \ sha256.h \ tinyxml2.h \ @@ -323,7 +326,8 @@ HEADERS += \ aes.h \ filehandler.h \ bytestream.h \ - stdafx.h + stdafx.h \ + hexx.h LIBS += -L$$OUT_PWD/../ziplib/ -lziplib diff --git a/KeePit/base64.cpp b/KeePit/base64.cpp index cc3011b..abe7648 100644 --- a/KeePit/base64.cpp +++ b/KeePit/base64.cpp @@ -19,6 +19,7 @@ #include "base64.h" #include +#include static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -34,6 +35,13 @@ Base64::Base64() { } +std::vector Base64::base64_encode(std::string const& string) { + const char * buf = string.c_str(); + std::string bStr = Base64::base64_encode(buf, string.length()); + std::vector data(bStr.begin(), bStr.end()); + return data; +} + /// \brief Base64::base64_encode /// Base64 encodes the given pointer to the char array /// \param buf The buffer to encode diff --git a/KeePit/base64.h b/KeePit/base64.h index 42667bf..26eeb4b 100644 --- a/KeePit/base64.h +++ b/KeePit/base64.h @@ -28,6 +28,7 @@ class Base64 { public: Base64(); + std::vector base64_encode(std::string const& string); std::string base64_encode(char const* buf, unsigned int bufLen); std::vector base64_decode(std::string const&); }; diff --git a/KeePit/database.cpp b/KeePit/database.cpp index 44bda95..6558480 100644 --- a/KeePit/database.cpp +++ b/KeePit/database.cpp @@ -34,6 +34,7 @@ #include "passwordentry.h" #include "base64.h" #include "readkeyfile.h" +#include "writexmlfile.h" #include "filehandler.h" #include "bytestream.h" #include "../ziplib/GZipHelper.h" @@ -104,6 +105,10 @@ Database::Database(QObject *parent) : Database::~Database() { } +void Database::createNewDatabase(QString filePath) { + WriteXmlFile::CreateNewDatabase(filePath); +} + /// /// \brief Database::deleteFile /// \param filePath diff --git a/KeePit/database.h b/KeePit/database.h index ff5ee21..3fba83b 100644 --- a/KeePit/database.h +++ b/KeePit/database.h @@ -47,6 +47,7 @@ class Database : public QObject PasswordEntryModel* createModel(); Q_INVOKABLE void loadHome(); Q_INVOKABLE void deleteFile(QString); + Q_INVOKABLE void createNewDatabase(QString); Q_SIGNALS: void error(QString msg); diff --git a/KeePit/hexx.cpp b/KeePit/hexx.cpp new file mode 100644 index 0000000..5eac53d --- /dev/null +++ b/KeePit/hexx.cpp @@ -0,0 +1,96 @@ +/* +* This file is part of KeePit +* +* Copyright (C) 2016-2018 Dan Beavon +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +*/ + +#include "hexx.h" + +QString Hex::ByteArrayToHexString(QByteArray array) +{ + int nLen = array.size(); + if(nLen == 0) return QString(); + + QString sb; + + unsigned char bt; + unsigned char btHigh; + unsigned char btLow; + + for(int i = 0; i < nLen; ++i) + { + bt = array[i]; + btHigh = bt; btHigh >>= 4; + btLow = (unsigned char)(bt & 0x0F); + + if(btHigh >= 10) sb.append((char)('A' + btHigh - 10)); + else sb.append((char)('0' + btHigh)); + + if(btLow >= 10) sb.append((char)('A' + btLow - 10)); + else sb.append((char)('0' + btLow)); + } + + return sb; +} + +QByteArray Hex::HexStringToByteArray(QString strHex) +{ + std::vector bytes; + std::string hex = strHex.toStdString(); + + for (unsigned int i = 0; i < hex.length(); i += 2) { + std::string byteString = hex.substr(i, 2); + char byte = (char) strtol(byteString.c_str(), NULL, 16); + bytes.push_back(byte); + } + + QByteArray qb(reinterpret_cast(bytes.data()), bytes.size()); // = new QByteArray(reinterpret_cast(bytes.data()), bytes.size()); + return qb; + + /*int nStrLen = strHex.length(); + + const char *data = strHex.toStdString().c_str(); + unsigned char *pb = new unsigned char[nStrLen / 2]; + unsigned char bt; + char ch; + + for(int i = 0; i < nStrLen; i += 2) + { + ch = data[i]; + + if((ch >= '0') && (ch <= '9')) + bt = (unsigned char)(ch - '0'); + else if((ch >= 'a') && (ch <= 'f')) + bt = (unsigned char)(ch - 'a' + 10); + else if((ch >= 'A') && (ch <= 'F')) + bt = (unsigned char)(ch - 'A' + 10); + else { bt = 0; } + + bt <<= 4; + + ch = data[i + 1]; + if((ch >= '0') && (ch <= '9')) + bt += (unsigned char)(ch - '0'); + else if((ch >= 'a') && (ch <= 'f')) + bt += (unsigned char)(ch - 'a' + 10); + else if((ch >= 'A') && (ch <= 'F')) + bt += (unsigned char)(ch - 'A' + 10); + + pb[i >> 1] = bt; + } + + return QByteArray(reinterpret_cast(pb));*/ +} \ No newline at end of file diff --git a/KeePit/hexx.h b/KeePit/hexx.h new file mode 100644 index 0000000..56b8730 --- /dev/null +++ b/KeePit/hexx.h @@ -0,0 +1,33 @@ +/* +* This file is part of KeePit +* +* Copyright (C) 2016-2018 Dan Beavon +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +*/ + +#ifndef HEX_H +#define HEX_H + +#include + +class Hex +{ +public: + Hex(); + static QString ByteArrayToHexString(QByteArray array); + static QByteArray HexStringToByteArray(QString strHex); +}; + +#endif //HEX_H \ No newline at end of file diff --git a/KeePit/qml/CreateDatabase.qml b/KeePit/qml/CreateDatabase.qml index 657284d..c2b2e11 100644 --- a/KeePit/qml/CreateDatabase.qml +++ b/KeePit/qml/CreateDatabase.qml @@ -55,6 +55,16 @@ Item { topMargin: pageHeader.height + units.gu(2) } + Label { + text: i18n.tr("Database Name") + } + + TextField { + id: databaseName + width: parent.width + text: "Q.xml" + } + Label { text: i18n.tr("Master Password") } @@ -79,26 +89,14 @@ Item { Label { text: i18n.tr("Key file") - color: UbuntuColors.darkAubergine } TextField { id: keyfile readOnly: true - color: UbuntuColors.darkAubergine width: parent.width } - Button { - id: create_keyfile - text: i18n.tr("Create Key") - width: parent.width - onClicked: { - //Create an XML key file - //Save to the file application location - } - } - KeySelector { id: combo width: parent.width @@ -115,16 +113,15 @@ Item { } } - /*Button { + Button { id: save text: i18n.tr("Save") width: parent.width color: UbuntuColors.green onClicked: { - //Create an XML key file - //Save to the file application location + database.createNewDatabase(appLocation + "/" + databaseName.text) } - }*/ + } } } } diff --git a/KeePit/qml/Main.qml b/KeePit/qml/Main.qml index 9f47305..36cc8fb 100644 --- a/KeePit/qml/Main.qml +++ b/KeePit/qml/Main.qml @@ -123,9 +123,9 @@ MainView { id: importer } - /*CreateDatabase { + CreateDatabase { id: createDatabase - }*/ + } } /*Component { diff --git a/KeePit/writexmlfile.cpp b/KeePit/writexmlfile.cpp new file mode 100644 index 0000000..e75a103 --- /dev/null +++ b/KeePit/writexmlfile.cpp @@ -0,0 +1,258 @@ +/* +* This file is part of KeePit +* +* Copyright (C) 2016-2018 Dan Beavon +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +*/ +#include "writexmlfile.h" +#include "passwordentry.h" +#include "treenode.h" +#include "salsa20.h" +#include "base64.h" + +#include +#include +#include + +#include "hexx.h" +#include "./tinyxml2.h" + +using namespace tinyxml2; + +/// +/// \brief WriteXmlFile::WriteXmlFile +/// \param xml +/// \param size +/// \param salsa +/// +WriteXmlFile::WriteXmlFile(const char* xml, size_t size, Salsa20 *salsa) +{ + m_xml = xml; + m_size = size; + m_salsa = salsa; +} + +/// +/// \brief WriteXmlFile::~WriteXmlFile +/// +WriteXmlFile::~WriteXmlFile() +{ + delete m_salsa; + m_salsa = 0; + delete lastRead; + lastRead = 0; +} + +/// +/// \brief WriteXmlFile::ToString +/// \return +/// +void WriteXmlFile::CreateNewDatabase(QString filePath) +{ + Base64 base64; + + XMLDocument doc; + XMLDeclaration * decl = doc.NewDeclaration(); + doc.InsertFirstChild(decl); + + XMLElement * keepassFile = doc.NewElement( "KeePassFile" ); // everything hangs off this element + doc.InsertEndChild(keepassFile); + + XMLElement * meta = doc.NewElement( "Meta" ); // meta and root are sibling elements + keepassFile->InsertEndChild( meta ); + + XMLElement * generator = doc.NewElement( "Generator" ); + generator->SetText("KeePass"); + meta->InsertEndChild( generator ); + XMLElement * databaseName = doc.NewElement( "DatabaseName" ); + databaseName->SetText("KeePass database"); + meta->InsertEndChild( databaseName ); + XMLElement * DatabaseNameChanged = doc.NewElement( "DatabaseNameChanged" ); + + char nowBuff[70]; + std::time_t now_c = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + std::tm now_tm = *std::localtime(&now_c); + strftime(nowBuff, sizeof nowBuff, "%Y-%m-%dT%H:%M:%SZ", &now_tm); + DatabaseNameChanged->SetText(nowBuff); + meta->InsertEndChild( DatabaseNameChanged ); + + XMLElement * DatabaseDescription = doc.NewElement( "DatabaseDescription" ); + meta->InsertEndChild( DatabaseDescription ); + XMLElement * DatabaseDescriptionChanged = doc.NewElement( "DatabaseDescriptionChanged" ); + DatabaseDescriptionChanged->SetText(nowBuff); + meta->InsertEndChild( DatabaseDescriptionChanged ); + + XMLElement * DefaultUserName = doc.NewElement( "DefaultUserName" ); + meta->InsertEndChild( DefaultUserName ); + + XMLElement * DefaultUserNameChanged = doc.NewElement( "DefaultUserNameChanged" ); + DefaultUserNameChanged->SetText(nowBuff); + meta->InsertEndChild( DefaultUserNameChanged ); + + XMLElement * MaintenanceHistoryDays = doc.NewElement( "MaintenanceHistoryDays" ); + MaintenanceHistoryDays->SetText(365); + meta->InsertEndChild( MaintenanceHistoryDays ); + + XMLElement * Color = doc.NewElement( "Color" ); + meta->InsertEndChild( Color ); + + XMLElement * MasterKeyChanged = doc.NewElement( "MasterKeyChanged" ); + MasterKeyChanged->SetText(nowBuff); + meta->InsertEndChild( MasterKeyChanged ); + + XMLElement * MasterKeyChangeRec = doc.NewElement( "MasterKeyChangeRec" ); + MasterKeyChangeRec ->SetText("-1"); + meta->InsertEndChild( MasterKeyChangeRec ); + + XMLElement * MasterKeyChangeForce = doc.NewElement( "MasterKeyChangeForce" ); + MasterKeyChangeForce ->SetText(1); + meta->InsertEndChild( MasterKeyChangeForce ); + + XMLElement * MemoryProtection = doc.NewElement( "MemoryProtection" ); + meta->InsertEndChild( MemoryProtection ); + XMLElement * ProtectTitle = doc.NewElement( "ProtectTitle" ); + ProtectTitle->SetText("False"); + MemoryProtection->InsertEndChild( ProtectTitle ); + XMLElement * ProtectUserName = doc.NewElement( "ProtectUserName" ); + ProtectUserName->SetText("False"); + MemoryProtection->InsertEndChild( ProtectUserName ); + XMLElement * ProtectPassword = doc.NewElement( "ProtectPassword" ); + ProtectPassword->SetText("True"); + MemoryProtection->InsertEndChild( ProtectPassword ); + XMLElement * ProtectURL = doc.NewElement( "ProtectURL" ); + ProtectURL->SetText("False"); + MemoryProtection->InsertEndChild( ProtectURL ); + XMLElement * ProtectNotes = doc.NewElement( "ProtectNotes" ); + ProtectNotes->SetText("False"); + MemoryProtection->InsertEndChild( ProtectNotes ); + + XMLElement * RecycleBinEnabled = doc.NewElement( "RecycleBinEnabled" ); + RecycleBinEnabled->SetText("True"); + meta->InsertEndChild( RecycleBinEnabled ); + XMLElement * RecycleBinUUID = doc.NewElement( "RecycleBinUUID" ); + RecycleBinUUID->SetText("AAAAAAAAAAAAAAAAAAAAAA=="); + meta->InsertEndChild( RecycleBinUUID ); + XMLElement * RecycleBinChanged = doc.NewElement( "RecycleBinChanged" ); + RecycleBinChanged->SetText(nowBuff); + meta->InsertEndChild( RecycleBinChanged ); + XMLElement * EntryTemplatesGroup = doc.NewElement( "EntryTemplatesGroup" ); + EntryTemplatesGroup->SetText("AAAAAAAAAAAAAAAAAAAAAA=="); + meta->InsertEndChild( EntryTemplatesGroup ); + XMLElement * EntryTemplatesGroupChanged = doc.NewElement( "EntryTemplatesGroupChanged" ); + EntryTemplatesGroupChanged->SetText(nowBuff); + meta->InsertEndChild( EntryTemplatesGroupChanged ); + XMLElement * HistoryMaxItems = doc.NewElement( "HistoryMaxItems" ); + HistoryMaxItems->SetText(10); + meta->InsertEndChild( HistoryMaxItems ); + XMLElement * HistoryMaxSize = doc.NewElement( "HistoryMaxSize" ); + HistoryMaxSize->SetText(621456); + meta->InsertEndChild( HistoryMaxSize ); + XMLElement * LastSelectedGroup = doc.NewElement( "LastSelectedGroup" ); + LastSelectedGroup->SetText("AAAAAAAAAAAAAAAAAAAAAA=="); + meta->InsertEndChild( LastSelectedGroup ); + XMLElement * LastTopVisibleGroup = doc.NewElement( "LastTopVisibleGroup" ); + LastTopVisibleGroup->SetText("AAAAAAAAAAAAAAAAAAAAAA=="); + meta->InsertEndChild( LastTopVisibleGroup ); + XMLElement * Binaries = doc.NewElement( "Binaries" ); + meta->InsertEndChild( Binaries ); + XMLElement * CustomData = doc.NewElement( "CustomData" ); + meta->InsertEndChild( CustomData ); + + XMLElement * root = doc.NewElement( "Root" ); + keepassFile->InsertEndChild( root ); + + XMLElement * group = doc.NewElement( "Group" ); // Group element hangs off root + root->InsertEndChild( group ); + + XMLElement * deletedObjects = doc.NewElement( "DeletedObjects" ); + root->InsertEndChild( deletedObjects ); + + XMLElement * uuid = doc.NewElement( "UUID" ); // hangs off Group + + QUuid uid = QUuid::createUuid(); + QString uuidStr = uid.toString(); + + uuidStr.remove("{"); + uuidStr.remove("}"); + uuidStr.remove("-"); + + QByteArray strBytes = Hex::HexStringToByteArray(uuidStr); + + std::string uStr = base64.base64_encode(strBytes.data(), strBytes.size()); + uuid->SetText(uStr.c_str()); + group->InsertEndChild( uuid ); + + // debugging info + // XMLElement * uuid_temp = doc.NewElement( "uuid_temp" ); // hangs off Group + // uuid_temp->SetText(uuidStr.toStdString().c_str()); + // group->InsertEndChild( uuid_temp ); + + + XMLElement * name = doc.NewElement( "Name" ); // hangs off Group + name->SetText("keepass"); + group->InsertEndChild( name ); + XMLElement * notes = doc.NewElement( "Notes" ); // hangs off Group + group->InsertEndChild( notes ); + + XMLElement * times = doc.NewElement( "Times" ); // hangs off Group + group->InsertEndChild( times ); + XMLElement * creationTime = doc.NewElement( "CreationTime" ); // hangs off Times + creationTime->SetText(nowBuff); + times->InsertEndChild( creationTime ); + XMLElement * lastModificationTime = doc.NewElement( "LastModificationTime" ); // hangs off Times + lastModificationTime->SetText(nowBuff); + times->InsertEndChild( lastModificationTime ); + XMLElement * lastAccessTime = doc.NewElement( "LastAccessTime" ); // hangs off Times + lastAccessTime->SetText(nowBuff); + times->InsertEndChild( lastAccessTime ); + XMLElement * expiryTime = doc.NewElement( "ExpiryTime" ); // hangs off Times + expiryTime->SetText(nowBuff); + times->InsertEndChild( expiryTime ); + XMLElement * expires = doc.NewElement( "Expires" ); // hangs off Times + expires->SetText("False"); + times->InsertEndChild( expires ); + XMLElement * usageCount = doc.NewElement( "UsageCount" ); // hangs off Times + usageCount->SetText(0); + times->InsertEndChild( usageCount ); + XMLElement * locationChanged = doc.NewElement( "LocationChanged" ); // hangs off Times + locationChanged->SetText(nowBuff); + times->InsertEndChild( locationChanged ); + + XMLElement * isExpanded = doc.NewElement( "IsExpanded" ); // hangs off Group + isExpanded->SetText("True"); + group->InsertEndChild( isExpanded ); + XMLElement * defaultAutoTypeSequence = doc.NewElement( "DefaultAutoTypeSequence" ); // hangs off Group + group->InsertEndChild( defaultAutoTypeSequence ); + XMLElement * enableAutoType = doc.NewElement( "EnableAutoType" ); // hangs off Group + enableAutoType->SetText("null"); + group->InsertEndChild( enableAutoType ); + XMLElement * enableSearching = doc.NewElement( "EnableSearching" ); // hangs off Group + enableSearching->SetText("null"); + group->InsertEndChild( enableSearching ); + XMLElement * lastTopVisibleEntry = doc.NewElement( "LastTopVisibleEntry" ); // hangs off Group + lastTopVisibleEntry->SetText("AAAAAAAAAAAAAAAAAAAAAA=="); + group->InsertEndChild( lastTopVisibleEntry ); + + //XmlText * text = new TiXmlText( "World" ); + //doc.SaveFile( filePath.toLocal8Bit().data() ); +} + +/// +/// \brief WriteXmlFile::ToString +/// \return +/// +/*QString WriteXmlFile::ToString(vector) +{ +}*/ diff --git a/KeePit/writexmlfile.h b/KeePit/writexmlfile.h new file mode 100644 index 0000000..cde92f2 --- /dev/null +++ b/KeePit/writexmlfile.h @@ -0,0 +1,51 @@ +/* +* This file is part of KeePit +* +* Copyright (C) 2016-2018 Dan Beavon +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +*/ + +#ifndef WRITEXMLFILE_H +#define WRITEXMLFILE_H + +#include "passwordentry.h" +#include "treenode.h" +#include "salsa20.h" +#include "base64.h" +#include "tinyxml2.h" +#include +#include +#include + +using namespace std; +using namespace tinyxml2; + +class WriteXmlFile +{ +public: + WriteXmlFile(const char*, size_t, Salsa20*); + ~WriteXmlFile(); + //QString ToString(vector); + static void CreateNewDatabase(QString fileName); + +private: + size_t m_size; + Base64 base64; + Salsa20 *m_salsa; + const char * m_xml; + TreeNode *lastRead = 0; +}; + +#endif // WRITEXMLFILE_H diff --git a/clean.sh b/clean.sh new file mode 100755 index 0000000..143dd96 --- /dev/null +++ b/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +clickable clean diff --git a/clickable.json b/clickable.json index 8a54d05..d47610d 100644 --- a/clickable.json +++ b/clickable.json @@ -1,6 +1,4 @@ { - "template": "qmake", - "sdk":"ubuntu-sdk-16.04", - "arch":"armhf", - "app":"keepit.dannygb" + "template": "qmake", + "arch":"armhf" } diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..cc714bc --- /dev/null +++ b/install.sh @@ -0,0 +1,2 @@ +#!/bin/bash +clickable install diff --git a/po/de.po b/po/de.po index 6a2e2f1..3a28986 100644 --- a/po/de.po +++ b/po/de.po @@ -1,7 +1,7 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# German translation file. +# Copyright (C) 2019 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. +# FIRST AUTHOR dan.beavon@gmail.com, 2019. # msgid "" msgstr ""