changed encryption method of SecStrings from Rijndael to ArcFour (much faster)

git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@49 b624d157-de02-0410-bad0-e51aec6abb33
master
tariq 19 years ago
parent 68f1d12d74
commit f89372b0c5
  1. 17
      src/PwManager.cpp
  2. 86
      src/crypto/arcfour.cpp
  3. 45
      src/crypto/arcfour.h
  4. 13
      src/dialogs/EditEntryDlg.cpp
  5. 9
      src/dialogs/SearchDlg.cpp
  6. 2
      src/dialogs/SearchDlg.h
  7. 44
      src/lib/EntryView.cpp
  8. 1
      src/lib/EntryView.h
  9. 110
      src/lib/SecString.cpp
  10. 25
      src/lib/SecString.h
  11. 2
      src/main.cpp
  12. 20
      src/mainwindow.cpp
  13. 23
      src/src.pro

@ -201,6 +201,7 @@ CEntry entry;
return false; } return false; }
bRet = entry.ReadEntryField(FieldType,FieldSize,(Q_UINT8*)pField); bRet = entry.ReadEntryField(FieldType,FieldSize,(Q_UINT8*)pField);
if((FieldType == 0xFFFF) && (bRet == true)){ if((FieldType == 0xFFFF) && (bRet == true)){
entry.sID=tmp_id++; entry.sID=tmp_id++;
Entries << entry; Entries << entry;
@ -272,14 +273,14 @@ if(paKey == NULL) return false;
KeyLen = strlen(paKey); KeyLen = strlen(paKey);
if(KeyLen == 0) { if(KeyLen == 0) {
SecString::overwrite(paKey,Password.length() + 1); SecString::overwrite((unsigned char*)paKey,Password.length() + 1);
delete [] paKey; delete [] paKey;
return false; } return false; }
sha256_starts(&sha32); sha256_starts(&sha32);
sha256_update(&sha32,(unsigned char*) paKey, KeyLen); sha256_update(&sha32,(unsigned char*) paKey, KeyLen);
sha256_finish(&sha32,MasterKey); sha256_finish(&sha32,MasterKey);
SecString::overwrite(paKey,Password.length() + 1); SecString::overwrite((unsigned char*)paKey,Password.length() + 1);
delete [] paKey; delete [] paKey;
return true; return true;
} }
@ -530,7 +531,6 @@ switch(FieldType)
memcpyFromLEnd32(&ImageID, (char*)pData); memcpyFromLEnd32(&ImageID, (char*)pData);
break; break;
case 0x0004: case 0x0004:
//Title=(char*)pData;
Title=QString::fromUtf8((char*)pData); Title=QString::fromUtf8((char*)pData);
break; break;
case 0x0005: case 0x0005:
@ -723,8 +723,9 @@ for(int i = 0; i < Entries.size(); i++){
FieldSize = Entries[i].Password.length() + 1; // Add terminating NULL character space FieldSize = Entries[i].Password.length() + 1; // Add terminating NULL character space
memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; memcpyToLEnd16(buffer+pos, &FieldType); pos += 2;
memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4;
memcpy(buffer+pos, Entries[i].Password.getString(),FieldSize); pos += FieldSize; Entries[i].Password.unlock();
Entries[i].Password.delRef(); memcpy(buffer+pos, Entries[i].Password.string(),FieldSize); pos += FieldSize;
Entries[i].Password.lock();
FieldType = 0x0008; FieldType = 0x0008;
FieldSize = Entries[i].Additional.utf8().length() + 1; // Add terminating NULL character space FieldSize = Entries[i].Additional.utf8().length() + 1; // Add terminating NULL character space
@ -1225,8 +1226,12 @@ void assertEntriesEq(KPTestResults& results, CEntry* left, CEntry* right){
kp_assert(results, left->UserName == right->UserName); kp_assert(results, left->UserName == right->UserName);
size += sizeof(left->UserName); size += sizeof(left->UserName);
kp_assert(results, left->Password.getString() == right->Password.getString()); left->Password.unlock();
right->Password.unlock();
kp_assert(results, left->Password.string() == right->Password.string());
size += sizeof(left->Password); size += sizeof(left->Password);
left->Password.lock();
right->Password.lock();
kp_assert(results, left->Additional == right->Additional); kp_assert(results, left->Additional == right->Additional);
size += sizeof(left->Additional); size += sizeof(left->Additional);

@ -0,0 +1,86 @@
/***************************************************************************
* 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 <QByteArray>
#include "arcfour.h"
static inline void swap_byte(unsigned char *a, unsigned char *b)
{
unsigned char swapByte;
swapByte = *a;
*a = *b;
*b = swapByte;
}
void CArcFour::setKey(byte* key_data_ptr, int key_data_len){
RawKey=QByteArray((const char*)key_data_ptr,key_data_len);
}
void CArcFour::prepareKey(){
unsigned char swapByte;
unsigned char index1;
unsigned char index2;
unsigned char* state;
short counter;
state = &key.state[0];
for(counter = 0; counter < 256; counter++)
state[counter] = counter;
key.x = 0;
key.y = 0;
index1 = 0;
index2 = 0;
for(counter = 0; counter < 256; counter++)
{
index2 = (RawKey.at(index1) + state[counter] + index2) % 256;
swap_byte(&state[counter], &state[index2]);
index1 = (index1 + 1) % RawKey.size();
}
}
void CArcFour::encrypt(const byte* src, byte* dst,int length){
//qDebug("Key:%s",RawKey.data());
prepareKey();
unsigned char x;
unsigned char y;
unsigned char* state;
unsigned char xorIndex;
short counter;
x = key.x;
y = key.y;
state = &key.state[0];
for(counter = 0; counter < length; counter ++)
{
x = (x + 1) % 256;
y = (state[x] + y) % 256;
swap_byte(&state[x], &state[y]);
xorIndex = (state[x] + state[y]) % 256;
dst[counter]=src[counter]^state[xorIndex];
}
key.x = x;
key.y = y;
}

@ -0,0 +1,45 @@
/***************************************************************************
* 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. *
***************************************************************************/
#ifndef _ARCFOUR_H_
#define _ARCFOUR_H_
#ifndef byte
#define byte unsigned char
#endif
class CArcFour{
public:
void encrypt(const byte* src, byte* dst,int length);
inline void decrypt(const byte* src, byte* dst,int length){encrypt(src,dst,length);} //just for readability
void setKey(byte* key, int length);
QByteArray RawKey;
private:
void prepareKey();
typedef struct rc4_key{
byte state[256];
byte x;
byte y;}rc4_key;
rc4_key key;
};
#endif

@ -77,9 +77,10 @@ setIcon(EntryIcons[entry->ImageID]);
Edit_Title->setText(entry->Title); Edit_Title->setText(entry->Title);
Edit_UserName->setText(entry->UserName); Edit_UserName->setText(entry->UserName);
Edit_URL->setText(entry->URL); Edit_URL->setText(entry->URL);
Edit_Password->setText(entry->Password.getString()); entry->Password.unlock();
Edit_Password_w->setText(entry->Password.getString()); Edit_Password->setText(entry->Password.string());
entry->Password.delRef(); Edit_Password_w->setText(entry->Password.string());
entry->Password.lock();
if(!config.ShowPasswords) if(!config.ShowPasswords)
ChangeEchoMode(); ChangeEchoMode();
OnPasswordwLostFocus(); OnPasswordwLostFocus();
@ -171,10 +172,10 @@ if(entry->URL!=Edit_URL->text())
ModFlag=true; ModFlag=true;
if(entry->Additional!=Edit_Comment->text()) if(entry->Additional!=Edit_Comment->text())
ModFlag=true; ModFlag=true;
QString& passw=entry->Password.getString(); entry->Password.unlock();
if(passw!=Edit_Password->text()) if(entry->Password.string()!=Edit_Password->text())
ModFlag=true; ModFlag=true;
entry->Password.delRef(); entry->Password.lock();
entry->Expire=DateTime_Expire->dateTime(); entry->Expire=DateTime_Expire->dateTime();
entry->LastAccess=QDateTime::currentDateTime(); entry->LastAccess=QDateTime::currentDateTime();

@ -92,15 +92,16 @@ for(int i=0;i<db->Entries.size();i++){
else else
if(db->Entries[i].GroupID != group->ID)continue; if(db->Entries[i].GroupID != group->ID)continue;
} }
bool hit=false; bool hit=false;
if(checkBox_Title->isChecked()) hit=hit||search(db->Entries[i].Title); if(checkBox_Title->isChecked()) hit=hit||search(db->Entries[i].Title);
if(checkBox_Username->isChecked()) hit=hit||search(db->Entries[i].UserName); if(checkBox_Username->isChecked()) hit=hit||search(db->Entries[i].UserName);
if(checkBox_URL->isChecked()) hit=hit||search(db->Entries[i].URL); if(checkBox_URL->isChecked()) hit=hit||search(db->Entries[i].URL);
if(checkBox_Comment->isChecked()) hit=hit||search(db->Entries[i].Additional); if(checkBox_Comment->isChecked()) hit=hit||search(db->Entries[i].Additional);
if(checkBox_Attachment->isChecked()) hit=hit||search(db->Entries[i].BinaryDesc); if(checkBox_Attachment->isChecked()) hit=hit||search(db->Entries[i].BinaryDesc);
if(checkBox_Password->isChecked()) hit=hit||search(db->Entries[i].Password.getString()); db->Entries[i].Password.unlock();
db->Entries[i].Password.delRef(); if(checkBox_Password->isChecked()) hit=hit||search(db->Entries[i].Password.string());
db->Entries[i].Password.lock();
if(hit)Hits.push_back(db->Entries[i].sID); if(hit)Hits.push_back(db->Entries[i].sID);
} }
@ -109,7 +110,7 @@ done(1);
} }
bool CSearchDlg::search(QString& str){ bool CSearchDlg::search(const QString& str){
if(regexp){ if(regexp){
QRegExp exp(txt,checkBox_Cs->isChecked()); QRegExp exp(txt,checkBox_Cs->isChecked());

@ -41,7 +41,7 @@ private:
CGroup* group; CGroup* group;
bool regexp; bool regexp;
PwDatabase* db; PwDatabase* db;
bool search(QString& str); bool search(const QString& str);
}; };
#endif #endif

@ -69,14 +69,31 @@ ContextMenu->popup(e->globalPos());
void KeepassEntryView::updateItems(unsigned int GroupID){ void KeepassEntryView::updateItems(unsigned int GroupID){
clear(); clear();
Items.clear(); Items.clear();
if(!db)return; if(!db)return;
if(!GroupID)return; if(!GroupID)return;
EntryViewItem *tmp=NULL;
for(int i=0;i<db->Entries.size();i++){ for(int i=0;i<db->Entries.size();i++){
CEntry* entry=&db->Entries[i]; if(db->Entries[i].GroupID==GroupID)
if(entry->GroupID==GroupID){ setEntry(&db->Entries[i]);
}
}
void KeepassEntryView::showSearchResults(QList<Q_UINT32>& results){
clear();
Items.clear();
for(int j=0; j<results.size(); j++){
for(int i=0; i<db->Entries.size();i++){
if(db->Entries[i].sID == results[j])
setEntry(&db->Entries[i]);
}
}
}
void KeepassEntryView::setEntry(CEntry* entry){
EntryViewItem* tmp=NULL;
Items.push_back(tmp=new EntryViewItem(this)); Items.push_back(tmp=new EntryViewItem(this));
Items.back()->pEntry=entry; Items.back()->pEntry=entry;
int j=0; int j=0;
@ -93,8 +110,9 @@ for(int i=0;i<db->Entries.size();i++){
if(config.ListView_HidePasswords) if(config.ListView_HidePasswords)
tmp->setText(j++,"******"); tmp->setText(j++,"******");
else{ else{
tmp->setText(j++,entry->Password.getString()); entry->Password.unlock();
entry->Password.delRef();}} tmp->setText(j++,entry->Password.string());
entry->Password.lock();}}
if(config.Columns[4]){ if(config.Columns[4]){
tmp->setText(j++,entry->Additional.section('\n',0,0));} tmp->setText(j++,entry->Additional.section('\n',0,0));}
if(config.Columns[5]){ if(config.Columns[5]){
@ -108,17 +126,6 @@ for(int i=0;i<db->Entries.size();i++){
if(config.Columns[9]){ if(config.Columns[9]){
tmp->setText(j++,entry->BinaryDesc);} tmp->setText(j++,entry->BinaryDesc);}
Items.back()->setIcon(0,EntryIcons[entry->ImageID]); Items.back()->setIcon(0,EntryIcons[entry->ImageID]);
}}
}
void KeepassEntryView::showSearchResults(QList<Q_UINT32>& results){
updateItems(0);
for(int j=0; j<results.size(); j++){
for(int i=0; i<Items.size();i++){
if(Items[i]->pEntry->sID == results[j])
setItemHidden(Items[i],false);
}
}
} }
void KeepassEntryView::refreshItems(){ void KeepassEntryView::refreshItems(){
@ -141,8 +148,9 @@ for(int i=0;i<Items.size();i++){
if(config.ListView_HidePasswords) if(config.ListView_HidePasswords)
tmp->setText(j++,"******"); tmp->setText(j++,"******");
else{ else{
tmp->setText(j++,entry->Password.getString()); entry->Password.unlock();
entry->Password.delRef();}} tmp->setText(j++,entry->Password.string());
entry->Password.lock();}}
if(config.Columns[4]){ if(config.Columns[4]){
tmp->setText(j++,entry->Additional.section('\n',0,0));} tmp->setText(j++,entry->Additional.section('\n',0,0));}
if(config.Columns[5]){ if(config.Columns[5]){

@ -38,6 +38,7 @@ public:
vector<EntryViewItem*>Items; vector<EntryViewItem*>Items;
QMenu *ContextMenu; QMenu *ContextMenu;
private: private:
void setEntry(CEntry* entry);
int CurrentGroup; int CurrentGroup;
protected: protected:
virtual void contextMenuEvent(QContextMenuEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event);

@ -19,83 +19,89 @@
***************************************************************************/ ***************************************************************************/
#include "SecString.h" #include "SecString.h"
#include <qmessagebox.h>
#include <iostream> #include <iostream>
#include "crypto/arcfour.h"
#include "random.h" #include "random.h"
using namespace std; using namespace std;
Q_UINT8 SecString::Key[32]={0}; CArcFour SecString::RC4;
SecString::operator QString(){
return string();
}
SecString::SecString(){ SecString::SecString(){
len=0; locked=true;
} }
int SecString::length(){
return crypt.size();
}
SecString::~SecString(){ SecString::~SecString(){
overwrite(plaintext); lock();
} }
void SecString::getString(QString & str){ void SecString::lock(){
if(data.size()){ locked=true;
Rijndael aes; overwrite(plain);
int r=aes.init(Rijndael::CBC, Rijndael::Decrypt,Key,Rijndael::Key32Bytes); plain=QString();
if(r){ cout << "AES error, code " << r << endl;
exit(-1);}
char* out=new char[len];
r=aes.padDecrypt((unsigned char*)data.data(),data.size(),(unsigned char*)out);
if(r!=len){ cout << "AES error in SecString::getString(), r!=length, r=" << r << endl;
exit(-1);}
str=QString::fromUtf8(out,len);
overwrite(out,len);
delete [] out;
}
} }
QString& SecString::getString(){ void SecString::unlock(){
getString(plaintext); locked=false;
return plaintext; plain=QString();
if(!crypt.length()){return;}
const unsigned char* buffer=new unsigned char[crypt.length()];
SecString::RC4.decrypt((byte*)crypt.data(),(unsigned char*)buffer,crypt.length());
plain=QString::fromUtf8((const char*)buffer,crypt.size());
overwrite((unsigned char*)buffer,crypt.size());
delete [] buffer;
} }
void SecString::delRef(){
overwrite(plaintext); const QString& SecString::string(){
if(locked){
printf("Error in function SecString::string(): string is locked\n");
return QString(">SEC_STRING_ERROR<");
}
return plain;
} }
void SecString::setString(QString& str,bool DelSrc){
Rijndael aes; void SecString::setString(QString& str,bool DeleteSource){
int r=aes.init(Rijndael::CBC, Rijndael::Encrypt,Key,Rijndael::Key32Bytes); QByteArray StrData=str.toUtf8();
if(r){ cout << "AES error, code " << r << endl; int len=StrData.size();
exit(-1);} unsigned char* buffer=new unsigned char[len];
int il=str.length(); SecString::RC4.encrypt((const unsigned char*)StrData.data(),buffer,len);
char* input=new char[il]; crypt=QByteArray((const char*)buffer,len);
char* output=new char[il+16]; overwrite(buffer,len);
memcpy(input,str.utf8(),il); overwrite((unsigned char*)StrData.data(),len);
r=aes.padEncrypt((unsigned char*)input,il,(unsigned char*)output); delete [] buffer;
if(r<0){ cout << "AES error, code " << r << endl; if(DeleteSource){
exit(-1);} overwrite(str);
len=il; str=QString();}
data=QByteArray(output,r); lock();
overwrite(input,il);
delete [] input;
if(DelSrc)overwrite(str);
} }
void SecString::overwrite(char* str,int strlen){ void SecString::overwrite(unsigned char* str,int strlen){
if(strlen==0 || str==NULL)return; if(strlen==0 || str==NULL)return;
getRandomBytes(str,strlen,1,false); for(int i=0; i<strlen; i++){
str[i]=0;
}
} }
void SecString::overwrite(QString &str){ void SecString::overwrite(QString &str){
if(str.length()==0)return; if(str.length()==0)return;
char* tmp=new char[str.length()]; for(int i=0; i<str.length(); i++){
getRandomBytes(tmp,str.length(),1,false); ((char*)str.data())[i]=0;
str=tmp;
delete [] tmp;
} }
int SecString::length(){
return len;
} }
void SecString::generateSessionKey(){
getRandomBytes(Key,32,1,false);
}
void SecString::generateSessionKey(){
CArcFour arc;
unsigned char* sessionkey=new unsigned char[32];
getRandomBytes(sessionkey,32,1,false);
RC4.setKey(sessionkey,32);
delete [] sessionkey;
}

@ -23,28 +23,29 @@
#include <QByteArray> #include <QByteArray>
#include <qstring.h> #include <qstring.h>
#include <qglobal.h> #include <qglobal.h>
#include "crypto/rijndael.h" #include "crypto/arcfour.h"
class SecString{ class SecString{
public: public:
SecString(unsigned char* key);
SecString(); SecString();
~SecString(); ~SecString();
void getString(QString& str);
QString& getString();
void setString(QString& str, bool DelSrc=false); void setString(QString& str, bool DelSrc=false);
void delRef(); void lock();
static void overwrite(char* str,int len); void unlock();
static void overwrite(QString& str); const QString& string();
operator QString();
int length(); int length();
static void overwrite(unsigned char* str,int len);
static void overwrite(QString& str);
static void generateSessionKey(); static void generateSessionKey();
private: private:
static Q_UINT8 Key[32]; bool locked;
QString plaintext; static CArcFour RC4;
QByteArray data; QByteArray crypt;
int len; QString plain;
}; };

@ -123,6 +123,8 @@ if(config.Language!="_DEUTSCH_"){
DateTimeFormat=QObject::trUtf8("dd'.'MM'.'yy' 'hh':'mm"); DateTimeFormat=QObject::trUtf8("dd'.'MM'.'yy' 'hh':'mm");
loadImages(); loadImages();
SecString::generateSessionKey();
KeepassMainWindow *mainWin = new KeepassMainWindow(); KeepassMainWindow *mainWin = new KeepassMainWindow();
mainWin->show(); mainWin->show();
int r=app->exec(); int r=app->exec();

@ -1,5 +1,5 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2005 by Tarek Saidi * * Copyright (C) 2005-2006 by Tarek Saidi *
* tarek.saidi@arcor.de * * tarek.saidi@arcor.de *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
@ -303,9 +303,10 @@ void KeepassMainWindow::OnFileOpen(){
if(FileOpen) if(FileOpen)
if(!closeDatabase())return; if(!closeDatabase())return;
QString filename=QFileDialog::getOpenFileName(this,trUtf8("Databank öffnen..."),QDir::homePath(),"*.kdb"); QString filename=QFileDialog::getOpenFileName(this,trUtf8("Databank öffnen..."),QDir::homePath(),"*.kdb");
if(filename!=QString::null) if(filename!=QString::null){
openDatabase(filename); openDatabase(filename);
} }
}
void KeepassMainWindow::OnFileClose(){ void KeepassMainWindow::OnFileClose(){
closeDatabase(); closeDatabase();
@ -394,22 +395,26 @@ if(EntryView->selectedItems().size()!=1){
CEntry& entry=*((EntryViewItem*)(EntryView->selectedItems()[0]))->pEntry; CEntry& entry=*((EntryViewItem*)(EntryView->selectedItems()[0]))->pEntry;
QString str=trUtf8("<B>Gruppe: </B>%1 <B>Titel: </B>%2 <B>Benutzername: </B>%3 <B>URL: </B><a href=%4>%4</a> <B>Passwort: </B>%5 <B>Erstellt: </B>%6 <B>letzte Änderung: </B>%7 <B>letzter Zugriff: </B>%8 <B>gültig bis: </B>%9"); QString str=trUtf8("<B>Gruppe: </B>%1 <B>Titel: </B>%2 <B>Benutzername: </B>%3 <B>URL: </B><a href=%4>%4</a> <B>Passwort: </B>%5 <B>Erstellt: </B>%6 <B>letzte Änderung: </B>%7 <B>letzter Zugriff: </B>%8 <B>gültig bis: </B>%9");
str=str.arg(currentGroup()->Name).arg(entry.Title); //todo: a "CGroup* PwDatabase::getGroup(CEntry*)" method would be a good idea
str=str.arg(db->Groups[db->getGroupIndex(entry.GroupID)].Name).arg(entry.Title);
if(!config.ListView_HideUsernames) str=str.arg(entry.UserName); if(!config.ListView_HideUsernames) str=str.arg(entry.UserName);
else str=str.arg("****"); else str=str.arg("****");
str=str.arg(entry.URL); str=str.arg(entry.URL);
if(!config.ListView_HidePasswords) str=str.arg(entry.Password.getString()); entry.Password.unlock();
if(!config.ListView_HidePasswords) str=str.arg(entry.Password.string());
else str=str.arg("****"); else str=str.arg("****");
entry.Password.lock();
str=str.arg(entry.Creation.toString(Qt::LocalDate)) str=str.arg(entry.Creation.toString(Qt::LocalDate))
.arg(entry.LastMod.toString(Qt::LocalDate)) .arg(entry.LastMod.toString(Qt::LocalDate))
.arg(entry.LastAccess.toString(Qt::LocalDate)) .arg(entry.LastAccess.toString(Qt::LocalDate))
.arg(entry.Expire.toString(Qt::LocalDate)); .arg(entry.Expire.toString(Qt::LocalDate));
DetailView->setHtml(str); DetailView->setHtml(str);
entry.Password.delRef();
} }
@ -669,9 +674,10 @@ ClipboardTimer.start(config.ClipboardTimeOut*1000,true);
} }
void KeepassMainWindow::OnEditPasswordToClipboard(){ void KeepassMainWindow::OnEditPasswordToClipboard(){
Clipboard->setText(currentEntry()->Password.getString(),QClipboard::Clipboard); currentEntry()->Password.unlock();
Clipboard->setText(currentEntry()->Password.string(),QClipboard::Clipboard);
ClipboardTimer.start(config.ClipboardTimeOut*1000,true); ClipboardTimer.start(config.ClipboardTimeOut*1000,true);
currentEntry()->Password.delRef(); currentEntry()->Password.lock();
} }

@ -3,15 +3,8 @@
# Unterordner relativ zum Projektordner: ./src # Unterordner relativ zum Projektordner: ./src
# Das Target ist eine Anwendung: ../bin/keepass # Das Target ist eine Anwendung: ../bin/keepass
INSTALLS += target \ INSTALLS += Share
Share
Share.files += ../share/keepass/* Share.files += ../share/keepass/*
unix{ target.path = /usr/local/bin
Share.path = /usr/local/share/keepass
}
macx{ target.path = /Applications
Share.path = /Applications/keepass.app/Contents/share/keepass
}
FORMS += forms/EditGroupDlg.ui \ FORMS += forms/EditGroupDlg.ui \
forms/SearchDlg.ui \ forms/SearchDlg.ui \
forms/AboutDlg.ui \ forms/AboutDlg.ui \
@ -57,7 +50,8 @@ HEADERS += lib/IniReader.h \
global.h \ global.h \
main.h \ main.h \
lib/GroupView.h \ lib/GroupView.h \
lib/EntryView.h lib/EntryView.h \
crypto/arcfour.h
SOURCES += lib/IniReader.cpp \ SOURCES += lib/IniReader.cpp \
lib/UrlLabel.cpp \ lib/UrlLabel.cpp \
main.cpp \ main.cpp \
@ -88,7 +82,8 @@ SOURCES += lib/IniReader.cpp \
Database.cpp \ Database.cpp \
lib/KdePlugin.cpp \ lib/KdePlugin.cpp \
lib/GroupView.cpp \ lib/GroupView.cpp \
lib/EntryView.cpp lib/EntryView.cpp \
crypto/arcfour.cpp
QT += xml \ QT += xml \
qt3support qt3support
MOC_DIR = ../build/moc MOC_DIR = ../build/moc
@ -103,3 +98,11 @@ thread \
exceptions \ exceptions \
stl stl
TEMPLATE = app TEMPLATE = app
unix{
target.path = /usr/local/bin
Share.path = /usr/local/share/keepass
}
macx{
target.path = /Applications
Share.path = /Applications/keepass.app/Contents/share/keepass
}