[Cryptography-dev] Asymmetric signing primitives

Paul Kehrer paul.l.kehrer at gmail.com
Sun Jul 27 02:11:01 CEST 2014


Ron, thank you very much for the feedback. I’ve added my comments inline.

On July 26, 2014 at 2:52:41 PM, Ron Frederick (ronf at timeheart.net) wrote:

Hello,

I recently began looking at adding support for PyCA to my AsyncSSH package (http://asyncssh.timeheart.net). It currently uses PyCrypto, but I see a lot of potential in being able to directly use OpenSSL and other more carefully scrutinized crypto libraries from a security perspective.

In the process of adding this support, I ran into an issue with DSA signing and verification. The current implementation in PyCA seems to ASN.1 encode the signature it produces before returning it, while the SSH protocol requires a different encoding to be used of the raw ‘r’ and ’s’ values. I’ve worked around this for now by doing my own ASN.1 code of the return result before re-encoding it in the form SSH needs, but this is somewhat wasteful. I was wondering if it might be possible to provide an option or alternate API which would return the raw r & s values as integers, for protocols that want to use an encoding other than ASN.1.


We’ve talked about adding alternate APIs to get the raw (r, s) tuple out of the DSA signature but we’ve been conflicted about whether we wanted to add a dependency on pyasn1 or if we just want to write some code that handles ASN.1 sequences and integers ourselves. How did you approach it? Filed as: https://github.com/pyca/cryptography/issues/1285

As I worked with these asymmetric key classes, I also noticed a bit of an inconsistency in the API used to access the various raw numbers that go into making up the keys. The current API uses a mixture of method calls and properties, and provides different ways to access some of the values depending on whether you are working with public or private keys. I think it would be good to make this a bit more consistent, at least about method calls vs. properties, but also ideally to provide a common way to access all the values common to public & private keys using the same API, with additional API calls for private keys to access values only applicable there.

As an example of what I’m talking about, here are the calls needed to access the parameters of a DSA public key today:

p: key.parameters().parameter_numbers().p
q: key.parameters().parameter_numbers().q
g: key.parameters().parameter_numbers().g
y: key.public_numbers().y

Note how in one case you can get to the public numbers directly, whereas in the other you have to go through an intermediate object first. It would be nice there to have parameter_numbers() available directly from the key similar to public_numbers(), at least as a convenience function. I would keep the existing parameters() function as well, as it has value to extract the parameters as a group to use in creating other keys. However, allowing access either that way or directly to the numbers object would be nice.
This seems reasonable to me. If we do this we would add it to the DSAPublicKeyWithNumbers and DSAPrivateKeyWithNumbers interfaces. Filed as https://github.com/pyca/cryptography/issues/1286



For a DSA private key, the first three calls are the same, but the call to get the “y” value is different:

y: key.private_numbers().public_numbers.y


Hmm, yes, the inconsistency between function and attribute here is definitely confusing. Filed as https://github.com/pyca/cryptography/issues/1288





Also, note here how public_numbers is a property of the object returned by private_numbers(), rather than being a function call the way it is above. Again, it would be nice if private keys had parameter_numbers(), public_numbers(), and private_numbers() calls to expose these values directly, in a way consistent with public keys.

The final call to get the private numbers is already consistent with this:

x: key.private_numbers().x

What I’m suggesting is something that looks more like:

p: key.parameter_numbers().p
q: key.parameter_numbers().q
g: key.parameter_numbers().g
y: key.public_numbers().y
x: key.private_numbers().x

RSA keys have similar issues. The current calls for public keys are:

n: key.public_numbers().n
e: key.public_numbers().e

However, the calls for private keys are:

n: key.private_numbers().public_numbers.n
e: key.private_numbers().public_numbers.e
d: key.private_numbers().d
p: key.private_numbers().p
q: key.private_numbers().q

Having a directly callable public_numbers() function on both the public & private key classes here would be convenient.


Agreed. Like DSA this would be accomplished by expanding the WithNumbers interfaces and implementing the methods on the backend specific implementations. (https://github.com/pyca/cryptography/issues/1286)





Finally, if I may, I have one final suggestion. It would be convenient to have the update() function return self (the signer object). That way, it would be possible to write something like:

        signature = key.signer(PKCS1v15(), SHA1()).update(data).finalize()

instead of:

        signer = self._key.signer(PKCS1v15(), SHA1())
        signer.update(data)
        signature = signer.finalize()

in cases where you had only a single block of data to pass in.


This also sounds like a good idea (that we should consider doing for all our update/finalize APIs). Filed as https://github.com/pyca/cryptography/issues/1287





Thank you for listening, and for all the work that has gone into this package so far!




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cryptography-dev/attachments/20140726/f75a2a9e/attachment-0001.html>


More information about the Cryptography-dev mailing list