diff --git a/src/format/KeePass2.h b/src/format/KeePass2.h index 913547623..94bb1378b 100644 --- a/src/format/KeePass2.h +++ b/src/format/KeePass2.h @@ -33,6 +33,8 @@ namespace KeePass2 const Uuid CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff")); + const QByteArray INNER_STREAM_SALSA20_IV("\xE8\x30\x09\x4B\x97\x20\x5D\x2A"); + enum HeaderFieldID { EndOfHeader = 0, diff --git a/src/format/KeePass2Reader.cpp b/src/format/KeePass2Reader.cpp index 1a499d1ce..c6dd31c5f 100644 --- a/src/format/KeePass2Reader.cpp +++ b/src/format/KeePass2Reader.cpp @@ -98,10 +98,9 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke } QByteArray protectedStreamKey = CryptoHash::hash(m_protectedStreamKey, CryptoHash::Sha256); - QByteArray protectedStreamIv("\xE8\x30\x09\x4B\x97\x20\x5D\x2A"); SymmetricCipher protectedStream(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher::Decrypt, - protectedStreamKey, protectedStreamIv); + protectedStreamKey, KeePass2::INNER_STREAM_SALSA20_IV); KeePass2XmlReader xmlReader; xmlReader.readDatabase(xmlDevice, m_db, &protectedStream); diff --git a/src/format/KeePass2Writer.cpp b/src/format/KeePass2Writer.cpp index 115c143a5..a44b7366f 100644 --- a/src/format/KeePass2Writer.cpp +++ b/src/format/KeePass2Writer.cpp @@ -45,11 +45,13 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) QByteArray masterSeed = Random::randomArray(32); QByteArray encryptionIV = Random::randomArray(16); + QByteArray protectedStreamKey = Random::randomArray(32); QByteArray startBytes = Random::randomArray(32); QByteArray endOfHeader = "\r\n\r\n"; CryptoHash hash(CryptoHash::Sha256); hash.addData(masterSeed); + Q_ASSERT(!db->transformedMasterKey().isEmpty()); hash.addData(db->transformedMasterKey()); QByteArray finalKey = hash.result(); @@ -64,7 +66,9 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) CHECK_RETURN(writeHeaderField(KeePass2::TransformSeed, db->transformSeed())); CHECK_RETURN(writeHeaderField(KeePass2::TransformRounds, Endian::int64ToBytes(db->transformRounds(), KeePass2::BYTEORDER))); CHECK_RETURN(writeHeaderField(KeePass2::EncryptionIV, encryptionIV)); + CHECK_RETURN(writeHeaderField(KeePass2::ProtectedStreamKey, protectedStreamKey)); CHECK_RETURN(writeHeaderField(KeePass2::StreamStartBytes, startBytes)); + CHECK_RETURN(writeHeaderField(KeePass2::InnerRandomStreamID, Endian::int32ToBytes(KeePass2::Salsa20, KeePass2::BYTEORDER))); CHECK_RETURN(writeHeaderField(KeePass2::EndOfHeader, endOfHeader)); SymmetricCipherStream cipherStream(device, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt, finalKey, encryptionIV); @@ -87,8 +91,11 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) m_device = ioCompressor.data(); } + SymmetricCipher protectedStream(SymmetricCipher::Salsa20, SymmetricCipher::Stream, SymmetricCipher::Encrypt, + CryptoHash::hash(protectedStreamKey, CryptoHash::Sha256), KeePass2::INNER_STREAM_SALSA20_IV); + KeePass2XmlWriter xmlWriter; - xmlWriter.writeDatabase(m_device, db); + xmlWriter.writeDatabase(m_device, db, &protectedStream); } bool KeePass2Writer::writeData(const QByteArray& data)