📄 pwmanager.cpp
字号:
/*************************************************************************** * Copyright (C) 2005-2006 by Tarek Saidi * * tarek.saidi@arcor.de * * * * 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 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, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/#include "global.h"#include <iostream>#include <time.h>#include <qfile.h>#include <qstringlist.h>#include <qobject.h>#include <qdatetime.h>#include <QSysInfo>#include <QBuffer>#include "crypto/sha256.h"#include "crypto/rijndael.h"#include "crypto/twoclass.h"#include "lib/random.h"using namespace std;#include "PwManager.h"#include "main.h"#define _ERROR Errors << QString("Unexpected error in: %1, Line:%2").arg(__FILE__).arg(__LINE__);QString PwDatabase::getError(){if(Errors.size()){QString r=Errors.front();Errors.pop_front();return r;}else return QString(tr("Unknown Error"));}QString PwDatabase::getErrors(){QString r;for(int i=0; i<Errors.size(); i++){ r+=Errors[i]; r+='\n';}Errors.clear();return r;}QList<int> PwDatabase::getChildIds(CGroup* group){if(!group)return QList<int>();int GroupIndex=Groups.indexOf(*group);int i;QList<int> ids;for(i=GroupIndex+1; i<Groups.size(); i++){ ids << Groups[i].ID; if(Groups[i].Level <= group->Level) break;}return ids;}bool PwDatabase::openDatabase(QString filename, QString& err){unsigned long total_size,crypto_size;quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;quint8 TrafoRandomSeed[32];quint8 FinalRandomSeed[16];quint8 ContentsHash[32];quint8 EncryptionIV[16];file=new QFile(filename);if(!file->open(QIODevice::ReadWrite)){ if(!file->open(QIODevice::ReadOnly)){ Errors << tr("Could not open file."); delete file; file=NULL; return false; }}total_size=file->size();char* buffer = new char[total_size];file->read(buffer,total_size);if(total_size < DB_HEADER_SIZE){err=tr("Unexpected file size (DB_TOTAL_SIZE < DB_HEADER_SIZE)");return false; }memcpyFromLEnd32(&Signature1,buffer);memcpyFromLEnd32(&Signature2,buffer+4);memcpyFromLEnd32(&Flags,buffer+8);memcpyFromLEnd32(&Version,buffer+12);memcpy(FinalRandomSeed,buffer+16,16);memcpy(EncryptionIV,buffer+32,16);memcpyFromLEnd32(&NumGroups,buffer+48);memcpyFromLEnd32(&NumEntries,buffer+52);memcpy(ContentsHash,buffer+56,32);memcpy(TrafoRandomSeed,buffer+88,32);memcpyFromLEnd32(&KeyEncRounds,buffer+120);if((Signature1!=PWM_DBSIG_1) || (Signature2!=PWM_DBSIG_2)){err=tr("Wrong Signature");return false;}if((Version & 0xFFFFFF00) != (PWM_DBVER_DW & 0xFFFFFF00)){ err=tr("Unsupported File Version."); return false;}if(Flags & PWM_FLAG_RIJNDAEL) CryptoAlgorithmus = ALGO_AES;else if(Flags & PWM_FLAG_TWOFISH) CryptoAlgorithmus = ALGO_TWOFISH;else { err=tr("Unknown Encryption Algorithm."); return false; }transformKey(MasterKey,TransformedMasterKey,TrafoRandomSeed,KeyEncRounds);quint8 FinalKey[32];sha256_context sha32;sha256_starts(&sha32);sha256_update(&sha32,FinalRandomSeed, 16);sha256_update(&sha32,TransformedMasterKey, 32);sha256_finish(&sha32,FinalKey);if(CryptoAlgorithmus == ALGO_AES) { Rijndael aes; // Initialize Rijndael algorithm if(aes.init(Rijndael::CBC, Rijndael::Decrypt, FinalKey, Rijndael::Key32Bytes, EncryptionIV) != RIJNDAEL_SUCCESS) {err=tr("AES-Init Failed"); return false;} // Decrypt! The first bytes aren't encrypted (that's the header) crypto_size = (unsigned long)aes.padDecrypt((quint8 *)buffer + DB_HEADER_SIZE, total_size - DB_HEADER_SIZE, (quint8 *)buffer + DB_HEADER_SIZE); }else if(CryptoAlgorithmus == ALGO_TWOFISH) { CTwofish twofish; if(twofish.init(FinalKey, 32, EncryptionIV) != true){return false;} crypto_size = (unsigned long)twofish.padDecrypt((quint8 *)buffer + DB_HEADER_SIZE, total_size - DB_HEADER_SIZE, (quint8 *)buffer + DB_HEADER_SIZE); }if((crypto_size > 2147483446) || (!crypto_size && NumGroups)){err=tr("Decryption failed.\nThe key is wrong or the file is damaged."); return false;}sha256_starts(&sha32);sha256_update(&sha32,(unsigned char *)buffer + DB_HEADER_SIZE,crypto_size);sha256_finish(&sha32,(unsigned char *)FinalKey);if(memcmp(ContentsHash, FinalKey, 32) != 0){err=tr("Hash test failed.\nThe key is wrong or the file is damaged.");return false;}unsigned long tmp_id=0;unsigned long pos = DB_HEADER_SIZE;quint16 FieldType;quint32 FieldSize;char* pField;bool bRet;CGroup group; for(unsigned long CurGroup = 0; CurGroup < NumGroups; ) { pField = buffer+pos; memcpyFromLEnd16(&FieldType, pField); pField += 2; pos += 2; if(pos >= total_size) { err=tr("Unexpected error: Offset is out of range. [G1]"); return false; } memcpyFromLEnd32(&FieldSize, pField); pField += 4; pos += 4; if(pos >= (total_size + FieldSize)){ err=tr("Unexpected error: Offset is out of range. [G2]"); return false;} bRet = group.ReadGroupField(FieldType, FieldSize, (quint8 *)pField); if((FieldType == 0xFFFF) && (bRet == true)){ Groups << group; CurGroup++;} // Now and ONLY now the counter gets increased pField += FieldSize; pos += FieldSize; if(pos >= total_size) { err=tr("Unexpected error: Offset is out of range. [G1]"); return false;} }CEntry entry; for(unsigned long CurEntry = 0; CurEntry < NumEntries;) { pField = buffer+pos; memcpyFromLEnd16(&FieldType, pField); pField += 2; pos += 2; if(pos >= total_size){ err=tr("Unexpected error: Offset is out of range. [E1]"); return false;} memcpyFromLEnd32(&FieldSize, pField); pField += 4; pos += 4; if(pos >= (total_size + FieldSize)) { err=tr("Unexpected error: Offset is out of range. [E2]"); return false; } bRet = entry.ReadEntryField(FieldType,FieldSize,(quint8*)pField); if((FieldType == 0xFFFF) && (bRet == true)){ entry.sID=tmp_id++; Entries << entry; CurEntry++;} // Now and ONLY now the counter gets increased pField += FieldSize; pos += FieldSize; if(pos >= total_size) { err=tr("Unexpected error: Offset is out of range. [E3]"); return false; } }unsigned long CurGID, g, e, z, num;delete [] buffer;for(int i=0;i<Entries.size();i++){if(IsMetaStream(Entries[i])==true){ if(!parseMetaStream(Entries[i])) UnkownMetaStreams << Entries[i]; deleteEntry(&Entries[i]); i--;}}return true;}bool PwDatabase::parseMetaStream(const CEntry& entry){if(entry.Additional=="KPX_CUSTOM_ICONS_2") return parseCustomIconsMetaStream(entry.BinaryData);if(entry.Additional=="KPX_CUSTOM_ICONS") return parseCustomIconsMetaStreamV1(entry.BinaryData); return false; //unknown MetaStream}CEntry* PwDatabase::getEntry(const KpxUuid& uuid){ for(int i=0; i<Entries.size();i++) if(Entries[i].Uuid==uuid)return &Entries[i]; return NULL;}/* legacy function */bool PwDatabase::parseCustomIconsMetaStreamV1(const QByteArray& dta){return true;}bool PwDatabase::parseCustomIconsMetaStream(const QByteArray& dta){quint32 NumIcons,NumEntries,NumGroups,offset;memcpyFromLEnd32(&NumIcons,dta.data());memcpyFromLEnd32(&NumEntries,dta.data()+4);memcpyFromLEnd32(&NumGroups,dta.data()+8);offset=12;CustomIcons.clear();for(int i=0;i<NumIcons;i++){ CustomIcons << QPixmap(); quint32 Size; memcpyFromLEnd32(&Size,dta.data()+offset); if(offset+Size > dta.size()){ CustomIcons.clear(); return false;} offset+=4; if(!CustomIcons.back().loadFromData((const unsigned char*)dta.data()+offset,Size,"PNG")){ CustomIcons.clear(); return false;} offset+=Size; if(offset > dta.size()){ CustomIcons.clear(); return false;}}for(int i=0;i<NumEntries;i++){ quint32 Icon; KpxUuid EntryUuid; EntryUuid.fromRaw(dta.data()+offset); offset+=16; memcpyFromLEnd32(&Icon,dta.data()+offset); offset+=4; CEntry* entry=getEntry(EntryUuid); if(entry){ entry->OldImgID=entry->ImageID; entry->ImageID=Icon; }}for(int i=0;i<NumGroups;i++){ quint32 Group,Icon; memcpyFromLEnd32(&Group,dta.data()+offset); offset+=4; memcpyFromLEnd32(&Icon,dta.data()+offset); offset+=4; Groups[Group].OldImgID=Groups[Group].ImageID; Groups[Group].ImageID=Icon;}return true;}void PwDatabase::createCustomIconsMetaStream(CEntry* e){/* Rev 2 */e->BinaryDesc="bin-stream";e->Title="Meta-Info";e->UserName="SYSTEM";e->Additional="KPX_CUSTOM_ICONS_2";e->URL="$";e->ImageID=0;if(Groups.size())e->GroupID=Groups[0].ID;int Size=12;quint32 NumEntries=Entries.size();quint32 NumGroups=Groups.size();Size+=8*NumGroups+20*NumEntries;Size+=CustomIcons.size()*1000; // 1KB e->BinaryData.reserve(Size);e->BinaryData.resize(12);quint32 NumIcons=CustomIcons.size();memcpyToLEnd32(e->BinaryData.data(),&NumIcons);memcpyToLEnd32(e->BinaryData.data()+4,&NumEntries);memcpyToLEnd32(e->BinaryData.data()+8,&NumGroups);for(int i=0;i<CustomIcons.size();i++){ quint32 ImgSize; char ImgSizeBin[4]; QByteArray png; png.reserve(1000); QBuffer buffer(&png); CustomIcons[i].save(&buffer,"PNG",0); ImgSize=png.size(); memcpyToLEnd32(ImgSizeBin,&ImgSize); e->BinaryData.append(QByteArray::fromRawData(ImgSizeBin,4)); e->BinaryData.append(png);}for(quint32 i=0;i<Entries.size();i++){ char Bin[20]; Entries[i].Uuid.toRaw(Bin); quint32 id=Entries[i].ImageID; memcpyToLEnd32(Bin+16,&id); e->BinaryData.append(QByteArray::fromRawData(Bin,20));}for(quint32 i=0;i<Groups.size();i++){ char Bin[8]; memcpyToLEnd32(Bin,&i); quint32 id=Groups[i].ImageID; memcpyToLEnd32(Bin+4,&id); e->BinaryData.append(QByteArray::fromRawData(Bin,8));}}int PwDatabase::numIcons(){return BUILTIN_ICONS+CustomIcons.size();}QPixmap& PwDatabase::icon(int i){if(i>=BUILTIN_ICONS+CustomIcons.size()) return EntryIcons[0];if(i<BUILTIN_ICONS) return EntryIcons[i];return CustomIcons[i-BUILTIN_ICONS];}void PwDatabase::addIcon(const QPixmap& icon){CustomIcons << icon;emit iconsModified();}void PwDatabase::removeIcon(int id){id-=BUILTIN_ICONS;if(id < 0 ) return;if(id >= CustomIcons.size()) return;CustomIcons.removeAt(id); // .isNull()==truefor(int i=0;i<Entries.size();i++){ if(Entries[i].ImageID == id+BUILTIN_ICONS) Entries[i].ImageID=Entries[i].OldImgID; if(Entries[i].ImageID>id+BUILTIN_ICONS) Entries[i].ImageID--;}for(int i=0;i<Groups.size();i++){ if(Groups[i].ImageID == id+BUILTIN_ICONS) Groups[i].ImageID=Groups[i].OldImgID; if(Groups[i].ImageID>id+BUILTIN_ICONS) Groups[i].ImageID--;}emit iconsModified();}void PwDatabase::replaceIcon(int id,const QPixmap& icon){if(id<BUILTIN_ICONS)return;CustomIcons[id-BUILTIN_ICONS]=icon;emit iconsModified();}void PwDatabase::transformKey(quint8* src,quint8* dst,quint8* KeySeed,int rounds){quint8* tmp=new quint8[32];Rijndael rijndael;sha256_context sha2;if(rijndael.init(Rijndael::ECB, Rijndael::Encrypt, (const quint8 *)KeySeed,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -