| 
<?phpuse \ParagonIE\Halite\Symmetric\Crypto as Symmetric;
 use \ParagonIE\Halite\Symmetric\AuthenticationKey;
 use \ParagonIE\Halite\Symmetric\EncryptionKey;
 use \ParagonIE\Halite\Alerts as CryptoException;
 use \ParagonIE\Halite\Halite;
 use \ParagonIE\Halite\Util;
 
 /**
 * @backupGlobals disabled
 * @backupStaticAttributes disabled
 */
 class SymmetricTest extends PHPUnit_Framework_TestCase
 {
 /**
 * @covers Symmetric::authenticate()
 * @covers Symmetric::verify()
 */
 public function testAuthenticate()
 {
 $key = new AuthenticationKey(\str_repeat('A', 32), true);
 $message = 'test message';
 $mac = Symmetric::authenticate($message, $key);
 $this->assertTrue(
 Symmetric::verify($message, $key, $mac)
 );
 }
 
 /**
 * @covers Symmetric::authenticate()
 * @covers Symmetric::verify()
 */
 public function testAuthenticateFail()
 {
 $key = new AuthenticationKey(\str_repeat('A', 32), true);
 $message = 'test message';
 $mac = Symmetric::authenticate($message, $key, true);
 
 // Test invalid message
 $this->assertFalse(
 Symmetric::verify('othermessage', $key, $mac, true)
 );
 
 $r = \Sodium\randombytes_uniform(\mb_strlen($mac, '8bit'));
 
 $_mac = $mac;
 $_mac[$r] = \chr(
 \ord($_mac[$r])
 ^
 1 << \Sodium\randombytes_uniform(8)
 );
 
 // Test invalid signature
 $this->assertFalse(
 Symmetric::verify($message, $key, $_mac, true)
 );
 }
 
 /**
 * @covers Symmetric::encrypt()
 */
 public function testEncrypt()
 {
 $key = new EncryptionKey(\str_repeat('A', 32));
 $message = Symmetric::encrypt('test message', $key);
 $this->assertTrue(strpos($message, '31420200') === 0);
 
 $plain = Symmetric::decrypt($message, $key);
 $this->assertEquals($plain, 'test message');
 }
 
 /**
 * @covers Symmetric::encrypt()
 */
 public function testRawEncrypt()
 {
 $key = new EncryptionKey(\str_repeat('A', 32));
 $message = Symmetric::encrypt('test message', $key, true);
 $this->assertTrue(strpos($message, \ParagonIE\Halite\Halite::HALITE_VERSION) === 0);
 
 $plain = Symmetric::decrypt($message, $key, true);
 $this->assertEquals($plain, 'test message');
 }
 
 /**
 * @covers Symmetric::encrypt()
 */
 public function testEncryptFail()
 {
 $key = new EncryptionKey(\str_repeat('A', 32));
 $message = Symmetric::encrypt('test message', $key, true);
 $r = \Sodium\randombytes_uniform(\mb_strlen($message, '8bit'));
 $message[$r] = \chr(
 \ord($message[$r])
 ^
 1 << \Sodium\randombytes_uniform(8)
 );
 try {
 $plain = Symmetric::decrypt($message, $key, true);
 $this->assertEquals($plain, $message);
 $this->fail(
 'This should have thrown an InvalidMessage exception!'
 );
 } catch (CryptoException\InvalidMessage $e) {
 $this->assertTrue($e instanceof CryptoException\InvalidMessage);
 }
 }
 
 /**
 * @covers Symmetric::unpackMessageForDecryption()
 */
 public function testUnpack()
 {
 $key = new EncryptionKey(\str_repeat('A', 32));
 
 // Randomly sized plaintext
 $size = \Sodium\randombytes_uniform(1023) + 1;
 $plaintext = \Sodium\randombytes_buf($size);
 $message = Symmetric::encrypt($plaintext, $key, true);
 
 // Let's unpack our message
 $unpacked = Symmetric::unpackMessageForDecryption($message);
 
 // Now to test our expected results!
 $this->assertEquals(Util::safeStrlen($unpacked[0]), Halite::VERSION_TAG_LEN);
 $this->assertTrue($unpacked[1] instanceof \ParagonIE\Halite\Symmetric\Config);
 $config = $unpacked[1];
 if ($config instanceof \ParagonIE\Halite\Symmetric\Config) {
 $this->assertEquals(Util::safeStrlen($unpacked[2]), $config->HKDF_SALT_LEN);
 $this->assertEquals(Util::safeStrlen($unpacked[3]), \Sodium\CRYPTO_STREAM_NONCEBYTES);
 $this->assertEquals(
 Util::safeStrlen($unpacked[4]),
 Util::safeStrlen($message) - (
 Halite::VERSION_TAG_LEN +
 $config->HKDF_SALT_LEN +
 \Sodium\CRYPTO_STREAM_NONCEBYTES +
 \Sodium\CRYPTO_AUTH_BYTES
 )
 );
 $this->assertEquals(Util::safeStrlen($unpacked[5]), \Sodium\CRYPTO_AUTH_BYTES);
 } else {
 $this->fail('Cannot continue');
 }
 }
 }
 |