|
| 1 | +<?php |
| 2 | + |
| 3 | +declare(strict_types=1); |
| 4 | + |
| 5 | +namespace BitWasp\Bitcoin\Tests\Crypto\EcAdapter; |
| 6 | + |
| 7 | +use BitWasp\Bitcoin\Crypto\EcAdapter\EcAdapterFactory; |
| 8 | +use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Signature\SchnorrSigner; |
| 9 | +use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Signature\Signature; |
| 10 | +use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory; |
| 11 | +use BitWasp\Bitcoin\Key\Factory\PublicKeyFactory; |
| 12 | +use BitWasp\Bitcoin\Math\Math; |
| 13 | +use BitWasp\Bitcoin\Tests\AbstractTestCase; |
| 14 | +use BitWasp\Buffertools\Buffer; |
| 15 | +use Mdanter\Ecc\EccFactory; |
| 16 | + |
| 17 | +class PhpeccSchnorrSignerTest extends AbstractTestCase |
| 18 | +{ |
| 19 | + public function getCompliantSignatureFixtures(): array |
| 20 | + { |
| 21 | + return [ |
| 22 | + [ |
| 23 | + /*$privKey = */ "0000000000000000000000000000000000000000000000000000000000000001", |
| 24 | + /*$pubKey = */ "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", |
| 25 | + /*$msg32 = */ "0000000000000000000000000000000000000000000000000000000000000000", |
| 26 | + /*$sig64 = */ "787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05", |
| 27 | + ], |
| 28 | + [ |
| 29 | + /*$privKey = */ "B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF", |
| 30 | + /*$pubKey = */ "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", |
| 31 | + /*$msg32 = */ "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", |
| 32 | + /*$sig64 = */ "2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD", |
| 33 | + ], |
| 34 | + [ |
| 35 | + /*$privKey = */ "C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7", |
| 36 | + /*$pubKey = */ "03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B", |
| 37 | + /*$msg32 = */ "5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C", |
| 38 | + /*$sig64 = */ "00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380", |
| 39 | + ], |
| 40 | + ]; |
| 41 | + } |
| 42 | + |
| 43 | + /** |
| 44 | + * @dataProvider getCompliantSignatureFixtures |
| 45 | + * @param string $privKey |
| 46 | + * @param string $pubKey |
| 47 | + * @param string $msg32 |
| 48 | + * @param string $sig64 |
| 49 | + * @throws \Exception |
| 50 | + */ |
| 51 | + public function testSignatureFixtures(string $privKey, string $pubKey, string $msg32, string $sig64) |
| 52 | + { |
| 53 | + $ecAdapter = EcAdapterFactory::getPhpEcc(new Math(), EccFactory::getSecgCurves()->generator256k1()); |
| 54 | + $privFactory = new PrivateKeyFactory($ecAdapter); |
| 55 | + $priv = $privFactory->fromHexCompressed($privKey); |
| 56 | + $pub = $priv->getPublicKey(); |
| 57 | + $msg = Buffer::hex($msg32); |
| 58 | + $schnorrSigner = new SchnorrSigner($ecAdapter); |
| 59 | + $signature = $schnorrSigner->sign($priv, $msg); |
| 60 | + |
| 61 | + $math = $ecAdapter->getMath(); |
| 62 | + $r = $math->intToFixedSizeString($signature->getR(), 32); |
| 63 | + $s = $math->intToFixedSizeString($signature->getS(), 32); |
| 64 | + $this->assertEquals(strtolower($sig64), bin2hex($r.$s)); |
| 65 | + $this->assertTrue($schnorrSigner->verify($msg, $pub, $signature)); |
| 66 | + } |
| 67 | + |
| 68 | + public function getVerificationFixtures(): array |
| 69 | + { |
| 70 | + return [ |
| 71 | + [ |
| 72 | + /*$pubKey = */ "03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34", |
| 73 | + /*$msg32 = */ "4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703", |
| 74 | + /*$sig64 = */ "00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D", |
| 75 | + ], |
| 76 | + ]; |
| 77 | + } |
| 78 | + |
| 79 | + /** |
| 80 | + * @dataProvider getVerificationFixtures |
| 81 | + * @param string $pubKey |
| 82 | + * @param string $msg32 |
| 83 | + * @param string $sig64 |
| 84 | + * @throws \Exception |
| 85 | + */ |
| 86 | + public function testPositiveVerification(string $pubKey, string $msg32, string $sig64) |
| 87 | + { |
| 88 | + $ecAdapter = EcAdapterFactory::getPhpEcc(new Math(), EccFactory::getSecgCurves()->generator256k1()); |
| 89 | + $pubKeyFactory = new PublicKeyFactory($ecAdapter); |
| 90 | + $pub = $pubKeyFactory->fromHex($pubKey); |
| 91 | + $msg = Buffer::hex($msg32); |
| 92 | + $schnorrSigner = new SchnorrSigner($ecAdapter); |
| 93 | + $sigBuf = Buffer::hex($sig64); |
| 94 | + $r = $sigBuf->slice(0, 32)->getGmp(); |
| 95 | + $s= $sigBuf->slice(32, 64)->getGmp(); |
| 96 | + $signature = new Signature($ecAdapter, $r, $s); |
| 97 | + $this->assertTrue($schnorrSigner->verify($msg, $pub, $signature)); |
| 98 | + } |
| 99 | + |
| 100 | + public function getNegativeVerificationFixtures(): array |
| 101 | + { |
| 102 | + return [ |
| 103 | + [ |
| 104 | + /*$pubKey = */ "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", |
| 105 | + /*$msg32 = */ "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", |
| 106 | + /*$sig64 = */ "2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7", |
| 107 | + /*$reason = */ "incorrect R residuosity", |
| 108 | + ], |
| 109 | + [ |
| 110 | + /*$pubKey = */ "03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B", |
| 111 | + /*$msg32 = */ "5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C", |
| 112 | + /*$sig64 = */ "00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC", |
| 113 | + /*$reason = */ "negated message hash", |
| 114 | + ], |
| 115 | + [ |
| 116 | + /*$pubKey = */ "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", |
| 117 | + /*$msg32 = */ "0000000000000000000000000000000000000000000000000000000000000000", |
| 118 | + /*$sig64 = */ "787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C", |
| 119 | + /*$reason = */ "negated s value", |
| 120 | + ], |
| 121 | + [ |
| 122 | + /*$pubKey = */ "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", |
| 123 | + /*$msg32 = */ "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", |
| 124 | + /*$sig64 = */ "2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD", |
| 125 | + /*$reason = */ "negated public key", |
| 126 | + ], |
| 127 | + ]; |
| 128 | + } |
| 129 | + |
| 130 | + /** |
| 131 | + * @dataProvider getNegativeVerificationFixtures |
| 132 | + * @param string $pubKey |
| 133 | + * @param string $msg32 |
| 134 | + * @param string $sig64 |
| 135 | + * @throws \Exception |
| 136 | + */ |
| 137 | + public function testNegativeVerification(string $pubKey, string $msg32, string $sig64) |
| 138 | + { |
| 139 | + $ecAdapter = EcAdapterFactory::getPhpEcc(new Math(), EccFactory::getSecgCurves()->generator256k1()); |
| 140 | + $pubKeyFactory = new PublicKeyFactory($ecAdapter); |
| 141 | + $pub = $pubKeyFactory->fromHex($pubKey); |
| 142 | + $msg = Buffer::hex($msg32); |
| 143 | + $schnorrSigner = new SchnorrSigner($ecAdapter); |
| 144 | + $sigBuf = Buffer::hex($sig64); |
| 145 | + $r = $sigBuf->slice(0, 32)->getGmp(); |
| 146 | + $s= $sigBuf->slice(32, 64)->getGmp(); |
| 147 | + $signature = new Signature($ecAdapter, $r, $s); |
| 148 | + $this->assertFalse($schnorrSigner->verify($msg, $pub, $signature)); |
| 149 | + } |
| 150 | +} |
0 commit comments