|
|
On Thursday 01 November 2007, Mike Broida wrote:
> > Action 3: scatter some random data in your exe, use this data plus some
> > salt value (eg. the current time when the password is stored) and hash
> > it using QCryptographicHash. Xor the (properly truncated) result with
> > the password and store the encrypted password and the salt value in the
> > ini file.
>
> This sounds interesting. So encryption part is just the XOR with a
> keyvalue (that the code rebuilds from less obvious parts). Then
> decryption is just XORing the encrypted value with that keyvalue. Hmmm.
> A bit of both encryption and obfuscation. Sounds like it might be
> enough. :)
Well, this is how all stream-ciphers work: you have an algorithm that
generates a stream of bytes (key-stream) from a key (and often an
additional Initialization Vector - IV, or salt). Then you xor this stream
with the clear text data. The strength of a stream cipher depends on how
easy it is to guess the key from the key-stream and how easy it is to guess
any byte in the stream from preceding or following bytes.
One of the beauties of stream ciphers is that they are symmetrical: you use
the same key and algorithm for decryption. One of the dangers is that you
should never use the same key twice or you risk to reveal information about
the encrypted data:
encrypted1 = data1 xor keystream
encrypted2 = data2 xor keystream
encrypted1 xor encrypted2 == data1 xor data2
That's why I proposed to use a "salt" value.
The algorithm I proposed is directly dependent on the strength of the hash.
If the hash is perfect then the cipher should be pretty strong (approx. as
strong as the hash). Unfortunately there are no perfect hashes (esp. not
those in Qt), so the strength of the cipher decreases at least as much as
the strength of the hash is different from "perfect".
A little warning on the side: this kind of hash-based stream ciphers has not
been researched very much, since they are slower than genuine stream
ciphers.
Ok, since the "TEA faction" provided some code, here is some code how the
hash-based-stream-cipher should work:
//we assume that this is the password:
QByteArray pwd= .... /*get it from some configuration GUI*/;
//get key data
QByteArray key= .... /*get some bytes scattered throughout the exe*/;
QByteArray salt=QDateTime::currentDateTime().toString().toAscii();
//generate key stream
QByteArray kstream;
for(int ctr=0;kstream.size()<pwd.size();ctr++){
//unfortunately SHA1 is the strongest Hash available
QCryptographicHash hash(QCryptographicHash::Sha1);
//add key/salt
hash.addData(key);
hash.addData(salt);
//add counter so that blocks of keystream are different
//do this the complicted way to be portable:
QByteArray bctr;
bctr.append((char)((ctr>>24)&0xff));
bctr.append((char)((ctr>>16)&0xff));
bctr.append((char)((ctr>>8)&0xff));
bctr.append((char)(ctr&0xff));
hash.addData(bctr);
//append to key stream
kstream+=hash.result();
}
kstream.truncate(pwd.size());
//encrypt
for(int i=0;i<pwd.size();i++)
pwd[i] ^= kstream[i];
//store
QSettings ini("c:\\my\\ini\\file.ini",QSettings::IniFormat);
ini.setValue("pwdsalt",salt);
ini.setValue("encryptedpwd",pwd);
For decryption you simply get the salt and encrypted password from the ini
file and then run the same algorithm. (Xor is symmetric.)
Konrad
|
|