Index: fedd/federation/asn1_raw.py
===================================================================
--- fedd/federation/asn1_raw.py	(revision 5d3f2390d0bf55a90f3cb9b8f7d6d5c25c8dbac9)
+++ fedd/federation/asn1_raw.py	(revision 5d3f2390d0bf55a90f3cb9b8f7d6d5c25c8dbac9)
@@ -0,0 +1,160 @@
+# Modified from an example in the Python ASN.1 package to read certificate
+# files and extract key bits.  More recent versions of m2crypto support this
+# more directly.
+
+import sys, string, base64
+from pyasn1.type import tag,namedtype,namedval,univ,constraint,char,useful
+from pyasn1.codec.der import decoder, encoder
+from pyasn1 import error
+
+from M2Crypto import EVP
+
+# Would be autogenerated from ASN.1 source by a ASN.1 parser
+# X.509 spec (rfc2459)
+
+MAX = 64  # XXX ?
+
+class DirectoryString(univ.Choice):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('teletexString', char.TeletexString().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType('printableString', char.PrintableString().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType('universalString', char.UniversalString().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType('utf8String', char.UTF8String().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType('bmpString', char.BMPString().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType('ia5String', char.IA5String().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) # hm, this should not be here!? XXX
+        )
+
+class AttributeValue(DirectoryString): pass
+
+class AttributeType(univ.ObjectIdentifier): pass
+
+class AttributeTypeAndValue(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('type', AttributeType()),
+        namedtype.NamedType('value', AttributeValue())
+        )
+
+class RelativeDistinguishedName(univ.SetOf):
+    componentType = AttributeTypeAndValue()
+
+class RDNSequence(univ.SequenceOf):
+    componentType = RelativeDistinguishedName()
+
+class Name(univ.Choice):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('', RDNSequence())
+        )
+                          
+class AlgorithmIdentifier(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('algorithm', univ.ObjectIdentifier()),
+        namedtype.OptionalNamedType('parameters', univ.Null())
+        # XXX syntax screwed?
+#        namedtype.OptionalNamedType('parameters', univ.ObjectIdentifier())
+        )
+
+class Extension(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('extnID', univ.ObjectIdentifier()),
+        namedtype.DefaultedNamedType('critical', univ.Boolean('False')),
+        namedtype.NamedType('extnValue', univ.OctetString())
+        )
+
+class Extensions(univ.SequenceOf):
+    componentType = Extension()
+    sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX)
+
+class SubjectPublicKeyInfo(univ.Sequence):
+     componentType = namedtype.NamedTypes(
+         namedtype.NamedType('algorithm', AlgorithmIdentifier()),
+         namedtype.NamedType('subjectPublicKey', univ.BitString())
+         )
+
+class UniqueIdentifier(univ.BitString): pass
+
+class Time(univ.Choice):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('utcTime', useful.UTCTime()),
+        namedtype.NamedType('generalTime', useful.GeneralizedTime())
+        )
+    
+class Validity(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('notBefore', Time()),
+        namedtype.NamedType('notAfter', Time())
+        )
+
+class CertificateSerialNumber(univ.Integer): pass
+
+class Version(univ.Integer):
+    namedValues = namedval.NamedValues(
+        ('v1', 0), ('v2', 1), ('v3', 2)
+        )
+
+class TBSCertificate(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.DefaultedNamedType('version', Version('v1', tagSet=Version.tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))),
+        namedtype.NamedType('serialNumber', CertificateSerialNumber()),
+        namedtype.NamedType('signature', AlgorithmIdentifier()),
+        namedtype.NamedType('issuer', Name()),
+        namedtype.NamedType('validity', Validity()),
+        namedtype.NamedType('subject', Name()),
+        namedtype.NamedType('subjectPublicKeyInfo', SubjectPublicKeyInfo()),
+        namedtype.OptionalNamedType('issuerUniqueID', UniqueIdentifier().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
+        namedtype.OptionalNamedType('subjectUniqueID', UniqueIdentifier().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
+        namedtype.OptionalNamedType('extensions', Extensions().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)))
+        )
+
+class Certificate(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('tbsCertificate', TBSCertificate()),
+        namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()),
+        namedtype.NamedType('signatureValue', univ.BitString())
+        )
+
+# end of ASN.1 data structures
+
+
+def get_bits(substrate):
+    certType = Certificate()
+    cert = decoder.decode(substrate, asn1Spec=certType)[0]
+    n = cert
+    for name in ('tbsCertificate', 'subjectPublicKeyInfo', 
+	    'subjectPublicKey'):
+	n = n.getComponentByName(name)
+	if n == None: raise RuntimeException("Bad cert")
+
+    b = []
+    for i in range(0, len(n), 8):
+	v = 0
+	for j in range(0, 8):
+	    v = (v << 1) + n[i+j]
+	b.append(v)
+
+    return str().join([chr(x) for x in b])
+
+
+def get_key_bits_from_file(fname):
+    stSpam, stHam, stDump = 0, 1, 2
+    state = stSpam
+
+    f = open(fname)
+
+    for certLine in f:
+	certLine = string.strip(certLine)
+	if state == stSpam:
+	    if certLine == '-----BEGIN CERTIFICATE-----':
+		substrate = ""
+		state = stHam
+		continue
+	if state == stHam:
+	    if certLine == '-----END CERTIFICATE-----':
+		state = stDump
+	    else:
+		substrate = substrate + base64.b64decode(certLine)
+	if state == stDump:
+	    f.close()
+	    return get_bits(substrate)
+
+def get_key_bits_from_cert(cert):
+    return get_bits(cert.as_der())
