KeePass源代码分析 3----KeePass 文件格式
KeePass文件格式由文件头部和数据部分组成。由于文件存储涉及到密码安全方面的东西,所以硬盘存储的是 KeePass 文件经过加密后的文件数据。
总体上KeePass 的文件格式组织方式如下:
KeePass文件格式开始部分是头部信息,紧跟着是分组信息,最后才是关于密码的信息。首先我们分析 KeePass 的头部信息结构 PW_DBHEADER , PW_DBHEADER 在文件PwStructs.h 中定义。
/// Database header structure. All KeePass KDB files begin with this structure.
typedef struct _PW_DBHEADER
{
DWORD dwSignature1 ; ///< File identifier word, set to PWM_DBSIG_1.
DWORD dwSignature2 ; ///< File identifier word, set to PWM_DBSIG_2.
DWORD dwFlags ;
DWORD dwVersion ;
BYTE aMasterSeed [16]; ///< Seed that gets hashed with the user key to form the final key.
UINT8 aEncryptionIV [16]; ///< IV used for content encryption.
DWORD dwGroups ; ///< Number of groups in the database.
DWORD dwEntries ; ///< Number of entries in the database.
BYTE aContentsHash [32]; ///< SHA-256 hash of the database, used for integrity checking.
BYTE aMasterSeed2 [32]; ///< Seed used for the dwKeyEncRounds AES transformations.
DWORD dwKeyEncRounds ; ///< Number of master key transformations.
} PW_DBHEADER , * PPW_DBHEADER ;
头部结构信息开始的8 个字节分别是 dwSignature1 和 dwSignature 2,也就是 KeePass 文件格式的签名信息,其值分别等于 PWM_DBSIG_1 和 PWM_DBSIG_ 2 , PWM_DBSIG_1 和 PWM_DBSIG_ 2 在KeePass 中定义如下 :
#define PWM_DBSIG_1 0x9AA2D903
#define PWM_DBSIG_2 0xB54BFB65
它们的作用仅仅是作为识别KeePass 文件格式而已,没有特殊的意义。
dwFlags:标示对 KeePass 文件的数据部分(除文件头部信息)使用的加密算法,目前可用的加密算法有 AES 和 TWOFISH 算法。
dwVersion :标示KeePass 文件的版本号,可用于实现版本兼容性。
aMasterSeed :16 位的主密钥。是随机生成的,也就是没有 KeePass 的数据库文件所使用的 aMasterSeed 都不同。用于对用户密 钥进行加密。
aEncryptionIV :16 位密钥。也是随机生成的,用于对文件的数据部分进行加密。
dwGroups :标示本数据库文件中分组的条数。
dwEntries :标示本数据库文件中密码的条数。
aContentsHash :标示本数据库文件中数据部分的hash 值, KeePass 使用它进行完整性检查。
aMasterSeed2 :16 位次密钥。随机生成的。用途同 aMasterSeed 。
dwKeyEncRounds :标示用户密钥的加密次数。
KeePass的分组数据部分 是由 多个 PW_GROUP 依次存储。类似数组的存储结构。 PW_GROUP 在pwstructs.h 中定义,
/// Group structure, containing information about one group.
typedef struct _PW_GROUP
{
DWORD uGroupId ; ///< ID of the group. The ID is a unique identifier in one database.
DWORD uImageId ; ///< Index of the icon in the image list to use for this group.
TCHAR * pszGroupName ; ///< Name of the group.
PW_TIME tCreation ; ///< Time when the group was created.
PW_TIME tLastMod ; ///< Time when the group was last modified.
PW_TIME tLastAccess ; ///< Time when the group was last accessed.
PW_TIME tExpire ; ///< Time when the group will expire.
USHORT usLevel ; ///< Indentation/depth level in the group tree.
#ifdef VPF_ALIGN
USHORT usDummy;
#endif
DWORD dwFlags ; ///< Used by KeePass internally, don't use (set to 0 for a new structure).
} PW_GROUP , * PPW_GROUP ;
由此可见,PW_GROUP 存储一下信息: (1) 分组 Id ,( 2 )图像 Id ( 3 )组名( 4 )创建日期( 5 )最后修改日期( 6 )最后访问日期( 7 )树状结构中所处的层次数( 8 )标志位。
KeePass文件的最后部分才是密码信息,其存储方式和组数据一样。也是依次存储。 PW_ENTRY 在pwstructs.h 中定义:
/// Entry structure, containing information about one entry.
typedef struct _PW_ENTRY
{
BYTE uuid [16]; ///< Unique GUID identifying this entry (not only in this database).
DWORD uGroupId ; ///< ID of the group that contains this entry.
DWORD uImageId ; ///< Index of the icon in the image list to use fo r this entry.
TCHAR * pszTitle ; ///< Title.
TCHAR * pszURL ; ///< URL.
TCHAR * ; ///< User name.
DWORD uPasswordLen ; ///< Length of the password (required for memory protection).
TCHAR * pszPassword ; ///< Password (may be encrypted, use IKpDatabase::UnlockEntryPassword to decrypt).
TCHAR * pszAdditional ; ///< Notes.
PW_TIME tCreation ; ///< Time when the entry was created.
PW_TIME tLastMod ; ///< Time when the entry was last modified.
PW_TIME tLastAccess ; ///< Time when the entry was last accessed.
PW_TIME tExpire ; ///< Time when the entry will expire.
TCHAR * pszBinaryDesc ; ///< A string describing the contents of pBinaryData.
BYTE * pBinaryData ; ///< Attachment data (of length uBinaryDataLen), may be NULL.
DWORD uBinaryDataLen ; ///< Length of the attachment data in bytes.
} PW_ENTRY , * PPW_ENTRY ;
值得一提的是,KeePass 字符串都是以 UTF-8 格式存储的。读取的时候要进行相关的转换才能使用。