/** * Stores internally the given data of a KeePass database file with the * index $dbid, to make it possible to find it later from that same index. * This methods basically packs all together in an array $hashname (the * filename of the actual KeePass database file), $keys (the description of * the master key: what kinds of keys compose it, in which order, and for * the key from files, the filenames of these files), $entries (the list of * entries of the database, without the passwords ; they are written only if * $writable is true) and $writeable, then serialize it and encrypts it with * the password $internalpwd, and stores the result in a kphpdb file. * If the index $dbid already exists, the corresponding data will be * overriden. * @param string $dbid The ID to use. * @param string $internalpwd The internal password to encrypt the data in * the KeePassPHP internal database with. * @param string $hashname The filename of the KeePass database file. * @param array $keys The type of keys composing the master key, with the * filenames in the case of key files. * @param array $entries The entries of the database to store. * @param boolean $writeable Whether the entries can be written or not (if * not, they will be loaded from the KeePass database file each time). * @return string|null Returns null if something went wrong, and the name * of the kphpdb file created otherwise. */ public static function addInternal($dbid, $internalpwd, $hashname, array $keys, array $entries, $writeable) { $db = array(self::IDX_DBTYPE => self::DBTYPE_KDBX, self::IDX_HASHNAME => $hashname, self::IDX_KEYS => $keys, self::IDX_ENTRIES => $writeable ? $entries : null, self::IDX_WRITEABLE => $writeable); $plaindb = serialize($db); $key = hash('SHA256', $internalpwd, true); $cipher = new CipherMcrypt(MCRYPT_RIJNDAEL_256, 'cfb', $key, null, CipherMcrypt::PK7_PADDING); $cipher->load(); $iv = $cipher->getIV(); if (strlen($iv) != self::IV_SIZE) { self::raiseError("Unexpected size of IV : " . strlen($iv)); $cipher->unload(); return null; } $bindb = $iv . $cipher->encrypt($plaindb); $cipher->unload(); return self::$dbmanager->addWithKey($dbid, $bindb, self::EXT_KPHPDB, true, true); }
/** * Returns as a binary string the final AES key used for decrypting * the database file, computed from the seeds and the master composite key. * @return string */ private function transformKey() { $seed = $this->header->transformSeed; $keyHash = $this->key->getHash(); /// does not yet support the case rounds >> 2**31 $rounds = $this->header->rounds->asInt(); $AESEncryptor = new CipherMcrypt(CipherMcrypt::AES128, 'ecb', $seed); $AESEncryptor->load(); for ($i = 0; $i < $rounds; $i++) { $keyHash = $AESEncryptor->encrypt($keyHash); } $AESEncryptor->unload(); $finalKey = HashHouse::hash($keyHash); $aesKey = HashHouse::hash($this->header->masterSeed . $finalKey); return $aesKey; }