Is there a standard way to validate an Ed25519 public key (check that it's really a point on the curve and not some random bytes) using the standard Java Crypto APIs and/or BouncyCastle?
I found a python example here for a slightly different curve, but I would rather not re-implement it manually if that's avoidable: Validating an Ed25519 public key
For the context, here's how I'm creating a PublicKey
object from raw bytes (though I guess it succeeds for any bytes in rawKey
):
KeyFactory keyFactory = KeyFactory.getInstance("Ed25519");
SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), rawKey);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(subjectPublicKeyInfo.getEncoded());
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
The validity of a 32 bytes public key in the sense of RFC 8032 can be performed with BouncyCastle's Ed25519.validatePublicKeyFull()
.
Unfortunately, the documentation for this function is missing. The source code of validatePublicKeyFull()
shows that this function basically does the following:
checkPointFullVar()
checks whether the curve point defined by the 32 bytes public key is the identity point, non-canonical (>= P), or a member of small (insecure) subgroups. If one of these applies, the key is invalid.decodePointVar()
attempts to reconstruct the x-coordinate of the curve point from the 32 bytes public key. If this is not successful, the key is invalid (s. RFC 8032, 5.1.3).checkPointOrderVar()
multiplies the curve point defined by the 32 bytes public key by the order of the curve. If this operation does not give the identity point, the key is invalid (because then the curve point is not in the prime order subgroup).The BouncyCastle tests contain some examples for validatePublicKeyFull()
.
Besides validatePublicKeyFull()
, there is also validatePublicKeyPartial()
, which only performs the first two checks (1) and (2).
validatePublicKeyPartial()
is intended for a faster validation, which only checks basic properties but does not guarantee validity, while validatePublicKeyFull()
guarantees validity.