Cryptography: The EllipticCurvePrivateNumbers API is inherently not constant-time

Created on 13 May 2018  路  4Comments  路  Source: pyca/cryptography

cryptography.io presents an intermediate representation, EllipticCurvePrivateNumbers, for callers to convert EC private keys to and from. This is not safe. An EC private key is a uniformly-selected non-zero scalar (number modulo the order). In a constant-time implementation, the scalar should not be treated differently based on how many leading zeros it happens to have. This is one of the key reasons a cryptographic big-integer implementation differs from a calculator one. Cryptography integers have known width. The scalar 42 in P-256 and 42 in P-384 have different bit widths.

EllipticCurvePrivateNumbers stores the private key as a Python integer, converted via _bn_to_int. While it appears to make some attempt at being constant-time, leading zeros will ultimately get stripped, leaking some information. Ultimately, a Python int is not a suitable integer type for cryptography. Instead, if there is a need to export the private key value, expose a byte string, with width determined by the (public) group order.

security-hardening

Most helpful comment

The real mistake here is that we put from_encoded_point on EllipticCurvePrivateNumbers. It should have been on EllipticCurvePublicKey -- numbers and encoded points are two different serializations, there shouldn't be methods for deserializing on a class which is itself a serialization.

The first step here would be to add a from_encoded_point to EllipticCurvePublicKey, then we can come up with a plan for killing the old method.

All 4 comments

Thanks for filing this. We've been regretting this API for years now but haven't been ambitious enough to bite off replacing it with something decent. The historical reasons this API exists don't matter any more -- we can definitely do much better here.

The real mistake here is that we put from_encoded_point on EllipticCurvePrivateNumbers. It should have been on EllipticCurvePublicKey -- numbers and encoded points are two different serializations, there shouldn't be methods for deserializing on a class which is itself a serialization.

The first step here would be to add a from_encoded_point to EllipticCurvePublicKey, then we can come up with a plan for killing the old method.

We moved conversion from encoded points to no longer require going through python bigints, so I think thrust of this is resolved.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DurandA picture DurandA  路  5Comments

MortenEriksen picture MortenEriksen  路  5Comments

darkn3rd picture darkn3rd  路  6Comments

NikolaiT picture NikolaiT  路  4Comments

webknjaz picture webknjaz  路  7Comments