alecmuffett / certificate-transparency

Automatically exported from code.google.com/p/certificate-transparency
0 stars 0 forks source link

API for public-key + algorithm #16

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I'm in-lining the patch since it's more for discussion.

The ASN.1 for the PK algorithm is an OID, plus "optional parameters" followed 
by an opaque-type of "bit string".   Each algorithm type is suppose to define 
it's own interpretation of the optional parameters and the bit-string.  

For RSA, optional parameters are not used (?)
For RSA, the public is a sequence of two integers

For DSA, optional parameters apparently it encodes "p,q,g"
For DSA, the public key is a single integer

For EC-PUB... it looks like a science project to extract the fields.

The code below doesn't convert bitstrings that aren't a multiple of 8 (unlikely 
to find any.. I put an assert in, but should throw an exception instead).  It 
also separates the algorithm (cheap) from the public key (maybe not cheap).    
it works "fine" on RSA and DSA keys, but it explodes on EC-PUB since I need to 
write a DER/ASN1 spec for it.

The "dumb api" might be just a tuple of (algorithm-name, byte-string) and let 
the caller DER-it or whatever.  the smart API might be breaking apart the 
bitstring by algorithm-type, and returning a table of fields (e.g. (rsa, 
{'p'=1234.., 'q'=213214, 'e'=3, etc})

To make like more interesting, certs are just missing algorithm info completely 
(these are more generated test certs to test bugs etc, and not really used on 
the web).

What are you thoughts on this API? I'm happy to hack on it..

nickg

+    def subject_public_key_algorithm(self):
+        """
+        Return 'short_name' for the OID, "RSA", "DSA", or "EC-PUBKEY"
+        """
+        alginfo = (self.__asn1_cert.getComponentByName("tbsCertificate").
+                   getComponentByName("subjectPublicKeyInfo").
+                   getComponentByName("algorithm"))
+        return alginfo[0].short_name()
+
+    def subject_public_key(self):
+        """
+        Return a tuple of (big) integers used in public key
+        """
+        bitstring = (self.__asn1_cert.getComponentByName("tbsCertificate").
+                         getComponentByName("subjectPublicKeyInfo").
+                         getComponentByName("subjectPublicKey"))
+
+        assert(len(bitstring) % 8 == 0)
+        s = ''
+        byte = 0
+        count = 0
+        for bit in bitstring:
+            byte = byte * 2 + bit
+            count += 1
+            if count == 8:
+                s += chr(byte)
+                byte = 0
+                count = 0
+
+        rsaparts = der_decoder.decode(s)
+        try:
+            # normal case in 99.99% of cases
+            return ( int(i) for i in rsaparts[0] )
+        except TypeError:
+            # sometimes a DSA  key is found (???)
+            # in this case it's just a single integer.
+            return ( int(rsaparts[0]), )
+

Original issue reported on code.google.com by nickgsup...@gmail.com on 15 Oct 2013 at 2:35

GoogleCodeExporter commented 9 years ago
(Routing to Emilia for review)

Original comment by er...@google.com on 15 Oct 2013 at 2:11

GoogleCodeExporter commented 9 years ago
I haven't forgotten about this, just working my way through a backlog.

Original comment by ekasper@google.com on 18 Oct 2013 at 1:43