Added 2 new password generator options

git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@227 b624d157-de02-0410-bad0-e51aec6abb33
master
sniperbeamer 16 years ago
parent 598d204716
commit a5d427d262
  1. 2
      changelog
  2. 427
      src/Kdb3Database.cpp
  3. 4
      src/KpxConfig.h
  4. 2
      src/crypto/twoclass.cpp
  5. 164
      src/dialogs/PasswordGenDlg.cpp
  6. 8
      src/dialogs/PasswordGenDlg.h
  7. 28
      src/forms/PasswordGenDlg.ui
  8. 1
      src/lib/EntryView.cpp
  9. 2
      src/lib/SecString.cpp
  10. 8
      src/lib/random.cpp
  11. 4
      src/lib/random.h
  12. 2
      src/mainwindow.cpp

@ -1,7 +1,7 @@
---------------------------- ----------------------------
0.3.3 (2008-08-11) 0.3.3 (2008-08-11)
---------------------------- ----------------------------
- fix an error when opening twofish encrypted databases - fixed error when opening twofish encrypted databases (Bug #2025075)
---------------------------- ----------------------------
0.3.2 (2008-07-20) 0.3.2 (2008-07-20)

@ -478,237 +478,237 @@ void Kdb3Database::restoreGroupTreeState(){
return false; return false;
bool Kdb3Database::load(QString filename){ bool Kdb3Database::load(QString filename){
unsigned long total_size,crypto_size; unsigned long total_size,crypto_size;
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags; quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
quint8 FinalRandomSeed[16]; quint8 FinalRandomSeed[16];
quint8 ContentsHash[32]; quint8 ContentsHash[32];
quint8 EncryptionIV[16]; quint8 EncryptionIV[16];
File = new QFile(filename); File = new QFile(filename);
if(!File->open(QIODevice::ReadWrite)){ if(!File->open(QIODevice::ReadWrite)){
if(!File->open(QIODevice::ReadOnly)){ if(!File->open(QIODevice::ReadOnly)){
error=tr("Could not open file."); error=tr("Could not open file.");
delete File; delete File;
File = NULL; File = NULL;
return false; return false;
}
} }
} total_size=File->size();
total_size=File->size(); char* buffer = new char[total_size];
char* buffer = new char[total_size]; File->read(buffer,total_size);
File->read(buffer,total_size);
if(total_size < DB_HEADER_SIZE){
if(total_size < DB_HEADER_SIZE){ error=tr("Unexpected file size (DB_TOTAL_SIZE < DB_HEADER_SIZE)");
error=tr("Unexpected file size (DB_TOTAL_SIZE < DB_HEADER_SIZE)");
LOAD_RETURN_CLEANUP
}
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(TransfRandomSeed,buffer+88,32);
memcpyFromLEnd32(&KeyTransfRounds,buffer+120);
if((Signature1!=PWM_DBSIG_1) || (Signature2!=PWM_DBSIG_2)){
error=tr("Wrong Signature");
LOAD_RETURN_CLEANUP
}
if((Version & 0xFFFFFF00) != (PWM_DBVER_DW & 0xFFFFFF00)){
error=tr("Unsupported File Version.");
LOAD_RETURN_CLEANUP
}
if (Flags & PWM_FLAG_RIJNDAEL)
Algorithm = Rijndael_Cipher;
else if (Flags & PWM_FLAG_TWOFISH)
Algorithm = Twofish_Cipher;
else{
error=tr("Unknown Encryption Algorithm.");
LOAD_RETURN_CLEANUP
}
RawMasterKey.unlock();
MasterKey.unlock();
KeyTransform::transform(*RawMasterKey,*MasterKey,TransfRandomSeed,KeyTransfRounds);
quint8 FinalKey[32];
SHA256 sha;
sha.update(FinalRandomSeed,16);
sha.update(*MasterKey,32);
sha.finish(FinalKey);
RawMasterKey.lock();
MasterKey.lock();
if(Algorithm == Rijndael_Cipher){
AESdecrypt aes;
aes.key256(FinalKey);
aes.cbc_decrypt((unsigned char*)buffer+DB_HEADER_SIZE,(unsigned char*)buffer+DB_HEADER_SIZE,total_size-DB_HEADER_SIZE,(unsigned char*)EncryptionIV);
crypto_size=total_size-((quint8*)buffer)[total_size-1]-DB_HEADER_SIZE;
}
else if(Algorithm == Twofish_Cipher){
CTwofish twofish;
if (twofish.init(FinalKey, 32, EncryptionIV) != true){
error=tr("Unable to initalize the twofish algorithm.");
LOAD_RETURN_CLEANUP LOAD_RETURN_CLEANUP
} }
crypto_size = (unsigned long)twofish.padDecrypt((quint8 *)buffer + DB_HEADER_SIZE,
total_size - DB_HEADER_SIZE, (quint8 *)buffer + DB_HEADER_SIZE); memcpyFromLEnd32(&Signature1,buffer);
} memcpyFromLEnd32(&Signature2,buffer+4);
memcpyFromLEnd32(&Flags,buffer+8);
if ((crypto_size > 2147483446) || (!crypto_size && NumGroups)){ memcpyFromLEnd32(&Version,buffer+12);
error=tr("Decryption failed.\nThe key is wrong or the file is damaged."); memcpy(FinalRandomSeed,buffer+16,16);
LOAD_RETURN_CLEANUP memcpy(EncryptionIV,buffer+32,16);
} memcpyFromLEnd32(&NumGroups,buffer+48);
SHA256::hashBuffer(buffer+DB_HEADER_SIZE,FinalKey,crypto_size); memcpyFromLEnd32(&NumEntries,buffer+52);
memcpy(ContentsHash,buffer+56,32);
if(memcmp(ContentsHash, FinalKey, 32) != 0){ memcpy(TransfRandomSeed,buffer+88,32);
if(PotentialEncodingIssue){ memcpyFromLEnd32(&KeyTransfRounds,buffer+120);
delete[] buffer;
delete File; if((Signature1!=PWM_DBSIG_1) || (Signature2!=PWM_DBSIG_2)){
File = NULL; error=tr("Wrong Signature");
// KeePassX used Latin-1 encoding for passwords until version 0.3.1
// but KeePass/Win32 uses Windows Codepage 1252.
// Too stay compatible with databases created with KeePassX <= 0.3.1
// the loading function gives both encodings a try.
RawMasterKey.copyData(RawMasterKey_Latin1);
PotentialEncodingIssue=false;
qDebug("Decryption failed. Retrying with Latin-1.");
return load(filename); // second try
}
error=tr("Hash test failed.\nThe key is wrong or the file is damaged.");
KeyError=true;
LOAD_RETURN_CLEANUP
}
unsigned long pos = DB_HEADER_SIZE;
quint16 FieldType;
quint32 FieldSize;
char* pField;
bool bRet;
StdGroup group;
QList<quint32> Levels;
RootGroup.Title="$ROOT$";
RootGroup.Parent=NULL;
RootGroup.Handle=NULL;
for(unsigned long CurGroup = 0; CurGroup < NumGroups; )
{
pField = buffer+pos;
memcpyFromLEnd16(&FieldType, pField);
pField += 2; pos += 2;
if (pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [G1]");
LOAD_RETURN_CLEANUP LOAD_RETURN_CLEANUP
} }
memcpyFromLEnd32(&FieldSize, pField); if((Version & 0xFFFFFF00) != (PWM_DBVER_DW & 0xFFFFFF00)){
pField += 4; pos += 4; error=tr("Unsupported File Version.");
if (pos >= (total_size + FieldSize)){
error=tr("Unexpected error: Offset is out of range.").append(" [G2]");
LOAD_RETURN_CLEANUP LOAD_RETURN_CLEANUP
} }
bRet = readGroupField(&group,Levels, FieldType, FieldSize, (quint8 *)pField); if (Flags & PWM_FLAG_RIJNDAEL)
if ((FieldType == 0xFFFF) && (bRet == true)){ Algorithm = Rijndael_Cipher;
Groups << group; else if (Flags & PWM_FLAG_TWOFISH)
CurGroup++; // Now and ONLY now the counter gets increased Algorithm = Twofish_Cipher;
} else{
pField += FieldSize; error=tr("Unknown Encryption Algorithm.");
pos += FieldSize;
if (pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [G1]");
LOAD_RETURN_CLEANUP LOAD_RETURN_CLEANUP
} }
}
RawMasterKey.unlock();
StdEntry entry; MasterKey.unlock();
KeyTransform::transform(*RawMasterKey,*MasterKey,TransfRandomSeed,KeyTransfRounds);
for (unsigned long CurEntry = 0; CurEntry < NumEntries;)
{ quint8 FinalKey[32];
pField = buffer+pos;
SHA256 sha;
memcpyFromLEnd16(&FieldType, pField); sha.update(FinalRandomSeed,16);
pField += 2; pos += 2; sha.update(*MasterKey,32);
if(pos >= total_size){ sha.finish(FinalKey);
error=tr("Unexpected error: Offset is out of range.").append(" [E1]");
RawMasterKey.lock();
MasterKey.lock();
if(Algorithm == Rijndael_Cipher){
AESdecrypt aes;
aes.key256(FinalKey);
aes.cbc_decrypt((unsigned char*)buffer+DB_HEADER_SIZE,(unsigned char*)buffer+DB_HEADER_SIZE,total_size-DB_HEADER_SIZE,(unsigned char*)EncryptionIV);
crypto_size=total_size-((quint8*)buffer)[total_size-1]-DB_HEADER_SIZE;
}
else if(Algorithm == Twofish_Cipher){
CTwofish twofish;
if (twofish.init(FinalKey, 32, EncryptionIV) != true){
error=tr("Unable to initalize the twofish algorithm.");
LOAD_RETURN_CLEANUP
}
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)){
error=tr("Decryption failed.\nThe key is wrong or the file is damaged.");
LOAD_RETURN_CLEANUP LOAD_RETURN_CLEANUP
} }
SHA256::hashBuffer(buffer+DB_HEADER_SIZE,FinalKey,crypto_size);
memcpyFromLEnd32(&FieldSize, pField);
pField += 4; pos += 4; if(memcmp(ContentsHash, FinalKey, 32) != 0){
if (pos >= (total_size + FieldSize)){ if(PotentialEncodingIssue){
error=tr("Unexpected error: Offset is out of range.").append(" [E2]"); delete[] buffer;
delete File;
File = NULL;
// KeePassX used Latin-1 encoding for passwords until version 0.3.1
// but KeePass/Win32 uses Windows Codepage 1252.
// Too stay compatible with databases created with KeePassX <= 0.3.1
// the loading function gives both encodings a try.
RawMasterKey.copyData(RawMasterKey_Latin1);
PotentialEncodingIssue=false;
qDebug("Decryption failed. Retrying with Latin-1.");
return load(filename); // second try
}
error=tr("Hash test failed.\nThe key is wrong or the file is damaged.");
KeyError=true;
LOAD_RETURN_CLEANUP LOAD_RETURN_CLEANUP
} }
bRet = readEntryField(&entry,FieldType,FieldSize,(quint8*)pField); unsigned long pos = DB_HEADER_SIZE;
quint16 FieldType;
if((FieldType == 0xFFFF) && (bRet == true)){ quint32 FieldSize;
Entries << entry; char* pField;
if(!entry.GroupId) bool bRet;
qDebug("NULL: %i, '%s'", (int)CurEntry, (char*)entry.Title.toUtf8().data()); StdGroup group;
CurEntry++; QList<quint32> Levels;
RootGroup.Title="$ROOT$";
RootGroup.Parent=NULL;
RootGroup.Handle=NULL;
for(unsigned long CurGroup = 0; CurGroup < NumGroups; )
{
pField = buffer+pos;
memcpyFromLEnd16(&FieldType, pField);
pField += 2; pos += 2;
if (pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [G1]");
LOAD_RETURN_CLEANUP
}
memcpyFromLEnd32(&FieldSize, pField);
pField += 4; pos += 4;
if (pos >= (total_size + FieldSize)){
error=tr("Unexpected error: Offset is out of range.").append(" [G2]");
LOAD_RETURN_CLEANUP
}
bRet = readGroupField(&group,Levels, 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){
error=tr("Unexpected error: Offset is out of range.").append(" [G1]");
LOAD_RETURN_CLEANUP
}
} }
pField += FieldSize; StdEntry entry;
pos += FieldSize;
if (pos >= total_size){ for (unsigned long CurEntry = 0; CurEntry < NumEntries;)
error=tr("Unexpected error: Offset is out of range.").append(" [E3]"); {
pField = buffer+pos;
memcpyFromLEnd16(&FieldType, pField);
pField += 2; pos += 2;
if(pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [E1]");
LOAD_RETURN_CLEANUP
}
memcpyFromLEnd32(&FieldSize, pField);
pField += 4; pos += 4;
if (pos >= (total_size + FieldSize)){
error=tr("Unexpected error: Offset is out of range.").append(" [E2]");
LOAD_RETURN_CLEANUP
}
bRet = readEntryField(&entry,FieldType,FieldSize,(quint8*)pField);
if((FieldType == 0xFFFF) && (bRet == true)){
Entries << entry;
if(!entry.GroupId)
qDebug("NULL: %i, '%s'", (int)CurEntry, (char*)entry.Title.toUtf8().data());
CurEntry++;
}
pField += FieldSize;
pos += FieldSize;
if (pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [E3]");
LOAD_RETURN_CLEANUP
}
}
if(!createGroupTree(Levels)){
error=tr("Invalid group tree.");
LOAD_RETURN_CLEANUP LOAD_RETURN_CLEANUP
} }
}
delete [] buffer;
if(!createGroupTree(Levels)){
error=tr("Invalid group tree."); hasV4IconMetaStream = false;
LOAD_RETURN_CLEANUP for(int i=0;i<Entries.size();i++){
} if(isMetaStream(Entries[i]) && Entries[i].Comment=="KPX_CUSTOM_ICONS_4"){
hasV4IconMetaStream = true;
delete [] buffer; break;
}
hasV4IconMetaStream = false;
for(int i=0;i<Entries.size();i++){
if(isMetaStream(Entries[i]) && Entries[i].Comment=="KPX_CUSTOM_ICONS_4"){
hasV4IconMetaStream = true;
break;
} }
}
//Remove the metastreams from the entry list
//Remove the metastreams from the entry list for(int i=0;i<Entries.size();i++){
for(int i=0;i<Entries.size();i++){ if(isMetaStream(Entries[i])){
if(isMetaStream(Entries[i])){ if(!parseMetaStream(Entries[i]))
if(!parseMetaStream(Entries[i])) UnknownMetaStreams << Entries[i];
UnknownMetaStreams << Entries[i]; Entries.removeAt(i);
Entries.removeAt(i); i--;
i--; }
} }
}
int* EntryIndices=new int[Groups.size()];
int* EntryIndices=new int[Groups.size()]; for(int i=0;i<Groups.size();i++)EntryIndices[i]=0;
for(int i=0;i<Groups.size();i++)EntryIndices[i]=0;
for(int g=0;g<Groups.size();g++){
for(int g=0;g<Groups.size();g++){ for(int e=0;e<Entries.size();e++){
for(int e=0;e<Entries.size();e++){ if(Entries[e].GroupId==Groups[g].Id){
if(Entries[e].GroupId==Groups[g].Id){ Entries[e].Index=EntryIndices[g];
Entries[e].Index=EntryIndices[g]; EntryIndices[g]++;
EntryIndices[g]++; }
} }
} }
} delete [] EntryIndices;
delete [] EntryIndices; createHandles();
createHandles(); restoreGroupTreeState();
restoreGroupTreeState();
return true;
return true;
} }
QDateTime Kdb3Database::dateFromPackedStruct5(const unsigned char* pBytes){ QDateTime Kdb3Database::dateFromPackedStruct5(const unsigned char* pBytes){
@ -1614,10 +1614,7 @@ void Kdb3Database::create(){
RootGroup.Parent=NULL; RootGroup.Parent=NULL;
RootGroup.Handle=NULL; RootGroup.Handle=NULL;
Algorithm=Rijndael_Cipher; Algorithm=Rijndael_Cipher;
quint16 ran; KeyTransfRounds=50000;
randomize(&ran,2);
ran &= 0x03FF; // only use 10 bits -> max 1024
KeyTransfRounds=10000 + ran;
KeyError=false; KeyError=false;
} }

@ -75,6 +75,8 @@ public:
bool autoSaveChange(){return settings.value("Options/AutoSaveChange",false).toBool();} bool autoSaveChange(){return settings.value("Options/AutoSaveChange",false).toBool();}
int pwGenCategory(){return settings.value("Options/PwGenCategory",0).toInt();} int pwGenCategory(){return settings.value("Options/PwGenCategory",0).toInt();}
QString pwGenCharList(){return settings.value("Options/PwGenCharList").toString();} QString pwGenCharList(){return settings.value("Options/PwGenCharList").toString();}
bool pwGenExcludeLookAlike(){return settings.value("Options/PwGenExcludeLookAlike").toBool();}
bool pwGenEveryGroup(){return settings.value("Options/PwGenEveryGroup").toBool();}
int pwGenLength(){return settings.value("Options/PwGenLength",25).toInt();} int pwGenLength(){return settings.value("Options/PwGenLength",25).toInt();}
QBitArray pwGenOptions(){return stringToBitArray(settings.value("Options/PwGenOptions","11111000011110").toString(),14);} QBitArray pwGenOptions(){return stringToBitArray(settings.value("Options/PwGenOptions","11111000011110").toString(),14);}
bool rememberLastKey(){return settings.value("Options/RememberLastKey",true).toBool();} bool rememberLastKey(){return settings.value("Options/RememberLastKey",true).toBool();}
@ -136,6 +138,8 @@ public:
void setAutoSaveChange(bool value){settings.setValue("Options/AutoSaveChange",value);} void setAutoSaveChange(bool value){settings.setValue("Options/AutoSaveChange",value);}
void setPwGenCategory(int value){settings.setValue("Options/PwGenCategory",value);} void setPwGenCategory(int value){settings.setValue("Options/PwGenCategory",value);}
void setPwGenCharList(const QString& value){settings.setValue("Options/PwGenCharList",value);} void setPwGenCharList(const QString& value){settings.setValue("Options/PwGenCharList",value);}
void setPwGenExcludeLookAlike(bool value){settings.setValue("Options/PwGenExcludeLookAlike",value);}
void setPwGenEveryGroup(bool value){settings.setValue("Options/PwGenEveryGroup",value);}
void setPwGenLength(int value){settings.setValue("Options/PwGenLength",value);} void setPwGenLength(int value){settings.setValue("Options/PwGenLength",value);}
void setPwGenOptions(const QBitArray& value){settings.setValue("Options/PwGenOptions",bitArrayToString(value));} void setPwGenOptions(const QBitArray& value){settings.setValue("Options/PwGenOptions",bitArrayToString(value));}
void setRememberLastKey(bool value){settings.setValue("Options/RememberLastKey",value);} void setRememberLastKey(bool value){settings.setValue("Options/RememberLastKey",value);}

@ -18,7 +18,7 @@
***************************************************************************/ ***************************************************************************/
#include <qstring.h> #include <QString>
#include "twoclass.h" #include "twoclass.h"
static bool g_bInitialized = false; static bool g_bInitialized = false;

@ -22,6 +22,7 @@
#include "dialogs/PasswordGenDlg.h" #include "dialogs/PasswordGenDlg.h"
#include "dialogs/CollectEntropyDlg.h" #include "dialogs/CollectEntropyDlg.h"
#include "random.h"
#include "apg/randpass.h" #include "apg/randpass.h"
#include "apg/pronpass.h" #include "apg/pronpass.h"
@ -109,6 +110,8 @@ CGenPwDialog::CGenPwDialog(QWidget* parent, bool StandAloneMode,Qt::WFlags fl)
checkBoxPN->setChecked(true); checkBoxPN->setChecked(true);
checkBoxPS->setChecked(false); checkBoxPS->setChecked(false);
} }
Check_ExcludeLookAlike->setChecked(config->pwGenExcludeLookAlike());
Check_EveryGroup->setChecked(config->pwGenEveryGroup());
Spin_Num->setValue(config->pwGenLength()); Spin_Num->setValue(config->pwGenLength());
adjustSize(); adjustSize();
setMaximumSize(size()); setMaximumSize(size());
@ -139,6 +142,8 @@ CGenPwDialog::~CGenPwDialog(){
pwGenOptions.setBit(12,checkBoxPN->isChecked()); pwGenOptions.setBit(12,checkBoxPN->isChecked());
pwGenOptions.setBit(13,checkBoxPS->isChecked()); pwGenOptions.setBit(13,checkBoxPS->isChecked());
config->setPwGenOptions(pwGenOptions); config->setPwGenOptions(pwGenOptions);
config->setPwGenExcludeLookAlike(Check_ExcludeLookAlike->isChecked());
config->setPwGenEveryGroup(Check_EveryGroup->isChecked());
config->setPwGenLength(Spin_Num->value()); config->setPwGenLength(Spin_Num->value());
} }
@ -198,21 +203,6 @@ void CGenPwDialog::OnGeneratePw()
gen_pron_pass(buffer, hyphenated_word, length, length, mode); gen_pron_pass(buffer, hyphenated_word, length, length, mode);
delete[] hyphenated_word; delete[] hyphenated_word;
} }
else if (Radio_1->isChecked() && !checkBox5->isChecked() &&
!checkBox6->isChecked() && !checkBox7->isChecked())
{
unsigned int mode = 0;
if (checkBox1->isChecked())
mode |= S_CL;
if (checkBox2->isChecked())
mode |= S_SL;
if (checkBox3->isChecked())
mode |= S_NB;
if (checkBox4->isChecked())
mode |= S_SS;
gen_rand_pass(buffer, length, length, mode);
}
else{ else{
generatePasswordInternal(buffer, length); generatePasswordInternal(buffer, length);
} }
@ -221,24 +211,6 @@ void CGenPwDialog::OnGeneratePw()
delete[] buffer; delete[] buffer;
} }
int CGenPwDialog::AddToAssoctable(char* table,int start,int end,int pos){
for(int i=start;i<=end;i++){
table[pos]=i;
pos++;
}
return (end-start)+1;
}
bool CGenPwDialog::trim(unsigned char &x, int r){
if(x<r)
return true;
if(256%r!=0)
return false;
x=x-(x/r)*r;
return true;
}
void CGenPwDialog::estimateQuality(){ void CGenPwDialog::estimateQuality(){
int num=0; int num=0;
if (tabCategory->currentIndex()==0){ if (tabCategory->currentIndex()==0){
@ -340,6 +312,32 @@ void CGenPwDialog::SwapEchoMode(){
} }
} }
void CGenPwDialog::AddToAssoctable(char* table,int start,int end,int& pos){
for (int i=start;i<=end;i++){
if (Check_ExcludeLookAlike->isChecked()){
switch (i){
case 48: // 0
case 79: // O
case 49: // 1
case 73: // I
case 108: // l
case 124: // |
continue;
}
}
table[pos]=i;
pos++;
}
}
CGenPwDialog::PwGroup CGenPwDialog::AddToAssoctableGroup(char* table,int start,int end,int& pos){
PwGroup group;
group.start = pos;
AddToAssoctable(table,start,end,pos);
group.end = pos-1;
return group;
}
void CGenPwDialog::generatePasswordInternal(char* buffer, int length){ void CGenPwDialog::generatePasswordInternal(char* buffer, int length){
/*------------------------------------------------------- /*-------------------------------------------------------
ASCII ASCII
@ -355,26 +353,62 @@ void CGenPwDialog::generatePasswordInternal(char* buffer, int length){
int num=0; int num=0;
char assoctable[255]; char assoctable[255];
int groups=0;
bool ensureEveryGroup = false;
QList<PwGroup> groupTable;
if(Radio_1->isChecked()){ if(Radio_1->isChecked()){
if(checkBox1->isChecked()) if (Check_EveryGroup->isChecked()){
num+=AddToAssoctable(assoctable,65,90,num); if (checkBox1->isChecked()) groups++;
if(checkBox2->isChecked()) if (checkBox2->isChecked()) groups++;
num+=AddToAssoctable(assoctable,97,122,num); if (checkBox3->isChecked()) groups++;
if(checkBox3->isChecked()) if (checkBox4->isChecked()) groups++;
num+=AddToAssoctable(assoctable,48,57,num); if (checkBox5->isChecked()) groups++;
if (checkBox6->isChecked()) groups++;
if (checkBox7->isChecked()) groups++;
if (groups<=length)
ensureEveryGroup = true;
}
if(checkBox1->isChecked()){
if (ensureEveryGroup) groupTable.append(AddToAssoctableGroup(assoctable,65,90,num));
else AddToAssoctable(assoctable,65,90,num);
}
if(checkBox2->isChecked()){
if (ensureEveryGroup) groupTable.append(AddToAssoctableGroup(assoctable,97,122,num));
else AddToAssoctable(assoctable,97,122,num);
}
if(checkBox3->isChecked()){
if (ensureEveryGroup) groupTable.append(AddToAssoctableGroup(assoctable,48,57,num));
else AddToAssoctable(assoctable,48,57,num);
}
if(checkBox4->isChecked()){ if(checkBox4->isChecked()){
num+=AddToAssoctable(assoctable,33,47,num); PwGroup group;
num+=AddToAssoctable(assoctable,58,64,num); group.start = num;
num+=AddToAssoctable(assoctable,91,96,num); AddToAssoctable(assoctable,33,44,num);
num+=AddToAssoctable(assoctable,123,126,num); AddToAssoctable(assoctable,46,47,num);
AddToAssoctable(assoctable,58,64,num);
AddToAssoctable(assoctable,91,94,num);
AddToAssoctable(assoctable,96,96,num);
AddToAssoctable(assoctable,123,126,num);
if (ensureEveryGroup){
group.end = num-1;
groupTable.append(group);
}
}
if(checkBox5->isChecked()){
if (ensureEveryGroup) groupTable.append(AddToAssoctableGroup(assoctable,32,32,num));
else AddToAssoctable(assoctable,32,32,num);
}
if(checkBox6->isChecked()){
if (ensureEveryGroup) groupTable.append(AddToAssoctableGroup(assoctable,45,45,num));
else AddToAssoctable(assoctable,45,45,num);
}
if(checkBox7->isChecked()){
if (ensureEveryGroup) groupTable.append(AddToAssoctableGroup(assoctable,95,95,num));
else AddToAssoctable(assoctable,95,95,num);
} }
if(checkBox5->isChecked())
num+=AddToAssoctable(assoctable,32,32,num);
if(checkBox6->isChecked() && !checkBox4->isChecked())
num+=AddToAssoctable(assoctable,45,45,num);
if(checkBox7->isChecked() && !checkBox4->isChecked())
num+=AddToAssoctable(assoctable,95,95,num);
} }
else{ else{
QString str=Edit_chars->text(); QString str=Edit_chars->text();
@ -393,14 +427,30 @@ void CGenPwDialog::generatePasswordInternal(char* buffer, int length){
EntropyCollected=true; EntropyCollected=true;
} }
} }
unsigned char tmp; if (ensureEveryGroup){
for(int i=0;i<length;i++){ QList<int> charPos;
for (int i=0; i<length; i++)
do randomize(&tmp,1); charPos.append(i);
while(!trim(tmp,num));
for (int i=0; i<groups; i++){
buffer[i]=assoctable[tmp]; int posIndex = randintRange(0, charPos.count()-1);
int pos = charPos[posIndex];
charPos.removeAt(posIndex);
buffer[pos] = assoctable[randintRange(groupTable[i].start, groupTable[i].end)];
}
for (int i=groups; i<length; i++){
int posIndex = randintRange(0, charPos.count()-1);
int pos = charPos[posIndex];
charPos.removeAt(posIndex);
buffer[pos] = assoctable[randint(num)];
}
}
else{
qDebug("ja");
for (int i=0; i<length; i++)
buffer[i] = assoctable[randint(num)];
} }
} }

@ -32,8 +32,12 @@ class CGenPwDialog : public QDialog, public Ui_GenPwDlg
~CGenPwDialog(); ~CGenPwDialog();
private: private:
int AddToAssoctable(char* table,int start,int end,int pos); struct PwGroup {
bool trim(unsigned char &value,int range); int start;
int end;
};
void AddToAssoctable(char* table,int start,int end,int& pos);
PwGroup AddToAssoctableGroup(char* table,int start,int end,int& pos);
void paintEvent(QPaintEvent* event); void paintEvent(QPaintEvent* event);
void generatePasswordInternal(char* buffer, int length); void generatePasswordInternal(char* buffer, int length);
QPixmap BannerPixmap; QPixmap BannerPixmap;

@ -6,7 +6,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>462</width> <width>462</width>
<height>491</height> <height>543</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle" >
@ -43,7 +43,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>440</width> <width>440</width>
<height>219</height> <height>271</height>
</rect> </rect>
</property> </property>
<attribute name="title" > <attribute name="title" >
@ -102,7 +102,7 @@
<item row="2" column="1" > <item row="2" column="1" >
<widget class="QCheckBox" name="checkBox7" > <widget class="QCheckBox" name="checkBox7" >
<property name="text" > <property name="text" >
<string>U&amp;nderline</string> <string>&amp;Underline</string>
</property> </property>
<property name="shortcut" > <property name="shortcut" >
<string>Alt+N</string> <string>Alt+N</string>
@ -125,7 +125,7 @@
<item row="0" column="1" > <item row="0" column="1" >
<widget class="QCheckBox" name="checkBox5" > <widget class="QCheckBox" name="checkBox5" >
<property name="text" > <property name="text" >
<string>White &amp;Spaces</string> <string>&amp;White Spaces</string>
</property> </property>
<property name="shortcut" > <property name="shortcut" >
<string>Alt+S</string> <string>Alt+S</string>
@ -148,7 +148,7 @@
<item row="1" column="1" > <item row="1" column="1" >
<widget class="QCheckBox" name="checkBox6" > <widget class="QCheckBox" name="checkBox6" >
<property name="text" > <property name="text" >
<string>Minus</string> <string>&amp;Minus</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -219,6 +219,20 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QCheckBox" name="Check_ExcludeLookAlike" >
<property name="text" >
<string>Exclude look-alike characters</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="Check_EveryGroup" >
<property name="text" >
<string>Ensure that password contains characters from every group</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tabPronounceable" > <widget class="QWidget" name="tabPronounceable" >
@ -227,7 +241,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>440</width> <width>440</width>
<height>219</height> <height>271</height>
</rect> </rect>
</property> </property>
<attribute name="title" > <attribute name="title" >
@ -250,7 +264,7 @@
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout" > <layout class="QHBoxLayout" name="horizontalLayout" >
<item> <item>
<layout class="QGridLayout" name="gridLayout" > <layout class="QGridLayout" name="gridLayout_2" >
<property name="spacing" > <property name="spacing" >
<number>15</number> <number>15</number>
</property> </property>

@ -274,6 +274,7 @@ void KeepassEntryView::OnEditOpenUrl(){
void KeepassEntryView::OnEditCopyUrl(){ void KeepassEntryView::OnEditCopyUrl(){
if (selectedItems().size() == 0) return; if (selectedItems().size() == 0) return;
QString url = ((EntryViewItem*)selectedItems().first())->EntryHandle->url(); QString url = ((EntryViewItem*)selectedItems().first())->EntryHandle->url();
if (url.trimmed().isEmpty()) return;
if (url.startsWith("cmd://") && url.length()>6) if (url.startsWith("cmd://") && url.length()>6)
url = url.right(url.length()-6); url = url.right(url.length()-6);

@ -126,7 +126,7 @@ void SecData::unlock(){
} }
void SecData::copyData(quint8* src){ void SecData::copyData(quint8* src){
unlock(); locked = false;
memcpy(data, src, length); memcpy(data, src, length);
lock(); lock();
} }

@ -47,10 +47,14 @@ void getEntropy(quint8* buffer, int length){
} }
} }
quint32 randint(quint32 n){ quint32 randint(quint32 limit){
quint32 rand; quint32 rand;
randomize(&rand, 4); randomize(&rand, 4);
return (rand % n); return (rand % limit);
}
quint32 randintRange(quint32 min, quint32 max){
return min + randint(max-min+1);
} }
#if defined(Q_WS_X11) || defined(Q_WS_MAC) #if defined(Q_WS_X11) || defined(Q_WS_MAC)

@ -33,10 +33,12 @@ extern "C" {
#endif #endif
void getEntropy(quint8* buffer, int length); void getEntropy(quint8* buffer, int length);
quint32 randint(quint32 n); quint32 randint(quint32 limit); // generate random number: 0 <= n < limit
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
quint32 randintRange(quint32 min, quint32 max); // generate random number: min <= n <= max
#endif #endif

@ -354,6 +354,7 @@ void KeepassMainWindow::setupMenus(){
EditPasswordToClipboardAction->setShortcut(tr("Ctrl+C")); EditPasswordToClipboardAction->setShortcut(tr("Ctrl+C"));
EditUsernameToClipboardAction->setShortcut(tr("Ctrl+B")); EditUsernameToClipboardAction->setShortcut(tr("Ctrl+B"));
EditOpenUrlAction->setShortcut(tr("Ctrl+U")); EditOpenUrlAction->setShortcut(tr("Ctrl+U"));
EditCopyUrlAction->setShortcut(tr("Ctrl+I"));
EditNewEntryAction->setShortcut(tr("Ctrl+Y")); EditNewEntryAction->setShortcut(tr("Ctrl+Y"));
EditEditEntryAction->setShortcut(tr("Ctrl+E")); EditEditEntryAction->setShortcut(tr("Ctrl+E"));
EditDeleteEntryAction->setShortcut(tr("Ctrl+D")); EditDeleteEntryAction->setShortcut(tr("Ctrl+D"));
@ -630,7 +631,6 @@ void KeepassMainWindow::setStateFileOpen(bool IsOpen){
void KeepassMainWindow::setStateFileModified(bool mod){ void KeepassMainWindow::setStateFileModified(bool mod){
if (config->autoSaveChange() && mod && db->file()){ if (config->autoSaveChange() && mod && db->file()){
OnFileSave(); OnFileSave();
mod = false;
} }
ModFlag=mod; ModFlag=mod;