phpseclib/tests/Unit/Crypt/GCMTest.php
2024-02-07 21:17:27 -06:00

238 lines
8.2 KiB
PHP

<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright 2013 Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
declare(strict_types=1);
namespace phpseclib3\Tests\Unit\Crypt;
use phpseclib3\Crypt\AES;
use phpseclib3\Tests\PhpseclibTestCase;
class GCMTest extends PhpseclibTestCase
{
/**
* Produces all combinations of test values.
*/
public static function engine128Vectors(): array
{
$engines = [
'PHP',
'Eval',
'OpenSSL',
'OpenSSL (GCM)',
];
// test vectors come from the following URL:
// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
$p1 = '00000000000000000000000000000000';
$p2 = 'd9313225f88406e5a55909c5aff5269a' .
'86a7a9531534f7da2e4c303d8a318a72' .
'1c3c0c95956809532fcf0e2449a6b525' .
'b16aedf5aa0de657ba637b391aafd255';
$p3 = 'd9313225f88406e5a55909c5aff5269a' .
'86a7a9531534f7da2e4c303d8a318a72' .
'1c3c0c95956809532fcf0e2449a6b525' .
'b16aedf5aa0de657ba637b39';
$n1 = '000000000000000000000000';
$n2 = 'cafebabefacedbaddecaf888';
$n3 = 'cafebabefacedbad';
$n4 = '9313225df88406e555909c5aff5269aa' .
'6a7a9538534f7da1e4c303d2a318a728' .
'c3c0c95156809539fcf0e2429a6b5254' .
'16aedbf5a0de6a57a637b39b';
$k1 = '00000000000000000000000000000000';
$k2 = 'feffe9928665731c6d6a8f9467308308';
$c1 = '0388dace60b6a392f328c2b971b2fe78';
$c2 = '42831ec2217774244b7221b784d0d49c' .
'e3aa212f2c02a4e035c17e2329aca12e' .
'21d514b25466931c7d8f6a5aac84aa05' .
'1ba30b396a0aac973d58e091473f5985';
$c3 = '42831ec2217774244b7221b784d0d49c' .
'e3aa212f2c02a4e035c17e2329aca12e' .
'21d514b25466931c7d8f6a5aac84aa05' .
'1ba30b396a0aac973d58e091';
$c4 = '61353b4c2806934a777ff51fa22a4755' .
'699b2a714fcdc6f83766e5f97b6c7423' .
'73806900e49f24b22b097544d4896b42' .
'4989b5e1ebac0f07c23f4598';
$c5 = '8ce24998625615b603a033aca13fb894' .
'be9112a5c3a211a8ba262a3cca7e2ca7' .
'01e4a9a4fba43c90ccdcb281d48c7c6f' .
'd62875d2aca417034c34aee5';
$a1 = 'feedfacedeadbeeffeedfacedeadbeef' .
'abaddad2';
$subvectors = [
// key, plaintext, nonce, aad, ciphertext, tag
// Test Case 1
[$k1, '', $n1, '', '', '58e2fccefa7e3061367f1d57a4e7455a'],
// Test Case 2
[$k1, $p1, $n1, '', $c1, 'ab6e47d42cec13bdf53a67b21257bddf'],
// Test Case 3
[$k2, $p2, $n2, '', $c2, '4d5c2af327cd64a62cf35abd2ba6fab4'],
// Test Case 4
[$k2, $p3, $n2, $a1, $c3, '5bc94fbc3221a5db94fae95ae7121a47'],
// Test Case 5
[$k2, $p3, $n3, $a1, $c4, '3612d2e79e3b0785561be14aaca2fccb'],
// Test Case 6
[$k2, $p3, $n4, $a1, $c5, '619cc5aefffe0bfa462af43c1699d050'],
];
$vectors = [];
for ($i = 0; $i < count($subvectors); $i++) {
for ($j = 0; $j < count($subvectors[$i]); $j++) {
$subvectors[$i][$j] = pack('H*', $subvectors[$i][$j]);
}
foreach ($engines as $engine) {
$temp = $subvectors[$i];
array_unshift($temp, $engine);
$vectors[] = $temp;
}
}
return $vectors;
}
/**
* @dataProvider engine128Vectors
*/
public function test128Vectors($engine, $key, $plaintext, $nonce, $aad, $ciphertext, $tag): void
{
$aes = new AES('gcm');
$aes->setKey($key);
$aes->setNonce($nonce);
$aes->setAAD($aad);
if (!$aes->isValidEngine($engine)) {
self::markTestSkipped("Unable to initialize $engine engine");
}
$aes->setPreferredEngine($engine);
$ciphertext2 = $aes->encrypt($plaintext);
$this->assertEquals($ciphertext, $ciphertext2);
$this->assertEquals($tag, $aes->getTag());
$aes->setTag($tag);
$this->assertEquals($plaintext, $aes->decrypt($ciphertext));
}
/**
* Produces all combinations of test values.
*/
public static function engine256Vectors(): array
{
$engines = [
'PHP',
'Eval',
'OpenSSL',
'OpenSSL (GCM)',
'libsodium',
];
$p1 = '00000000000000000000000000000000';
$p2 = 'd9313225f88406e5a55909c5aff5269a' .
'86a7a9531534f7da2e4c303d8a318a72' .
'1c3c0c95956809532fcf0e2449a6b525' .
'b16aedf5aa0de657ba637b391aafd255';
$p3 = 'd9313225f88406e5a55909c5aff5269a' .
'86a7a9531534f7da2e4c303d8a318a72' .
'1c3c0c95956809532fcf0e2449a6b525' .
'b16aedf5aa0de657ba637b39';
$n1 = '000000000000000000000000';
$n2 = 'cafebabefacedbaddecaf888';
$n3 = 'cafebabefacedbad';
$n4 = '9313225df88406e555909c5aff5269aa' .
'6a7a9538534f7da1e4c303d2a318a728' .
'c3c0c95156809539fcf0e2429a6b5254' .
'16aedbf5a0de6a57a637b39b';
$k1 = '00000000000000000000000000000000' .
'00000000000000000000000000000000';
$k2 = 'feffe9928665731c6d6a8f9467308308' .
'feffe9928665731c6d6a8f9467308308';
$c1 = 'cea7403d4d606b6e074ec5d3baf39d18';
$c2 = '522dc1f099567d07f47f37a32a84427d' .
'643a8cdcbfe5c0c97598a2bd2555d1aa' .
'8cb08e48590dbb3da7b08b1056828838' .
'c5f61e6393ba7a0abcc9f662898015ad';
$c3 = '522dc1f099567d07f47f37a32a84427d' .
'643a8cdcbfe5c0c97598a2bd2555d1aa' .
'8cb08e48590dbb3da7b08b1056828838' .
'c5f61e6393ba7a0abcc9f662';
$c4 = 'c3762df1ca787d32ae47c13bf19844cb' .
'af1ae14d0b976afac52ff7d79bba9de0' .
'feb582d33934a4f0954cc2363bc73f78' .
'62ac430e64abe499f47c9b1f';
$c5 = '5a8def2f0c9e53f1f75d7853659e2a20' .
'eeb2b22aafde6419a058ab4f6f746bf4' .
'0fc0c3b780f244452da3ebf1c5d82cde' .
'a2418997200ef82e44ae7e3f';
$a1 = 'feedfacedeadbeeffeedfacedeadbeef' .
'abaddad2';
$subvectors = [
// key, plaintext, nonce, aad, ciphertext, tag
// Test Case 13
[$k1, '', $n1, '', '', '530f8afbc74536b9a963b4f1c4cb738b'],
// Test Case 14
[$k1, $p1, $n1, '', $c1, 'd0d1c8a799996bf0265b98b5d48ab919'],
// Test Case 15
[$k2, $p2, $n2, '', $c2, 'b094dac5d93471bdec1a502270e3cc6c'],
// Test Case 16
[$k2, $p3, $n2, $a1, $c3, '76fc6ece0f4e1768cddf8853bb2d551b'],
// Test Case 17
[$k2, $p3, $n3, $a1, $c4, '3a337dbf46a792c45e454913fe2ea8f2'],
// Test Case 18
[$k2, $p3, $n4, $a1, $c5, 'a44a8266ee1c8eb0c8b5d4cf5ae9f19a'],
];
$vectors = [];
for ($i = 0; $i < count($subvectors); $i++) {
for ($j = 0; $j < count($subvectors[$i]); $j++) {
$subvectors[$i][$j] = pack('H*', $subvectors[$i][$j]);
}
foreach ($engines as $engine) {
$temp = $subvectors[$i];
array_unshift($temp, $engine);
$vectors[] = $temp;
}
}
return $vectors;
}
/**
* @dataProvider engine256Vectors
*/
public function test256Vectors($engine, $key, $plaintext, $nonce, $aad, $ciphertext, $tag): void
{
$aes = new AES('gcm');
$aes->setKey($key);
$aes->setNonce($nonce);
$aes->setAAD($aad);
if (!$aes->isValidEngine($engine)) {
self::markTestSkipped("Unable to initialize $engine engine");
}
$aes->setPreferredEngine($engine);
$ciphertext2 = $aes->encrypt($plaintext);
$this->assertEquals($ciphertext, $ciphertext2);
$this->assertEquals($tag, $aes->getTag());
$aes->setTag($tag);
$this->assertEquals($plaintext, $aes->decrypt($ciphertext));
}
}