diff --git a/phpseclib/Crypt/EC/Formats/Signature/IEEE.php b/phpseclib/Crypt/EC/Formats/Signature/IEEE.php index cb98daa7..e300b6c1 100644 --- a/phpseclib/Crypt/EC/Formats/Signature/IEEE.php +++ b/phpseclib/Crypt/EC/Formats/Signature/IEEE.php @@ -54,11 +54,11 @@ abstract class IEEE /** * Returns a signature in the appropriate format */ - public static function save(BigInteger $r, BigInteger $s): string + public static function save(BigInteger $r, BigInteger $s, string $curve, int $length): string { $r = $r->toBytes(); $s = $s->toBytes(); - $len = max(strlen($r), strlen($s)); - return str_pad($r, $len, "\0", STR_PAD_LEFT) . str_pad($s, $len, "\0", STR_PAD_LEFT); + $length >>= 3; + return str_pad($r, $length, "\0", STR_PAD_LEFT) . str_pad($s, $length, "\0", STR_PAD_LEFT); } } diff --git a/phpseclib/Crypt/EC/PrivateKey.php b/phpseclib/Crypt/EC/PrivateKey.php index 513983cb..0382eb6d 100644 --- a/phpseclib/Crypt/EC/PrivateKey.php +++ b/phpseclib/Crypt/EC/PrivateKey.php @@ -158,7 +158,7 @@ final class PrivateKey extends EC implements Common\PrivateKey extract(ASN1Signature::load($signature)); - return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s); + return $this->formatSignature($r, $s); } } @@ -207,7 +207,7 @@ final class PrivateKey extends EC implements Common\PrivateKey list(, $s) = $temp->divide($this->q); */ - return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s); + return $this->formatSignature($r, $s); } /** @@ -249,4 +249,28 @@ final class PrivateKey extends EC implements Common\PrivateKey } return $key; } + + /** + * Returns a signature in the appropriate format + * + * @return string + */ + private function formatSignature(BigInteger $r, BigInteger $s): string + { + $format = $this->sigFormat; + + $temp = new \ReflectionMethod($format, 'save'); + $paramCount = $temp->getNumberOfRequiredParameters(); + + // @codingStandardsIgnoreStart + switch ($paramCount) { + case 2: return $format::save($r, $s); + case 3: return $format::save($r, $s, $this->getCurve()); + case 4: return $format::save($r, $s, $this->getCurve(), $this->getLength()); + } + // @codingStandardsIgnoreEnd + + // presumably the only way you could get to this is if you were using a custom plugin + throw new UnsupportedOperationException("$format::save() has $paramCount parameters - the only valid parameter counts are 2 or 3"); + } } diff --git a/tests/Unit/Crypt/EC/KeyTest.php b/tests/Unit/Crypt/EC/KeyTest.php index e6534986..0f84446e 100644 --- a/tests/Unit/Crypt/EC/KeyTest.php +++ b/tests/Unit/Crypt/EC/KeyTest.php @@ -749,4 +749,18 @@ z9DYTLdGkQDqox3AtEs9nn6kE1O/vHE4bqMegjj4gbA= $key = EC::loadFormat('PKCS8', $key); $this->assertInstanceOf(PublicKey::class, $key); } + + public function testIEEESignatureCreate(): void + { + $key = PublicKeyLoader::load('-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg7+qVCtyt+tV2hTou +kbZNIHu+PaE0osExnxdlkiC+VYqhRANCAAS8yEueJvIAnCk++0rsD8X9dk3hAmyb +4lv6WkjCQU5iksxIG/E60L8IeDZX8+oNzHPjNN5/6MBk0ISrGKyFhlH1 +-----END PRIVATE KEY-----'); + + $priv = $key->withSignatureFormat('IEEE'); + $sig = $priv->sign('ddd'); + + $this->assertTrue($key->getPublicKey()->withSignatureFormat('IEEE')->verify('ddd', $sig)); + } }