KDBX 4
從 KDBX 3.1 文件格式更改為 KDBX 4棍厂。
介紹
Keepass 2.35 引入 KDBX 文件格式版本 4。新格式既有改進又有新功能超陆。以下各節(jié)概述了這些內(nèi)容牺弹。
自 KDBX 3.1 以來,內(nèi)部 XML 格式進行了一些更改(比如頭部哈希 HeaderHash 元元素已經(jīng)過時时呀;用于條目和組的新的自定義數(shù)據(jù) CustomData 元素张漂;新的設(shè)置更改 SettingChanged 元素)。包裝的二進制格式有很大的變化退唠。此外鹃锈,加密和數(shù)據(jù)身份驗證的順序也會更改。
遷移說明瞧预。 由于并非所有主要的 KeePass 實現(xiàn)都已完成對 KDBX 4 的支持屎债,因此,僅在滿足以下至少一項條件時垢油,KeePass 2.35 才以這種新格式保存數(shù)據(jù)庫盆驹。
- 未選擇 AES-KDF 作為密鑰生成方法(KDBX 3.1 僅支持 AES-KDF;任何其他的密鑰生成方法滩愁,都需要 KDBX 4躯喇,如 Argon2)。
- 插件需要在 KDBX 文件中存儲自定義頭數(shù)據(jù) custom header data。
- 插件需要在條目或組中存儲自定義數(shù)據(jù) custom data廉丽。
從 KeePass 2.44 開始倦微,選擇 ChaCha20 作為文件加密算法也將強制使用 KDBX 4 格式。
一旦所有主要的 KeePass 實現(xiàn)都支持 KDBX 4正压,KeePass 將始終以這種格式保存欣福。
Argon2 算法
從 KDBX 4 開始,可以使用 Argon2 密鑰生成方法來轉(zhuǎn)換復(fù)合主密鑰(以防止字典攻擊)焦履。
Argon2 是 “密碼哈希競賽” 的獲勝者拓劝。在 KDBX 3.1 之前,KeePass 使用 AES-KDF嘉裤,一種基于迭代高級加密標準(AES)的密鑰生成方法郑临。Argon2 相對于 AES-KDF 的主要優(yōu)勢在于具有更好的抵抗 GPU/ASIC 攻擊的能力(由于具有硬內(nèi)存功能)。
用戶現(xiàn)在可以在 AES-KDF 和 Argon2 之間進行選擇屑宠。
對于開發(fā)者
可以在 Argon2Kdf.Core.cs 中找到 Argon2 實現(xiàn)厢洞。文件 Argon2Kdf.cs 定義了參數(shù)的默認值,并實現(xiàn)了密鑰生成基礎(chǔ)結(jié)構(gòu)的方法典奉。僅支持 Argon2 的 Argon2d 變體(對 GPU/ASIC 破解攻擊的強大防御最重要犀变,而在這方面 Argon2d 優(yōu)于 Argon2i;旁通道定時攻擊基本上是無關(guān)緊要的秋柄,因為 KeePass 是本地應(yīng)用程序,而不是遠程服務(wù)器)蠢正。
KeePass 的 Argon2 實現(xiàn)支持官方規(guī)范中定義的所有參數(shù)骇笔,但是用戶只能在數(shù)據(jù)庫設(shè)置對話框中配置迭代次數(shù),內(nèi)存大小和并行度嚣崭。對于其他參數(shù)笨触,KeePass 選擇合理的默認值:每次保存數(shù)據(jù)庫時,CSPRNG 都會生成 256 位亂數(shù)鹽雹舀,標簽長度為 256 位芦劣,沒有密鑰或相關(guān)數(shù)據(jù)。支持 Argon2d 的所有版本(1.0 到 1.3)说榆。 默認情況下虚吟,KeePass 使用最新版本 1.3。
可擴展的密鑰生成
插件現(xiàn)在可以提供其他密鑰生成方法(用于轉(zhuǎn)換復(fù)合主密鑰)签财。
對于開發(fā)者
直到 KDBX 3.1串慰,AES-KDF 的回合數(shù)存儲在 ID 為 6(TransformRounds)的頭部字段中,而轉(zhuǎn)換的種子存儲在 ID 為 5(TransformSeed)的頭部字段中唱蒸。 這兩個字段現(xiàn)在已過時邦鲫。
從 KDBX 4 開始,密鑰生成方法的參數(shù)存儲在 ID 為 11(KdfParameters)的頭部字段中神汹。參數(shù)被序列化為 VariantDictionary(KDF UUID 存儲在 $UUID 中)庆捺;有關(guān) AES-KDF 和 Argon2 使用的參數(shù)的詳細信息古今,請參閱 AesKdf.cs 和 Argon2Kdf.cs。
VariantDictionary 是一個鍵值字典(鍵是一個字符串滔以,值是一個對象)捉腥,其序列化如下:
- [2 字節(jié)] 版本,為 UInt16醉者,小字節(jié)序但狭,當(dāng)前為 0x0100(1.0版)。高字節(jié)重要(即高字節(jié)太高可拒絕加載數(shù)據(jù))撬即,低字節(jié)是信息性的(即可以忽略)立磁。
- [n 個項目] n 個序列化項目(請參見下文)。
- [1 字節(jié)] 空終止符字符剥槐。
n 個序列化項目中的每一個都具有以下格式:
- [1 字節(jié)] 值類型唱歧,可以是以下之一:
- 0x04:UInt32
- 0x05:UInt64
- 0x08:Bool
- 0x0C:Int32
- 0x0D:Int64
- 0x18:String(UTF-8,不帶 BOM粒竖,不帶空終止符)
- 0x42:Byte 數(shù)組
- [4 字節(jié)] 鍵名長度 k颅崩,以字節(jié)為單位,Int32蕊苗,小字節(jié)序沿后。
- [k 字節(jié)] 鍵名(字符串,UTF-8朽砰,不帶 BOM尖滚,不帶空終止符)。
- [4 字節(jié)] 值長度 v瞧柔,以字節(jié)為單位漆弄,Int32,小字節(jié)序造锅。
- [v 字節(jié)] 值撼唾,整數(shù)以小字節(jié)序存儲,Bool 類型為一個字節(jié)(false = 0哥蔚,true = 1)倒谷。
在 KDBX 3.1 之前,頭部字段的長度為 2 個字節(jié)肺素。從 KDBX 4 開始恨锚,長度為 4 個字節(jié)。此更改使其他密鑰生成方法的實現(xiàn)成為可能倍靡,其參數(shù)可能需要超過 64KB 的空間猴伶。此外,插件提供的頭部數(shù)據(jù)可以大于 64KB。
改進的頭部驗證
在 KDBX 4 中他挎,頭數(shù)據(jù)使用 HMAC-SHA-256 進行驗證筝尾。
直到 KDBX 3.1 為止,頭部數(shù)據(jù)都是使用存儲在數(shù)據(jù)庫文件加密部分中的 SHA-256 哈希進行驗證办桨。KDBX 4 中使用的 HMAC-SHA-256 方法具有各種優(yōu)點筹淫。優(yōu)點之一就是 KeePass 可以在嘗試解密其余部分之前驗證頭部,從而可以防止對不正確數(shù)據(jù)解密的嘗試呢撞。
對于開發(fā)者
在 KDBX 4 中损姜,XML 部分中的 HeaderHash 元素現(xiàn)在已過時,不再存儲殊霞。必須使用 HMAC-SHA-256 進行新的頭部驗證摧阅。
直接在頭部之后,存儲頭部的(未加密的)SHA-256 哈希(這允許在不知道主密鑰的情況下檢測意外損壞)绷蹲。在哈希之后棒卷,直接存儲頭部的 HMAC-SHA-256 值。
改進的數(shù)據(jù)驗證
在KDBX 4中祝钢,通過加密文本的 HMAC-SHA-256 對數(shù)據(jù)塊進行驗證(先加密后 MAC 方案)比规。
在KDBX 3.1之前的版本中,通過解密該數(shù)據(jù)塊的 SHA-256 哈希(類似先 MAC 后加密)來驗證該數(shù)據(jù)塊的方案拦英。盡管通常認為先加密后 MAC 方案(KDBX 4)比先 MAC 后加密方案(KDBX 3.1)更安全蜒什,但我們不認為 KDBX 3.1 文件是不安全的(因為特定情況下的 KDBX 文件經(jīng)過驗證的數(shù)據(jù)塊通常很大,并且使用了 CBC 模式下的塊密碼)疤估。無論如何吃谣,我們認為最好切換到通常被認為是最安全的方案(即使實際上在 KDBX 沒啥區(qū)別)。此外做裙,先加密后 MAC 具有實際優(yōu)勢。一個優(yōu)點就是 KeePass 可以在嘗試解密數(shù)據(jù)塊之前驗證它的真實性肃晚。這樣可以避免塊密碼填充異常(對于 KDBX 3.1锚贱,KeePass 會自動將其轉(zhuǎn)換為文件損壞異常;盡管這樣做也行关串,但在遇到此類異常之前先檢測不正確的數(shù)據(jù)會更優(yōu)雅拧廊。
對于開發(fā)者
對于使用 HMAC-SHA-256 認證的加載/保存的數(shù)據(jù)塊的流,請參閱新文件 HmacBlockStream.cs晋修。該流類似于 KDBX 3.1 所使用的 HashedBlockStream吧碾,但是使用 HMAC 而不只是哈希。此外墓卦,在 KDBX 4 中倦春,HMAC 是在密文上計算的,而在 KDBX 3.1 中,是計算明文哈希(然后與明文一起加密)睁本。
由 HmacBlockStream 生成的單個塊如下所示:
- [32 字節(jié)] HMAC-SHA-256 值(請參見下文)尿庐。
- [4 字節(jié)] 塊大小 n(以字節(jié)為單位,最小 0呢堰,最大
抄瑟,0 表示最后一個塊,小字節(jié)序)枉疼。
- [n 字節(jié)] 塊數(shù)據(jù) C(密文)皮假。
HMAC 通過 i || n || C 計算(其中 64 位的序列數(shù) i 和 32 位的塊長度 n 使用小字節(jié)序;i 是隱式的不需要存儲)骂维。HMAC 每塊數(shù)據(jù)的密鑰都不同惹资;計算方式為 , 其中
是從用戶復(fù)合主密鑰和保存在 KDBX 頭中的主種子生成的 512 位密鑰席舍。
在頭部及其 HMAC 之后即是機密數(shù)據(jù)布轿,按以上方式分為多塊。KeePass 2.35 寫入 KDBX 文件時使用 来颤,即每塊 1 MB汰扭。
可擴展的頭部
KDBX 4 文件的頭部可由插件擴展。
對于開發(fā)者
插件提供的頭部數(shù)據(jù)存儲在 ID 為 12 的頭部字段中福铅。其值為序列化的 VariantDictionary萝毛。
對于插件開發(fā)者
注意附加的頭部數(shù)據(jù)不加密,僅存在于 KDBX 文件中(無法用 XML 導(dǎo)出)滑黔。 除非確實需要未解密的附加頭部數(shù)據(jù)笆包,否則強烈建議插件將附加數(shù)據(jù)存儲在 PwDatabase 的 CustomData 字段中。CustomData 序列化在 XML 中略荡,加密庵佣,并支持 XML 導(dǎo)出。
ChaCha20 算法
添加了對 ChaCha20 加密算法的支持(如 RFC 7539 所述汛兜,具有 256 位密鑰和 96 位隨機數(shù))巴粪。
ChaCha20 是 Salsa20 算法(包含在 eSTREAM 產(chǎn)品中)的衍生算法。
可以在數(shù)據(jù)庫設(shè)置對話框中將其設(shè)為 KDBX 文件的加密算法粥谬。
此外肛根,ChaCha20 取代 Salsa20 作為默認選項,用于生成 KDBX 4 文件內(nèi)部的隨機流漏策。
對于開發(fā)者
在 KDBX 3.1 之前派哲,存儲在 KDBX 頭部(ID 為 7 的字段 EncryptionIV)中的加密 IV 始終長 16 個字節(jié)(128 位)。從 KDBX 4 開始掺喻,從密碼實現(xiàn)中檢索加密 IV 長度芭届,并且 KDBX 頭部字段存儲了恰好此長度的加密 IV储矩。對于 ChaCha20,即 12 個字節(jié)(96 位)喉脖。
對于插件開發(fā)人員
加密算法插件開發(fā)人員椰苟,請注意以下內(nèi)容。默認的 IV 長度繼續(xù)為 16 個字節(jié)(128 位)树叽。如果您的加密引擎實現(xiàn)了該 ICipherEngine2 接口舆蝴,則可以通過 IVLength 屬性指定 IV 長度 。
可擴展的條目和組
插件現(xiàn)在可以將自定義數(shù)據(jù)存儲在條目和組中题诵。
到目前洁仗,插件已將自定義數(shù)據(jù)存儲在條目的字符串字段中,從設(shè)計的角度來看并不理想性锭。從 KDBX 4 開始赠潦,每個條目和每個組都有一個鍵值字典,插件可以在其中存儲自定義數(shù)據(jù)草冈。
對于開發(fā)人員
PwEntry 和 PwGroup 現(xiàn)在有一個 CustomData 屬性她奥。此屬性與 PwDatabase 的 CustomData 屬性類似,序列化(相同的 XML 結(jié)構(gòu))怎棱。
內(nèi)部頭
KDBX 4 文件具有二進制內(nèi)部頭哩俭。該頭文件位于 XML 之前甲雅;壓縮(若打開壓縮選項)并加密恬总。內(nèi)部頭之后為 XML 部分(相同的壓縮和加密流)。
內(nèi)部頭可以存儲條目附件冗懦,這是引入內(nèi)部頭的主要原因谬运。直到 KDBX 3.1隙赁,條目附件都是用 Base64 編碼,并存儲在 XML 中梆暖。與此相比伞访,KDBX 4 內(nèi)部頭的使用可以減小數(shù)據(jù)庫文件大小并提高加載/保存性能。
對于開發(fā)者
內(nèi)部頭的結(jié)構(gòu)類似于外部頭轰驳。由以下形式的任意多個項目組成:
- [1 字節(jié)] 項目類型咐扭。
- [4 字節(jié)] 數(shù)據(jù)長度 n(Int32,小字節(jié)序)滑废。
- [n 字節(jié)] 數(shù)據(jù) D。
支持的項目類型:
- 0x00:頭部結(jié)束標識袜爪。
- 0x01:內(nèi)部隨機流 ID(取代 KDBX 3.1 文件外部頭中的內(nèi)部隨機流 ID)蠕趁。
- 0x02:內(nèi)部隨機流密鑰(取代 KDBX 3.1 文件外部頭中的內(nèi)部隨機流密鑰)。
- 0x03:二進制文件(條目附件)辛馆。
俺陋,F 單字節(jié)豁延,存儲附件數(shù)據(jù)標識,M 為條目附件實際二進制數(shù)據(jù)腊状。F 支持的標識:
- 0x01:用戶已為此二進制文件打開進程內(nèi)存保護诱咏。
內(nèi)部頭必須以 0x00 類型的項目結(jié)束(且 n = 0)。