New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calling verifyPoint on EC curves throws TypeError #1997
Comments
Try this: $curve = new \phpseclib3\Crypt\EC\Curves\brainpoolP256r1();
$x = new \phpseclib3\Math\BigInteger(0);
$y = new \phpseclib3\Math\BigInteger(0);
$x = $curve->convertInteger($x);
$y = $curve->convertInteger($y);
$curve->verifyPoint([$x, $y]); The thing is... brainpoolP256r1 is a prime field elliptic curve (as opposed to a binary field elliptic curve). What this means is that you can't have numbers greater than or equal to the modulo. Like if the modulo is 5 then the only valid numbers that you're going to be able to use are 0-4. From that one might conclude that this would work: $curve = new \phpseclib3\Crypt\EC\Curves\brainpoolP256r1();
$x = new \phpseclib3\Math\BigInteger(0);
$y = new \phpseclib3\Math\BigInteger(0);
$modulo = new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16);
$factory = new \phpseclib3\Math\PrimeField($modulo);
$x = $factory->newInteger($x);
$y = $factory->newInteger($y);
$curve->verifyPoint([$x, $y]); But if you do that you'll get this:
That's because doing modular reductions over and over again is costly so what phpseclib does is that it create a hyper optimized modular reduction method that's bespoke to the modulo and for performance purposes it just checks to see that both \phpseclib3\Math\PrimeField\Integer instances were created by the same factory. So like whereas this works: $modulo = new BigInteger(5);
$factory = new \phpseclib3\Math\PrimeField($modulo);
$x = $factory->newInteger(new BigInteger(4));
$y = $factory->newInteger(new BigInteger(4));
echo $x->add($y); This doesn't: $modulo = new BigInteger(5);
$factory = new \phpseclib3\Math\PrimeField($modulo);
$x = $factory->newInteger(new BigInteger(4));
$factory = new \phpseclib3\Math\PrimeField($modulo);
$y = $factory->newInteger(new BigInteger(4));
echo $x->add($y); |
Thanks for the detailed explanation. Is there a mechanism for creating key objects (for me, public keys) from the curve name and coordinates, or am I looking at things from the wrong direction? |
Yah - I'll try to get that to you this evening. Need to get ready to head off to work! |
So prob the easiest way to create a key with specific coordinate would be to do something like this (based on the RFC4050 format): $key = PublicKeyLoader::load('<ECDSAKeyValue xmlns="http://www.w3.org/2001/04/xmldsig-more#">
<DomainParameters><NamedCurve URN="urn:oid:1.3.36.3.3.2.8.1.1.7" /></DomainParameters>
<PublicKey>
<X Value="72379364585787862211816843651173825953534775149312366423617662317441035882390" />
<Y Value="60964272061100602708590358249320835245921448174521229979647778785859175709132" />
</PublicKey>
</ECDSAKeyValue>'); The curve name is loaded with If it weren't for you wanting to use less common curves like the brainpool curves the JWK format could work, too, but that format only supports a few very specific curves. It might be easier to pass to $key = PublicKeyLoader::load([
'e' => new BigInteger($e, 16),
'n' => new BigInteger($n, 16)
]); Unfortunately, there's not (currently) a Raw plugin for EC curves. I could add one this weekend but there's not currently one. Alternatively, you could write your own plugin. https://phpseclib.com/docs/publickeys#custom-key-formats talks about how to do that. Or if I wrote a Raw plugin you could get that plugin and use it with the current version of phpseclib 3 without having to make any changes to your vendor/ directory contents. If you wanted a Raw plugin I should be able to whip one up this weekend. Also, sorry for not responding yesterday after work - I got home and fell asleep very shortly thereafter. Not sure why I was so tired but I was! |
I was wondering whether a plugin might be a useful addition - this format is supposedly a standardised format from ISO 7816 (self-descriptive card-verifiable certificates), although without access to the standard itself I don't know if it's explicitly described there. The best reference I have for it is the EU tachograph equipment regulations, which is probably why it seems like I'm approaching it from different directions to most. I'll try and get myself familiar with how phpseclib does things, and see if I can't put something useful together myself first - what you've already sent across has helped massively though, as I can at least see something similar to OpenSSLs certificate detail text view now. |
Yah - ISO standards tend not to be free. If I had to guess I'd guess https://www.iso.org/standard/77180.html houses it but I'm also not prepared to pay $200+ USD for it. Anyway, if you'd be willing to share it I'd probably be down to include it in phpseclib! |
I'm trying to load a public key from a weird storage method, and I've come across the following when trying to use it to verify a signature. In the full code, the curve is being loaded based on an ASN.1 object identifier in DER format along with the x/y coordinates, but I've stripped that out to see what's happening.
The $x parameter appears to be EC\BaseCurves\Prime::$a.
Error Message:
PHP Fatal error: Uncaught TypeError: phpseclib3\Math\BigInteger::multiply(): Argument #1 ($x) must be of type phpseclib3\Math\BigInteger, phpseclib3\Math\PrimeField\Integer given, called in vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php on line 476 and defined in vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php:274
Minimal test case
Expected outcome: true/false depending on whether 0,0 is on the curve or not.
I'm not ruling out that I'm doing something dumb to get to this point, but this seems like a bug.
The text was updated successfully, but these errors were encountered: