<?php 
use \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'); 
        } 
    } 
}
 
 |