Question

What I am trying to do is read some PEM public keys using Python GAE.

the RSAKey module does not parse PEM formatted public keys, just private.

If I can get the modulus and exponent from the PEM, I can go from there.

Exploring a typical PEM (of the sort I will be using) with openssl asn1parse I can find the BIT STRING where they live.

But I can't figure out how to find them using the gdata ASN1Parser.

For example openssl output:

openssl asn1parse -i -in test.pem
 0:d=0  hl=3 l= 159 cons: SEQUENCE          
 3:d=1  hl=2 l=  13 cons:  SEQUENCE          
 5:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
16:d=2  hl=2 l=   0 prim:   NULL              
18:d=1  hl=3 l= 141 prim:  BIT STRING

And then drilling down I can see the RSA Modulus and Exponent:

openssl asn1parse -strparse 18 -i -in test.pem 
  0:d=0  hl=3 l= 137 cons: SEQUENCE          
  3:d=1  hl=3 l= 129 prim:  INTEGER           :09C7A8007111B2B...
135:d=1  hl=2 l=   3 prim:  INTEGER           :010001

If I then take this same PEM and in Python stick it into bytes, how do I get the correct child to get these values?

asn1 = ASN1Parser(bytes)
modulus = asn1.getChild(1).getChild(0).value
exponent = asn1.getChild(1).getChild(1).value
binascii.hexlify(modulus)

Or what? I can't figure out what level, etc I need to look. I also don't really know what I'm doing... Using hexlify I can see the values in there, but always (playing with child, and depth) with extra stuff in front, and/or not the full number as shown in openssl.

Was it helpful?

Solution

I modified tlslite to do what you are talking about... Here's a snippet that should help you out. "bytes" is the DER encoded public key.

I think the problem that you are having is that some keys may have "padding". The padding length is the first byte of the payload. You'll then need to skip the padding bytes and that many bytes of padding.

@staticmethod
def parseDERPublicKey(bytes):
    a = ASN1Parser(bytes)
    b = a.getChild(1)
    padding = b.value[1]
    # TODO: I am assuming padding is 0, this is wrong.
    #       Skip the padding as well.
    c = b.value[1:] # get the mod/exp portion after the padding
    d = ASN1Parser(c)

    modulus = bytesToNumber(d.getChild(0).value)
    exponent = bytesToNumber(d.getChild(1).value)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top