diff --git a/README.md b/README.md index 88e76292..60aa447f 100644 --- a/README.md +++ b/README.md @@ -266,6 +266,10 @@ insightful technical information you may find helpful. * `crypto_sign()` * `crypto_sign_open()` * PECL Libsodium Features + * `crypto_aead_aegis128l_encrypt()` + * `crypto_aead_aegis128l_decrypt()` + * `crypto_aead_aegis256_encrypt()` + * `crypto_aead_aegis256_decrypt()` * `crypto_aead_aes256gcm_encrypt()` * `crypto_aead_aes256gcm_decrypt()` * `crypto_aead_chacha20poly1305_encrypt()` @@ -343,13 +347,13 @@ insightful technical information you may find helpful. ### Features Excluded from this Polyfill -* `\Sodium\memzero()` - Although we expose this API endpoint, we can't reliably +* `sodium_memzero()` - Although we expose this API endpoint, we can't reliably zero buffers from PHP. If you have the PHP extension installed, sodium_compat will use the native implementation to zero out the string provided. Otherwise it will throw a `SodiumException`. -* `\Sodium\crypto_pwhash()` - It's not feasible to polyfill scrypt or Argon2 +* `sodium_crypto_pwhash()` - It's not feasible to polyfill scrypt or Argon2 into PHP and get reasonable performance. Users would feel motivated to select parameters that downgrade security to avoid denial of service (DoS) attacks. @@ -361,6 +365,8 @@ insightful technical information you may find helpful. To detect support for Argon2i at runtime, use `ParagonIE_Sodium_Compat::crypto_pwhash_is_available()`, which returns a boolean value (`TRUE` or `FALSE`). +* Libsodium's HKDF API (`crypto_kdf_hkdf_*()`) is not included because PHP has + its own [HMAC features](https://php.met/hash_hmac) amd it was not deemed necessary. ### PHPCompatibility Ruleset diff --git a/src/Core/AEGIS/State128L.php b/src/Core/AEGIS/State128L.php index 0bbf99d2..9decd2b4 100644 --- a/src/Core/AEGIS/State128L.php +++ b/src/Core/AEGIS/State128L.php @@ -1,4 +1,9 @@ state[7], - $this->state[0] ^ $m0 + list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound( + $this->state[7], $this->state[0] ^ $m0, + $this->state[0], $this->state[1] + ); + + list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound( + $this->state[1], $this->state[2], + $this->state[2], $this->state[3] + ); + + list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound( + $this->state[3], $this->state[4] ^ $m1, + $this->state[4], $this->state[5] ); - $s_1 = ParagonIE_Sodium_Core_AES::aesRound($this->state[0], $this->state[1]); - $s_2 = ParagonIE_Sodium_Core_AES::aesRound($this->state[1], $this->state[2]); - $s_3 = ParagonIE_Sodium_Core_AES::aesRound($this->state[2], $this->state[3]); - $s_4 = ParagonIE_Sodium_Core_AES::aesRound( - $this->state[3], - $this->state[4] ^ $m1 + list($s_6, $s_7) = ParagonIE_Sodium_Core_AES::doubleRound( + $this->state[5], $this->state[6], + $this->state[6], $this->state[7] ); - $s_5 = ParagonIE_Sodium_Core_AES::aesRound($this->state[4], $this->state[5]); - $s_6 = ParagonIE_Sodium_Core_AES::aesRound($this->state[5], $this->state[6]); - $s_7 = ParagonIE_Sodium_Core_AES::aesRound($this->state[6], $this->state[7]); /* S0 = S'0 diff --git a/src/Core/AEGIS/State256.php b/src/Core/AEGIS/State256.php index 7c11cf73..6f88b828 100644 --- a/src/Core/AEGIS/State256.php +++ b/src/Core/AEGIS/State256.php @@ -1,5 +1,9 @@ state[5], - $this->state[0] ^ $m + list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound( + $this->state[5],$this->state[0] ^ $m, + $this->state[0], $this->state[1] + ); + + list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound( + $this->state[1], $this->state[2], + $this->state[2], $this->state[3] + ); + list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound( + $this->state[3], $this->state[4], + $this->state[4], $this->state[5] ); - $s_1 = ParagonIE_Sodium_Core_AES::aesRound($this->state[0], $this->state[1]); - $s_2 = ParagonIE_Sodium_Core_AES::aesRound($this->state[1], $this->state[2]); - $s_3 = ParagonIE_Sodium_Core_AES::aesRound($this->state[2], $this->state[3]); - $s_4 = ParagonIE_Sodium_Core_AES::aesRound($this->state[3], $this->state[4]); - $s_5 = ParagonIE_Sodium_Core_AES::aesRound($this->state[4], $this->state[5]); /* S0 = S'0 diff --git a/src/Core/AES.php b/src/Core/AES.php index a7b75499..d86cff1a 100644 --- a/src/Core/AES.php +++ b/src/Core/AES.php @@ -1,5 +1,9 @@ orthogonalize(); + self::sbox($q); + $q->shiftRows(); + $q->mixColumns(); + $q->orthogonalize(); + // add round key without key schedule: + for ($i = 0; $i < 8; ++$i) { + $q[$i] ^= $rk[$i]; + } + return array( + self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]), + self::store32_le($q[1]) . self::store32_le($q[3]) . self::store32_le($q[5]) . self::store32_le($q[7]), + ); + } + /** * @param ParagonIE_Sodium_Core_AES_Expanded $skey * @param ParagonIE_Sodium_Core_AES_Block $q diff --git a/src/Core/AES/Expanded.php b/src/Core/AES/Expanded.php index e8b84924..84a6a476 100644 --- a/src/Core/AES/Expanded.php +++ b/src/Core/AES/Expanded.php @@ -1,5 +1,9 @@ assertSame( + '7a7b4e5638782546a8c0477a3b813f437a7b4e5638782546a8c0477a3b813f43', + ParagonIE_Sodium_Core_Util::bin2hex( + implode('', ParagonIE_Sodium_Core_AES::doubleRound($in, $rk, $in, $rk)) + ) + ); + + // Let's randomize this to test equivalence. + $in0 = random_bytes(16); + $in1 = random_bytes(16); + $rk0 = random_bytes(16); + $rk1 = random_bytes(16); + + $c0 = ParagonIE_Sodium_Core_AES::aesRound($in0, $rk0); + $c1 = ParagonIE_Sodium_Core_AES::aesRound($in1, $rk1); + list($c2, $c3) = ParagonIE_Sodium_Core_AES::doubleRound($in0, $rk0, $in1, $rk1); + $this->assertSame( + ParagonIE_Sodium_Core_Util::bin2hex($c0), + ParagonIE_Sodium_Core_Util::bin2hex($c2) + ); + $this->assertSame( + ParagonIE_Sodium_Core_Util::bin2hex($c1), + ParagonIE_Sodium_Core_Util::bin2hex($c3) + ); + } + /** * @dataProvider aes128ecbProvider * @covers ParagonIE_Sodium_Core_AES::encryptBlockECB