Bu örnekte, istemci verileri sunucuya göndermeden önce imzalamak için PHP 7.2+ makinada Sodium kullanacak. Sunucu verileri aldığında, verilen imzayla imzalanıp imzalanmadığını kontrol etmek için aynı şekilde PHP 7.2+ makinada Sodium kullanır. Doğrulama başarılı olduysa, istemci güvenilir olarak kabul edilir. Not: Kod içindeki yorumları okuyun.


Class


Uygulamanızdaki composer.json dosyasına "ext-sodium": "*" ekini eklemeniz gerekebilir. Ayrıca ilgili fonksiyonun tam olarak ne yaptığını öğrenmek isterseniz burayı okuyabilirsiniz.


/**
* Request signing without encrypting the data to prevent request tampering.
* You have to use same "key" sign and verify data.
*
* Use bin2hex() on signature before sending.
* Use hex2bin() on signature before verifying.
*/
class Sign
{
/**
* This is what sender computer does.
*
* @param string $plainData This is what sender computer will send to receiver computer
* @param string $key The key to sign data
*
* @return array
*/
public function sign(string $plainData, string $key): array
{
$mac = sodium_crypto_auth($plainData, $key);

return [
'signature' => $mac,
'data' => $plainData,
];
}

/**
* This is what receiver computer does.
*
* @param array $dataReceived This comes from the sender computer
* @param string $key The key to verify data
*
* @return string
*/
public function verify(array $dataReceived, string $key): string
{
if (!sodium_crypto_auth_verify($dataReceived['signature'], $dataReceived['data'], $key)) {
sodium_memzero($key);

throw new RuntimeException('Tempered data!');
}

return $dataReceived['data'];
}
}

Test


class SignTest extends TestCase
{
public function testSign(): void
{
$key = random_bytes(SODIUM_CRYPTO_AUTH_BYTES);

$dataToBeSent = (new Sign())->sign('inanzzz', $key);

$this->assertIsString($dataToBeSent['signature']);
$this->assertIsString($dataToBeSent['data']);
}

public function testVerifyFailsOnWrongKey(): void
{
// Sender
$key = random_bytes(SODIUM_CRYPTO_AUTH_BYTES);

$dataToBeSent = (new Sign())->sign('inanzzz', $key);

// Receiver
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Tempered data!');

$key = random_bytes(SODIUM_CRYPTO_AUTH_BYTES);

(new Sign())->verify($dataToBeSent, $key);
}

public function testVerifySucceeds(): void
{
// Sender
$key = random_bytes(SODIUM_CRYPTO_AUTH_BYTES);

$dataToBeSent = (new Sign())->sign('inanzzz', $key);

// Receiver
$result = (new Sign())->verify($dataToBeSent, $key);

$this->assertSame('inanzzz', $result);
}
}