160 lines
6.3 KiB
Python
160 lines
6.3 KiB
Python
#
|
|
# Copyright (c) 2014-2015 Sylvain Peyrefitte
|
|
#
|
|
# This file is part of rdpy.
|
|
#
|
|
# rdpy is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
"""
|
|
@see: https://github.com/filippog/pyasn1/blob/master/examples/x509.py
|
|
"""
|
|
|
|
from pyasn1.type import tag, namedtype, namedval, univ, constraint, char, useful
|
|
from pyasn1.codec.ber import decoder
|
|
|
|
MAX = 64
|
|
|
|
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 X509Certificate(univ.Sequence):
|
|
componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('tbsCertificate', TBSCertificate()),
|
|
namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()),
|
|
namedtype.NamedType('signatureValue', univ.BitString())
|
|
)
|
|
|
|
class RSAPublicKey(univ.Sequence):
|
|
"""
|
|
@summary: asn1 public rsa key
|
|
@see: https://tools.ietf.org/html/rfc3447
|
|
"""
|
|
componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('modulus', univ.Integer()),
|
|
namedtype.NamedType('publicExponent', univ.Integer()),
|
|
)
|
|
|
|
def load(stream):
|
|
"""
|
|
@summary: load X509 certificate
|
|
@param stream: {str}
|
|
"""
|
|
return decoder.decode(stream, asn1Spec=X509Certificate())[0]
|
|
|
|
def extractRSAKey(certificate):
|
|
"""
|
|
@summary: try to extract rsa key
|
|
@return: (modulus, public exponent)
|
|
"""
|
|
#http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html
|
|
|
|
#extract binary data
|
|
l = 0L
|
|
for b in certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('subjectPublicKey'):
|
|
l = (l << 1) | b
|
|
|
|
rsaKey = decoder.decode(hex(l)[2:-1].decode('hex'), asn1Spec=RSAPublicKey())[0]
|
|
return rsaKey.getComponentByName('modulus')._value , rsaKey.getComponentByName('publicExponent')._value
|
|
|
|
|
|
|