<?php

namespace Buckhill\U2F\tests\units;

require('vendor/autoload.php');

use mageekguy\atoum;
use Buckhill\U2F\U2FHelper;
use function Buckhill\U2F\u2f;

class U2FKey extends atoum
{
    public function testCreateKey()
    {
        $this
            ->given($key = u2f()->key($this->getKeyData()))
            ->then
                ->object($key)->isInstanceOf(\Buckhill\U2F\U2FKey::class)
                ->string($key->getChallenge())->isEqualTo('YnJHbzRiNXdQYW5YNnBhbUozOHBJaVpkZ0Jrb3pzSVU')
                ->string($key->getPublicKey())->isEqualTo($this->getExpectedPublicKey())
                ->string($key->getKeyHandle())->isEqualTo('TBl7BtPWkiiB7GEdphPferDvTdnB1wSdjSYtHYg3BqNh19RKSNgv6-hPROB-pqeoq3rlel5NsnFqeLUAhF5Nbg')
                ->string($key->getAppId())->isEqualTo('https://server.mfa.web')
                ->string($key->getVersion())->isEqualTo(U2FHelper::U2F_VERSION)

                ->object($key->setChallenge('test'))->isInstanceOf(\Buckhill\U2F\U2FKey::class)
                ->string($key->getChallenge())->isEqualTo('test')

                ->object($key->createChallenge())->isInstanceOf(\Buckhill\U2F\U2FKey::class)
                ->string($key->getChallenge())->hasLength(32)

                ->array($key->toArray())->isNotEmpty()
                ->string($key->toJSON())->isNotEmpty($key->getLastError())

                // We're going to force an error now when encoding to JSON, because we'll receive malformed utf8 bytes
                ->object($key->setChallenge(random_bytes(32)))->isInstanceOf(\Buckhill\U2F\U2FKey::class)
                ->boolean($key->toJSON())->isFalse()
                ->string($key->getLastError())->isEqualTo('Malformed UTF-8 characters, possibly incorrectly encoded')

                ->object($key->setCounter(1))->isInstanceOf(\Buckhill\U2F\U2FKey::class)
                ->exception(
                    function() use (&$key)
                    {
                        $key->setCounter(null);
                    }
                )
                    ->isInstanceOf(\InvalidArgumentException::class)
                    ->hasMessage($this->exception->getMessage())
                    ->hasMessage('Counter must be an integer, got: NULL')

                ->exception(
                    function() use (&$key)
                    {
                        $key->setCounter(-1);
                    }
                )
                    ->isInstanceOf(\InvalidArgumentException::class)
                    ->hasMessage($this->exception->getMessage())
                    ->hasMessage('Counter can\'t be less than 0. Got: -1')

                ->exception(
                    function() use (&$key)
                    {
                        $key->setPublicKey(null);
                    }
                )->isInstanceOf(\InvalidArgumentException::class)
        ;
    }

    public function testAuthenticationResponse()
    {
        $this
            ->given($u2fkey = u2f()->key($this->getKeyData()))
            ->then
            ->object($key = u2f()->authenticate()->response($this->getValidU2FAuthSignature(), $u2fkey))->isInstanceOf(\Buckhill\U2F\U2FKey::class)
            ->integer($key->getCounter())->isEqualTo(27)
            ->string($key->toJSON())->isNotEmpty()->hasLength(212)
        ;
    }

    protected function getKeyData()
    {
        return [
            'challenge'     => 'YnJHbzRiNXdQYW5YNnBhbUozOHBJaVpkZ0Jrb3pzSVU',
            'publicKey'     => 'BEfBekIF7AhKwgi4QpQg0mQUQmIIEq6fDCOEv8auCDNNfeNpdNLrRFfAB9KjlBxp/pxjl45v2CnSOuSH+nmHMuk=',
            'keyHandle'     => 'TBl7BtPWkiiB7GEdphPferDvTdnB1wSdjSYtHYg3BqNh19RKSNgv6-hPROB-pqeoq3rlel5NsnFqeLUAhF5Nbg',
            'appId'         => 'https://server.mfa.web',
            'version'       => U2FHelper::U2F_VERSION,
            'counter'       => 0
        ];
    }

    protected function getValidU2FAuthSignature()
    {
        return [
            'clientData'    => 'eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiWW5KSGJ6UmlOWGRRWVc1WU5uQmhiVW96T0hCSmFWcGtaMEpyYjNwelNWVSIsIm9yaWdpbiI6Imh0dHBzOi8vc2VydmVyLm1mYS53ZWIiLCJjaWRfcHVia2V5IjoiIn0',
            'keyHandle'     => 'TBl7BtPWkiiB7GEdphPferDvTdnB1wSdjSYtHYg3BqNh19RKSNgv6-hPROB-pqeoq3rlel5NsnFqeLUAhF5Nbg',
            'signatureData' => 'AQAAABswRAIgZnfBV7O_O1j3keClYYtobXWFRbropjiYATy_RoVwp8oCIHFvZjRFP5tGDB1qY6vJZ250yAnw8J_ZLVMZ8RN3kOr5'
        ];
    }

    protected function getExpectedPublicKey()
    {
        return <<<EOF
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAER8F6QgXsCErCCLhClCDSZBRCYggS
rp8MI4S/xq4IM01942l00utEV8AH0qOUHGn+nGOXjm/YKdI65If6eYcy6Q==
-----END PUBLIC KEY-----
EOF;

    }
}