RFR 8237218: Support NIST Curves verification in java implementation
Michael StJohns
mstjohns at comcast.net
Fri Feb 28 20:18:03 UTC 2020
On 2/28/2020 3:05 PM, Michael StJohns wrote:
> Sorry - running behind on this thread.
>
> In ECUtil.decodePoint(),
>
> Since this code is open, I'm wondering if it might be useful to add
> the checks specified in NIST SP800-186 Appendix D.1. or SP800-56Ar1
> 5.6.2.3 E.g.
>
>> D.1.2 Montgomery Curves
>> D.1.2.1 Partial Public Key Validation
>
>> Inputs:
>> 1. Montgomery curve MA,B defined over the prime field GF(p)
>>
>> 2. Point Q=(u, v) 1712
>> Output: ACCEPT or REJECT Q as an affine point on MA,B.
>> Process:
>> 1. If Q is the point at infinity ∅, output REJECT.
>> 2. Verify that both u and v are integers in the interval [0, p−1].
>> Output REJECT if verification fails.
>> 3. Verify that (u, v) is a point on the MA,B by checking that (u, v)
>> satisfies the defining equation v2 = u (u2 + A u + 1) where
>> computations are carried out in GF(p). Output REJECT if verification
>> fails.
>> 4. Otherwise output ACCEPT.
>
>> D.1.2.2 Full Public Key Validation
>> Inputs:
>> 1. Montgomery curve MA,B defined over the prime field GF(p)
>> 2. Point Q
>> Output: ACCEPT or REJECT Q as a point on MA,B of order n.
>> Process:
>> 1. Perform partial public key validation on Q using the procedure of
>> Appendix D.1.2.1. Output REJECT if this procedure outputs REJECT.
>> 2. Verify that n Q = ∅. Output REJECT if verification fails.
>> 3. Otherwise output ACCEPT.
>
> This mainly ensures that the X/Y provided is actually a point on the
> curve. The threat to receiving a bad public key is more on the ECDH
> side, but this appears to be the code that would need to be modified
> so...
>
> Later, Mike
>
Here's the function I use in my application code - the last check
(needed for full verification) uses BouncyCastle as I didn't have access
to the internal methods in the SunEC provider. Would have to be
refactored slightly to be used in ECUtil.decodePoint().
/**
* This function performs the checks described in NIST SP800-56A,
* section 5.6.2.5 over an ECPublicKey. It throws a
* GeneralSecurityException if the key does not validate
*
* @param k the key to validate
*
* @throws InvalidKeyException if the key is invalid
*/
public static void checkECPublicKey (ECPublicKey k)
throws InvalidKeyException {
// Step 0 - not in the SP document, but we don't support F2M
// curves
if (!((k.getParams().getCurve().getField()) instanceof ECFieldFp)) {
throw new InvalidKeyException ("ECPublicKey is not on a Prime
Curve - not supported");
}
ECPoint point = k.getW();
// Step 1:
if (point.equals(ECPoint.POINT_INFINITY)) {
throw new InvalidKeyException ("ECPublic key is point at Infinity");
}
// Step 2:
EllipticCurve curve = k.getParams().getCurve();
BigInteger p = ((ECFieldFp)curve.getField()).getP();
BigInteger x = point.getAffineX();
BigInteger y = point.getAffineY();
if (x.compareTo(BigInteger.ZERO) <= 0 || x.compareTo(p) >= 0)
throw new InvalidKeyException ("ECPublicKey X out of Range");
if (y.compareTo(BigInteger.ZERO) <= 0 || y.compareTo(p) >= 0)
throw new InvalidKeyException ("ECPublicKey Y out of Range");
// Step 3:
BigInteger y2 = y.pow(2).mod(p);
BigInteger x3 = x.pow(3);
BigInteger ax = curve.getA().multiply(x);
BigInteger sum = x3.add(ax).add(curve.getB()).mod(p);
if (!y2.equals(sum))
throw new InvalidKeyException ("ECPublicKey Point is not on Curve");
// Step 4: check nQ == INFINITY
BigInteger n = k.getParams().getOrder();
org.bouncycastle.math.ec.ECPoint bcPoint =
// EC5Util.convertPoint(k.getParams(), point, false); A/O 1.64
EC5Util.convertPoint(k.getParams(), point);
org.bouncycastle.math.ec.ECPoint testPoint =
bcPoint.multiply(n);
if (!testPoint.isInfinity())
throw new InvalidKeyException ("ECPublicKey invalid order");
}
More information about the security-dev
mailing list