keepassphp/lib/kdbxfile.php
private static function transformKey(iKey $key, KdbxHeader $header)
	{
		$keyHash = $key->getHash();
		$cipher = Cipher::Create('aes-256-ecb', $header->transformSeed,
			"", Cipher::PADDING_NONE);
		if($cipher == null)
			return null;
		// We have to do $rounds encryptions, where $rounds is a 64 bit
		// unsigned integer. Since PHP does not handle 64 bit integers in a
		// clear way, nor 32 bit unsigned integers, it is safer to take
		// $rounds as an array of 4 short (16 bit) unsigned integers.
		// Remember that $rounds is encoded in little-endian.
		$rounds = array_values(unpack("v4", $header->rounds));
		// To go even faster, represent $rounds in base 2**30 by only three
		// signed integers, that PHP should handle correctly. $o, $t and $h
		// will respectively be ones, tens and hundrers. $o and $t each take 30
		// bits, $h takes the remaining 4.
		$o = $rounds[0] | (($rounds[1] & 0x3fff) << 16);
		$t = (($rounds[1] & 0xc000) >> 14) | ($rounds[2] << 2) |
			(($rounds[3] & 0x0fff) << 18);
		$h = ($rounds[3] & 0xf000) >> 12;
		// So virtually, the number of rounds is $o + ($t << 30) + ($h << 60).
		$loop = false;
		do
		{
			// Let's do a direct, very fast loop on the ones $o
			if($o > 0)
				$keyHash = $cipher->encryptManyTimes($keyHash, $o);
			// whether there is still some rounds to perform
			$loop = false;
			// then, remove 1 from the number of rounds (that's just a
			// substraction in base 2**30 of a 3-digit number), knowing that
			// $o equals 0.
			if($t > 0)
			{
				$t--;
				// We set $o to (2**30 - 1) + 1 = 2**30 because we still
				// have to do the encryption round that we're currently
				// substracting. So we don't really do a substraction, we
				// just write the number differently. That's also why we
				// chose to represent $rounds in base 2**30 rather than 2**31.
				$o = 0x40000000;
				$loop = true;
			}
			else if($h > 0)
			{
				$h--;
				$t = 0x3fffffff;
				// same as above
				$o = 0x40000000;
				$loop = true;
			}
		} while($loop);

		$finalKey = hash(self::HASH, $keyHash, true);
		return hash(self::HASH, $header->masterSeed . $finalKey, true);
	}
private static function transformKey(iKey $key, KdbxHeader $header)
	{
		$keyHash = $key->getHash();
		$cipher = Cipher::Create('aes-256-ecb', $header->transformSeed,
			"", Cipher::PADDING_NONE);
		if($cipher == null)
			return null;
		// We have to do $rounds encryptions, where $rounds is a 64 bit
		// unsigned integer. Since PHP does not handle 64 bit integers in a
		// clear way, nor 32 bit unsigned integers, it is safer to take
		// $rounds as an array of 4 short (16 bit) unsigned integers.
		// Remember that $rounds is encoded in little-endian.
		$rounds = array_values(unpack("v4", $header->rounds));
		// To go even faster, represent $rounds in base 2**30 by only three
		// signed integers, that PHP should handle correctly. $o, $t and $h
		// will respectively be ones, tens and hundrers. $o and $t each take 30
		// bits, $h takes the remaining 4.
		$o = $rounds[0] | (($rounds[1] & 0x3fff) << 16);
		$t = (($rounds[1] & 0xc000) >> 14) | ($rounds[2] << 2) |
			(($rounds[3] & 0x0fff) << 18);
		$h = ($rounds[3] & 0xf000) >> 12;
		// So virtually, the number of rounds is $o + ($t << 30) + ($h << 60).
		$loop = false;
		do
		{
			// Let's do a direct, very fast loop on the ones $o
			if($o > 0)
				$keyHash = $cipher->encryptManyTimes($keyHash, $o);
			// whether there is still some rounds to perform
			$loop = false;
			// then, remove 1 from the number of rounds (that's just a
			// substraction in base 2**30 of a 3-digit number), knowing that
			// $o equals 0.
			if($t > 0)
			{
				$t--;
				// We set $o to (2**30 - 1) + 1 = 2**30 because we still
				// have to do the encryption round that we're currently
				// substracting. So we don't really do a substraction, we
				// just write the number differently. That's also why we
				// chose to represent $rounds in base 2**30 rather than 2**31.
				$o = 0x40000000;
				$loop = true;
			}
			else if($h > 0)
			{
				$h--;
				$t = 0x3fffffff;
				// same as above
				$o = 0x40000000;
				$loop = true;
			}
		} while($loop);

		$finalKey = hash(self::HASH, $keyHash, true);
		return hash(self::HASH, $header->masterSeed . $finalKey, true);
	}
private static function transformKey ( iKey $ key , KdbxHeader $ header ) { $ keyHash = $ key -> getHash ( ) ; $ cipher = Cipher :: Create ( 'aes-256-ecb' , $ header -> transformSeed , "" , Cipher :: PADDING_NONE ) ; if ( $ cipher == null ) return null ; // We have to do $rounds encryptions, where $rounds is a 64 bit // unsigned integer. Since PHP does not handle 64 bit integers in a // clear way, nor 32 bit unsigned integers, it is safer to take // $rounds as an array of 4 short (16 bit) unsigned integers. // Remember that $rounds is encoded in little-endian. $ rounds = array_values ( unpack ( "v4" , $ header -> rounds ) ) ; // To go even faster, represent $rounds in base 2**30 by only three // signed integers, that PHP should handle correctly. $o, $t and $h // will respectively be ones, tens and hundrers. $o and $t each take 30 // bits, $h takes the remaining 4. $ o = $ rounds [ 0 ] | ( ( $ rounds [ 1 ] & 0x3fff ) << 16 ) ; $ t = ( ( $ rounds [ 1 ] & 0xc000 ) >> 14 ) | ( $ rounds [ 2 ] << 2 ) | ( ( $ rounds [ 3 ] & 0x0fff ) << 18 ) ; $ h = ( $ rounds [ 3 ] & 0xf000 ) >> 12 ; // So virtually, the number of rounds is $o + ($t << 30) + ($h << 60). $ loop = false ; do { // Let's do a direct, very fast loop on the ones $o if ( $ o > 0 ) $ keyHash = $ cipher -> encryptManyTimes ( $ keyHash , $ o ) ; // whether there is still some rounds to perform $ loop = false ; // then, remove 1 from the number of rounds (that's just a // substraction in base 2**30 of a 3-digit number), knowing that // $o equals 0. if ( $ t > 0 ) { $ t -- ; // We set $o to (2**30 - 1) + 1 = 2**30 because we still // have to do the encryption round that we're currently // substracting. So we don't really do a substraction, we // just write the number differently. That's also why we // chose to represent $rounds in base 2**30 rather than 2**31. $ o = 0x40000000 ; $ loop = true ; } else if ( $ h > 0 ) { $ h -- ; $ t = 0x3fffffff ; // same as above $ o = 0x40000000 ; $ loop = true ; } } while ( $ loop ) ; $ finalKey = hash ( self :: HASH , $ keyHash , true ) ; return hash ( self :: HASH , $ header -> masterSeed . $ finalKey , true ) ; }
Computes the AES encryption key of a Kdbx file from its keys and header.
@param $key The encryption key.
@param $header The Kdbx file header.
@return A 32-byte-long string that can be used as an AES key, or null
if no suitable cryptography extension is laoded.
Computes the AES encryption key of a Kdbx file from its keys and header .