PHP Classes

File: tests/KDF/HKDFTest.php

Recommend this page to a friend!
  Classes of Scott Arciszewski   HPKE PHP   tests/KDF/HKDFTest.php   Download  
File: tests/KDF/HKDFTest.php
Role: Class source
Content type: text/plain
Description: Class source
Class: HPKE PHP
Encrypt and decrypt data using hybrid public keys
Author: By
Last change:
Date: 8 days ago
Size: 14,638 bytes
 

Contents

Class file image Download
<?php declare(strict_types=1); namespace ParagonIE\HPKE\Tests\KDF; use ParagonIE\HPKE\AEAD\{ AES128GCM, AES256GCM, ChaCha20Poly1305 }; use ParagonIE\HPKE\Hash; use ParagonIE\HPKE\KDF\HKDF; use ParagonIE\HPKE\KEM\{ DHKEM\Curve, DiffieHellmanKEM }; use PHPUnit\Framework\Attributes\{ CoversClass, DataProvider }; use PHPUnit\Framework\TestCase; use SodiumException; #[CoversClass(HKDF::class)] class HKDFTest extends TestCase { /** * Omits the SHA-1 test vectors */ public static function rfc5869TestVectors(): array { $sha256 = new HKDF(Hash::Sha256); return [ 'Test Case 1' => [ $sha256, '077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5', '3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', 'f0f1f2f3f4f5f6f7f8f9', 42, '000102030405060708090a0b0c', ], 'Test Case 2' => [ $sha256, '06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244', 'b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87', '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f', 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff', 82, '606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf' ], 'Test Case 3' => [ $sha256, '19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04', '8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', '', 42, null ] ]; } public static function rfc9180(): array { $sha256 = new HKDF(Hash::Sha256); $sha512 = new HKDF(Hash::Sha512); // KEMs $kem_x25519_id = (new DiffieHellmanKEM(Curve::X25519, $sha256))->getKemId(); $kem_p256_id = (new DiffieHellmanKEM(Curve::NistP256, $sha256))->getKemId(); $kem_p521_id = (new DiffieHellmanKEM(Curve::NistP521, $sha512))->getKemId(); // KDFs $kdf_sha256_id = $sha256->getKdfId(); $kdf_sha512_id = $sha512->getKdfId(); // AEADs $aes128 = (new AES128GCM()); $aes256 = (new AES256GCM()); $chapoly = (new ChaCha20Poly1305()); // Return the test cases: return [ 'DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM' => [ $sha256, "HPKE" . $kem_x25519_id . $kdf_sha256_id . $aes128->getAeadId(), [ 'nk' => $aes128->keyLength(), 'mode' => '00', 'info' => '4f6465206f6e2061204772656369616e2055726e', 'shared_secret' => 'fe0e18c9f024ce43799ae393c7e8fe8fce9d218875e8227b0187c04e7d2ea1fc', 'key_schedule_context' => '00725611c9d98c07c03f60095cd32d400d8347d45ed67097bbad50fc56da742d07cb6cffde367bb0565ba28bb02c90744a20f5ef37f30523526106f637abb05449', 'secret' => '12fff91991e93b48de37e7daddb52981084bd8aa64289c3788471d9a9712f397', 'key' => '4531685d41d65f03dc48f6b8302c05b0', 'base_nonce' => '56d890e5accaaf011cff4b7d', 'exporter_secret' => '45ff1c2e220db587171952c0592d5f5ebe103f1561a2614e38f2ffd47e99e3f8', ] ], 'DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305' => [ $sha256, "HPKE" . $kem_x25519_id . $kdf_sha256_id . $chapoly->getAeadId(), [ 'nk' => $chapoly->keyLength(), 'mode' => '00', 'info' => '4f6465206f6e2061204772656369616e2055726e', 'shared_secret' => '0bbe78490412b4bbea4812666f7916932b828bba79942424abb65244930d69a7', 'key_schedule_context' => '00431df6cd95e11ff49d7013563baf7f11588c75a6611ee2a4404a49306ae4cfc5b69c5718a60cc5876c358d3f7fc31ddb598503f67be58ea1e798c0bb19eb9796', 'secret' => '5b9cd775e64b437a2335cf499361b2e0d5e444d5cb41a8a53336d8fe402282c6', 'key' => 'ad2744de8e17f4ebba575b3f5f5a8fa1f69c2a07f6e7500bc60ca6e3e3ec1c91', 'base_nonce' => '5c4d98150661b848853b547f', 'exporter_secret' => 'a3b010d4994890e2c6968a36f64470d3c824c8f5029942feb11e7a74b2921922', ] ], 'DHKEM(P-256, HKDF-SHA256), HKDF-SHA256, AES-128-GCM' => [ $sha256, "HPKE" . $kem_p256_id . $kdf_sha256_id . $aes128->getAeadId(), [ 'nk' => $aes128->keyLength(), 'mode' => '00', 'info' => '4f6465206f6e2061204772656369616e2055726e', 'shared_secret' => 'c0d26aeab536609a572b07695d933b589dcf363ff9d93c93adea537aeabb8cb8', 'key_schedule_context' => '00b88d4e6d91759e65e87c470e8b9141113e9ad5f0c8ceefc1e088c82e6980500798e486f9c9c09c9b5c753ac72d6005de254c607d1b534ed11d493ae1c1d9ac85', 'secret' => '2eb7b6bf138f6b5aff857414a058a3f1750054a9ba1f72c2cf0684a6f20b10e1', 'key' => '868c066ef58aae6dc589b6cfdd18f97e', 'base_nonce' => '4e0bc5018beba4bf004cca59', 'exporter_secret' => '14ad94af484a7ad3ef40e9f3be99ecc6fa9036df9d4920548424df127ee0d99f', ] ], 'DHKEM(P-256, HKDF-SHA256), HKDF-SHA512, AES-128-GCM' => [ $sha512, "HPKE" . $kem_p256_id . $kdf_sha512_id . $aes128->getAeadId(), [ 'nk' => $aes128->keyLength(), 'mode' => '00', 'info' => '4f6465206f6e2061204772656369616e2055726e', 'shared_secret' => '02f584736390fc93f5b4ad039826a3fa08e9911bd1215a3db8e8791ba533cafd', 'key_schedule_context' => '005b8a3617af7789ee716e7911c7e77f84cdc4cc46e60fb7e19e4059f9aeadc00585e26874d1ddde76e551a7679cd47168c466f6e1f705cc9374c192778a34fcd5ca221d77e229a9d11b654de7942d685069c633b2362ce3b3d8ea4891c9a2a87a4eb7cdb289ba5e2ecbf8cd2c8498bb4a383dc021454d70d46fcbbad1252ef4f9', 'secret' => '0c7acdab61693f936c4c1256c78e7be30eebfe466812f9cc49f0b58dc970328dfc03ea359be0250a471b1635a193d2dfa8cb23c90aa2e25025b892a725353eeb', 'key' => '090ca96e5f8aa02b69fac360da50ddf9', 'base_nonce' => '9c995e621bf9a20c5ca45546', 'exporter_secret' => '4a7abb2ac43e6553f129b2c5750a7e82d149a76ed56dc342d7bca61e26d494f4855dff0d0165f27ce57756f7f16baca006539bb8e4518987ba610480ac03efa8', ] ], 'DHKEM(P-256, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305' => [ $sha256, "HPKE" . $kem_p256_id . $kdf_sha256_id . $chapoly->getAeadId(), [ 'nk' => $chapoly->keyLength(), 'mode' => '00', 'info' => '4f6465206f6e2061204772656369616e2055726e', 'shared_secret' => '806520f82ef0b03c823b7fc524b6b55a088f566b9751b89551c170f4113bd850', 'key_schedule_context' => '00b738cd703db7b4106e93b4621e9a19c89c838e55964240e5d3f331aaf8b0d58b2e986ea1c671b61cf45eec134dac0bae58ec6f63e790b1400b47c33038b0269c', 'secret' => 'fe891101629aa355aad68eff3cc5170d057eca0c7573f6575e91f9783e1d4506', 'key' => 'a8f45490a92a3b04d1dbf6cf2c3939ad8bfc9bfcb97c04bffe116730c9dfe3fc', 'base_nonce' => '726b4390ed2209809f58c693', 'exporter_secret' => '4f9bd9b3a8db7d7c3a5b9d44fdc1f6e37d5d77689ade5ec44a7242016e6aa205', ] ], 'DHKEM(P-521, HKDF-SHA512), HKDF-SHA512, AES-256-GCM' => [ $sha512, "HPKE" . $kem_p521_id . $kdf_sha512_id . $aes256->getAeadId(), [ 'nk' => $aes256->keyLength(), 'mode' => '00', 'info' => '4f6465206f6e2061204772656369616e2055726e', 'shared_secret' => '776ab421302f6eff7d7cb5cb1adaea0cd50872c71c2d63c30c4f1d5e43653336fef33b103c67e7a98add2d3b66e2fda95b5b2a667aa9dac7e59cc1d46d30e818', 'key_schedule_context' => '0083a27c5b2358ab4dae1b2f5d8f57f10ccccc822a473326f543f239a70aee46347324e84e02d7651a10d08fb3dda739d22d50c53fbfa8122baacd0f9ae5913072ef45baa1f3a4b169e141feb957e48d03f28c837d8904c3d6775308c3d3faa75dd64adfa44e1a1141edf9349959b8f8e5291cbdc56f62b0ed6527d692e85b09a4', 'secret' => '49fd9f53b0f93732555b2054edfdc0e3101000d75df714b98ce5aa295a37f1b18dfa86a1c37286d805d3ea09a20b72f93c21e83955a1f01eb7c5eead563d21e7', 'key' => '751e346ce8f0ddb2305c8a2a85c70d5cf559c53093656be636b9406d4d7d1b70', 'base_nonce' => '55ff7a7d739c69f44b25447b', 'exporter_secret' => 'e4ff9dfbc732a2b9c75823763c5ccc954a2c0648fc6de80a58581252d0ee3215388a4455e69086b50b87eb28c169a52f42e71de4ca61c920e7bd24c95cc3f992', ] ], ]; } /** * @throws SodiumException */ #[DataProvider('rfc5869TestVectors')] public function testRfc5869( HKDF $kdf, string $prk_hex, string $okm_hex, string $ikm_hex, string $info_hex, int $length, ?string $salt_hex = null ): void { $ikm = sodium_hex2bin($ikm_hex); $info = sodium_hex2bin($info_hex); $salt = is_null($salt_hex) ? '' : sodium_hex2bin($salt_hex); // Test the combined mode $output = $kdf->deriveBytes($ikm, $info, $salt, $length); $this->assertSame($okm_hex, sodium_bin2hex($output)); // Now let's test extract/expand separately $prk = $kdf->extract($ikm, $salt); $this->assertSame($prk_hex, sodium_bin2hex($prk), 'HKDF-extract'); $result = $kdf->expand($prk, $info, $length); $this->assertSame($okm_hex, sodium_bin2hex($result), 'HKDF-expand'); } /** * @throws SodiumException */ #[DataProvider('rfc9180')] public function testRfc9180( HKDF $kdf, string $suiteId, array $testVectorsInHex = [] ): void { // We aren't testing it at this level. $info = sodium_hex2bin($testVectorsInHex['info']); $mode = sodium_hex2bin($testVectorsInHex['mode']); $info_hash = $kdf->labeledExtract( suiteId: $suiteId, ikm: $info, label: 'info_hash' ); $psk_id_hash = $kdf->labeledExtract( suiteId: $suiteId, ikm: '', label: 'psk_id_hash' ); $this->assertSame( $testVectorsInHex['key_schedule_context'], sodium_bin2hex($mode . $psk_id_hash . $info_hash), 'info hashing' ); $shared_secret = sodium_hex2bin($testVectorsInHex['shared_secret']); $actual_secret = $kdf->labeledExtract( suiteId: $suiteId, ikm: '', label: 'secret', salt: $shared_secret ); $this->assertSame( $testVectorsInHex['secret'], sodium_bin2hex($actual_secret), 'secret' ); $nk = $testVectorsInHex['nk']; $secret = sodium_hex2bin($testVectorsInHex['secret']); $key_schedule_context = sodium_hex2bin($testVectorsInHex['key_schedule_context']); $actual_key = $kdf->labeledExpand( suiteId: $suiteId, prk: $secret, label: 'key', info: $key_schedule_context, length: $nk ); $this->assertSame( $testVectorsInHex['key'], sodium_bin2hex($actual_key), 'key' ); $actual_base_nonce = $kdf->labeledExpand( suiteId: $suiteId, prk: $secret, label: 'base_nonce', info: $key_schedule_context, length: 12 // This is pretty universal for all AEADs in scope ); $this->assertSame( $testVectorsInHex['base_nonce'], sodium_bin2hex($actual_base_nonce), 'base_nonce' ); $actual_exp = $kdf->labeledExpand( suiteId: $suiteId, prk: $secret, label: 'exp', info: $key_schedule_context, length: $kdf->getHashLength() ); $this->assertSame( $testVectorsInHex['exporter_secret'], sodium_bin2hex($actual_exp), 'exporter_secret' ); } }