diff --git a/scapy/asn1/asn1.py b/scapy/asn1/asn1.py
index 841ed901e7f51c084e922481500f2e426ac584bd..624a5e32434de8a6cba2cbea8778267370b0392e 100644
--- a/scapy/asn1/asn1.py
+++ b/scapy/asn1/asn1.py
@@ -1,6 +1,7 @@
 ## This file is part of Scapy
 ## See http://www.secdev.org/projects/scapy for more informations
 ## Copyright (C) Philippe Biondi <phil@secdev.org>
+## Modified by Maxence Tury <maxence.tury@ssi.gouv.fr>
 ## This program is published under a GPLv2 license
 
 """
@@ -8,10 +9,11 @@ ASN.1 (Abstract Syntax Notation One)
 """
 
 import random
+from datetime import datetime
 from scapy.config import conf
-from scapy.error import Scapy_Exception,warning
+from scapy.error import Scapy_Exception, warning
 from scapy.volatile import RandField
-from scapy.utils import Enum_metaclass, EnumElement
+from scapy.utils import Enum_metaclass, EnumElement, binrepr
 
 class RandASN1Object(RandField):
     def __init__(self, objlist=None):
@@ -153,27 +155,25 @@ class ASN1_Class_UNIVERSAL(ASN1_Class):
     EMBEDDED_PDF = 11
     UTF8_STRING = 12
     RELATIVE_OID = 13
-    SEQUENCE = 0x30#XXX 16 ??
-    SET = 0x31 #XXX 17 ??
+    SEQUENCE = 16|0x20          # constructed encoding
+    SET = 17|0x20               # constructed encoding
     NUMERIC_STRING = 18
     PRINTABLE_STRING = 19
-    T61_STRING = 20
+    T61_STRING = 20             # aka TELETEX_STRING
     VIDEOTEX_STRING = 21
     IA5_STRING = 22
     UTC_TIME = 23
     GENERALIZED_TIME = 24
     GRAPHIC_STRING = 25
-    ISO646_STRING = 26
+    ISO646_STRING = 26          # aka VISIBLE_STRING
     GENERAL_STRING = 27
     UNIVERSAL_STRING = 28
     CHAR_STRING = 29
     BMP_STRING = 30
-    IPADDRESS = 0x40
-    COUNTER32 = 0x41
-    GAUGE32 = 0x42
-    TIME_TICKS = 0x43
-    COUNTER64 = 0x46
-    SEP = 0x80
+    IPADDRESS = 0|0x40          # application-specific encoding
+    COUNTER32 = 1|0x40          # application-specific encoding
+    TIME_TICKS = 3|0x40         # application-specific encoding
+
 
 class ASN1_Object_metaclass(type):
     def __new__(cls, name, bases, dct):
@@ -184,7 +184,6 @@ class ASN1_Object_metaclass(type):
             warning("Error registering %r for %r" % (c.tag, c.codec))
         return c
 
-
 class ASN1_Object:
     __metaclass__ = ASN1_Object_metaclass
     tag = ASN1_Class_UNIVERSAL.ANY
@@ -205,6 +204,13 @@ class ASN1_Object:
     def __cmp__(self, other):
         return cmp(self.val, other)
 
+
+#######################
+####  ASN1 objects ####
+#######################
+
+# on the whole, we order the classes by ASN1_Class_UNIVERSAL tag value
+
 class ASN1_DECODING_ERROR(ASN1_Object):
     tag = ASN1_Class_UNIVERSAL.ERROR
     def __init__(self, val, exc=None):
@@ -230,61 +236,124 @@ class ASN1_BADTAG(ASN1_force):
 
 class ASN1_INTEGER(ASN1_Object):
     tag = ASN1_Class_UNIVERSAL.INTEGER
+    def __repr__(self):
+        h = hex(self.val)
+        if h[-1] == "L":
+            h = h[:-1]
+        # cut at 22 because with leading '0x', x509 serials should be < 23
+        if len(h) > 22:
+            h = h[:12] + "..." + h[-10:]
+        r = repr(self.val)
+        if len(r) > 20:
+            r = r[:10] + "..." + r[-10:]
+        return h + " <%s[%s]>" % (self.__dict__.get("name", self.__class__.__name__), r)
+
+class ASN1_BOOLEAN(ASN1_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.BOOLEAN
+    # BER: 0 means False, anything else means True
+    def __repr__(self):
+        return str((not (self.val==0))) + " " + ASN1_Object.__repr__(self)
+    
+class ASN1_BIT_STRING(ASN1_Object):
+    """
+    /!\ ASN1_BIT_STRING values are bit strings like "011101".
+    /!\ A zero-bit padded readable string is provided nonetheless.
+    """
+    tag = ASN1_Class_UNIVERSAL.BIT_STRING
+    def __init__(self, val, readable=False):
+        if readable:
+            self.val_readable = val
+            val = "".join(binrepr(ord(x)).zfill(8) for x in val)
+            self.unused_bits = 0
+        else:
+            if len(val) % 8 == 0:
+                self.unused_bits = 0
+            else:
+                self.unused_bits = 8 - len(val)%8
+            padded_val = val + "0"*self.unused_bits
+            bytes_arr = zip(*[iter(padded_val)]*8)
+            self.val_readable = "".join(chr(int("".join(x),2)) for x in bytes_arr)
+        ASN1_Object.__init__(self, val)
+    def __repr__(self):
+        if len(self.val) <= 16:
+            return "<%s[%r] (%d unused bit%s)>" % (self.__dict__.get("name", self.__class__.__name__), self.val, self.unused_bits, "s" if self.unused_bits>1 else "")
+        else:
+            s = self.val_readable
+            if len(s) > 20:
+                s = s[:10] + "..." + s[-10:]
+            return "<%s[%r] (%d unused bit%s)>" % (self.__dict__.get("name", self.__class__.__name__), s, self.unused_bits, "s" if self.unused_bits>1 else "")
 
 class ASN1_STRING(ASN1_Object):
     tag = ASN1_Class_UNIVERSAL.STRING
 
-class ASN1_BIT_STRING(ASN1_STRING):
-    tag = ASN1_Class_UNIVERSAL.BIT_STRING
+class ASN1_NULL(ASN1_Object):
+    tag = ASN1_Class_UNIVERSAL.NULL
+    def __repr__(self):
+        return ASN1_Object.__repr__(self)
 
-class ASN1_PRINTABLE_STRING(ASN1_STRING):
-    tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
+class ASN1_OID(ASN1_Object):
+    tag = ASN1_Class_UNIVERSAL.OID
+    def __init__(self, val):
+        val = conf.mib._oid(val)
+        ASN1_Object.__init__(self, val)
+        self.oidname = conf.mib._oidname(val)
+    def __repr__(self):
+        return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), self.oidname)
 
-class ASN1_T61_STRING(ASN1_STRING):
-    tag = ASN1_Class_UNIVERSAL.T61_STRING
+class ASN1_ENUMERATED(ASN1_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.ENUMERATED
 
-class ASN1_IA5_STRING(ASN1_STRING):
-    tag = ASN1_Class_UNIVERSAL.IA5_STRING
+class ASN1_UTF8_STRING(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.UTF8_STRING
 
 class ASN1_NUMERIC_STRING(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
 
+class ASN1_PRINTABLE_STRING(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
+
+class ASN1_T61_STRING(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.T61_STRING
+
 class ASN1_VIDEOTEX_STRING(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
 
-class ASN1_IPADDRESS(ASN1_STRING):
-    tag = ASN1_Class_UNIVERSAL.IPADDRESS
+class ASN1_IA5_STRING(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.IA5_STRING
 
 class ASN1_UTC_TIME(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.UTC_TIME
+    def __init__(self, val):
+        pretty_time = ""
+        if len(val) == 13 and val[-1] == "Z":
+            dt = datetime.strptime(val[:-1], "%y%m%d%H%M%S")
+            pretty_time = dt.strftime("%b %d %H:%M:%S %Y GMT")
+        self.pretty_time = pretty_time
+        ASN1_STRING.__init__(self, val)
+    def __repr__(self):
+        return self.pretty_time + " " + ASN1_STRING.__repr__(self)
 
 class ASN1_GENERALIZED_TIME(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
+    def __init__(self, val):
+        pretty_time = ""
+        if len(val) == 15 and val[-1] == "Z":
+            dt = datetime.strptime(val[:-1], "%Y%m%d%H%M%S")
+            pretty_time = dt.strftime("%b %d %H:%M:%S %Y GMT")
+        self.pretty_time = pretty_time
+        ASN1_STRING.__init__(self, val)
+    def __repr__(self):
+        return self.pretty_time + " " + ASN1_STRING.__repr__(self)
 
-class ASN1_TIME_TICKS(ASN1_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+class ASN1_ISO646_STRING(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.ISO646_STRING
 
-class ASN1_BOOLEAN(ASN1_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.BOOLEAN
+class ASN1_UNIVERSAL_STRING(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING
 
-class ASN1_ENUMERATED(ASN1_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.ENUMERATED
-    
-class ASN1_NULL(ASN1_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.NULL
+class ASN1_BMP_STRING(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.BMP_STRING
 
-class ASN1_SEP(ASN1_NULL):
-    tag = ASN1_Class_UNIVERSAL.SEP
-
-class ASN1_GAUGE32(ASN1_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.GAUGE32
-    
-class ASN1_COUNTER32(ASN1_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.COUNTER32
-    
-class ASN1_COUNTER64(ASN1_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.COUNTER64
-    
 class ASN1_SEQUENCE(ASN1_Object):
     tag = ASN1_Class_UNIVERSAL.SEQUENCE
     def strshow(self, lvl=0):
@@ -295,17 +364,15 @@ class ASN1_SEQUENCE(ASN1_Object):
     
 class ASN1_SET(ASN1_SEQUENCE):
     tag = ASN1_Class_UNIVERSAL.SET
-    
-class ASN1_OID(ASN1_Object):
-    tag = ASN1_Class_UNIVERSAL.OID
-    def __init__(self, val):
-        val = conf.mib._oid(val)
-        ASN1_Object.__init__(self, val)
-    def __repr__(self):
-        return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), conf.mib._oidname(self.val))
-    def __oidname__(self):
-        return '%s'%conf.mib._oidname(self.val)
-    
 
+class ASN1_IPADDRESS(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.IPADDRESS
+
+class ASN1_COUNTER32(ASN1_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.COUNTER32
+    
+class ASN1_TIME_TICKS(ASN1_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+   
 
 conf.ASN1_default_codec = ASN1_Codecs.BER
diff --git a/scapy/asn1/ber.py b/scapy/asn1/ber.py
index fe180e1cc2f517350f381c667807b35c3f080fb1..499cda61fe43bc2b59600413de70741bfe0cf51f 100644
--- a/scapy/asn1/ber.py
+++ b/scapy/asn1/ber.py
@@ -1,6 +1,8 @@
 ## This file is part of Scapy
 ## See http://www.secdev.org/projects/scapy for more informations
 ## Copyright (C) Philippe Biondi <phil@secdev.org>
+## Modified by Maxence Tury <maxence.tury@ssi.gouv.fr>
+## Acknowledgment: Ralph Broenink
 ## This program is published under a GPLv2 license
 
 """
@@ -8,7 +10,7 @@ Basic Encoding Rules (BER) for ASN.1
 """
 
 from scapy.error import warning
-from scapy.utils import inet_aton,inet_ntoa
+from scapy.utils import binrepr,inet_aton,inet_ntoa
 from asn1 import ASN1_Decoding_Error,ASN1_Encoding_Error,ASN1_BadTag_Decoding_Error,ASN1_Codecs,ASN1_Class_UNIVERSAL,ASN1_Error,ASN1_DECODING_ERROR,ASN1_BADTAG
 
 ##################
@@ -87,8 +89,7 @@ def BER_num_enc(l, size=1):
             l >>= 7
             size -= 1
         return "".join([chr(k) for k in x])
-def BER_num_dec(s):
-        x = 0
+def BER_num_dec(s, x=0):
         for i, c in enumerate(s):
             c = ord(c)
             x <<= 7
@@ -99,6 +100,43 @@ def BER_num_dec(s):
             raise BER_Decoding_Error("BER_num_dec: unfinished number description", remaining=s)
         return x, s[i+1:]
 
+# The function below provides low-tag and high-tag identifier partial support.
+# Class and primitive/constructed bit decoding is not supported yet.
+# For now Scapy considers this information to always be part of the identifier
+# e.g. we need BER_id_dec("\x30") to be 0x30 so that Scapy calls a SEQUENCE,
+# even though the real id is 0x10 once bit 6 (constructed) has been removed.
+def BER_id_dec(s):
+        x = ord(s[0])
+        if x & 0x1f != 0x1f:
+            return x,s[1:]
+        return BER_num_dec(s[1:], x&0xe0)
+
+# The functions below provide implicit and explicit tagging support.
+def BER_tagging_dec(s, hidden_tag=None, implicit_tag=None,
+                    explicit_tag=None, safe=False):
+    if len(s) > 0:
+        err_msg = "BER_tagging_dec: observed tag does not match expected tag"
+        if implicit_tag is not None:
+            ber_id,s = BER_id_dec(s)
+            if ber_id != implicit_tag:
+                if not safe:
+                    raise BER_Decoding_Error(err_msg, remaining=s)
+            s = chr(hidden_tag) + s
+        elif explicit_tag is not None:
+            ber_id,s = BER_id_dec(s)
+            if ber_id != explicit_tag:
+                if not safe:
+                    raise BER_Decoding_Error(err_msg, remaining=s)
+            l,s = BER_len_dec(s)
+    return s
+def BER_tagging_enc(s, implicit_tag=None, explicit_tag=None):
+    if len(s) > 0:
+        if implicit_tag is not None:
+            s = chr(implicit_tag) + s[1:]
+        elif explicit_tag is not None:
+            s = chr(explicit_tag) + BER_len_enc(len(s)) + s
+    return s
+
 #####[ BER classes ]#####
 
 class BERcodec_metaclass(type):
@@ -128,10 +166,11 @@ class BERcodec_Object:
     @classmethod
     def check_type(cls, s):
         cls.check_string(s)
-        if cls.tag != ord(s[0]):
+        tag, remainder = BER_id_dec(s)
+        if cls.tag != tag:
             raise BER_BadTag_Decoding_Error("%s: Got tag [%i/%#x] while expecting %r" %
-                                            (cls.__name__, ord(s[0]), ord(s[0]),cls.tag), remaining=s)
-        return s[1:]
+                                            (cls.__name__, tag, tag, cls.tag), remaining=s)
+        return remainder
     @classmethod
     def check_type_get_len(cls, s):
         s2 = cls.check_type(s)
@@ -152,7 +191,7 @@ class BERcodec_Object:
         if context is None:
             context = cls.tag.context
         cls.check_string(s)
-        p = ord(s[0])
+        p,_ = BER_id_dec(s)
         if p not in context:
             t = s
             if len(t) > 18:
@@ -187,11 +226,13 @@ class BERcodec_Object:
         else:
             return BERcodec_INTEGER.enc(int(s))
 
-            
-
 ASN1_Codecs.BER.register_stem(BERcodec_Object)
 
 
+##########################
+#### BERcodec objects ####
+##########################
+
 class BERcodec_INTEGER(BERcodec_Object):
     tag = ASN1_Class_UNIVERSAL.INTEGER
     @classmethod
@@ -223,12 +264,46 @@ class BERcodec_INTEGER(BERcodec_Object):
                 x |= ord(c)
         return cls.asn1_object(x),t
     
-
 class BERcodec_BOOLEAN(BERcodec_INTEGER):
     tag = ASN1_Class_UNIVERSAL.BOOLEAN
 
-class BERcodec_ENUMERATED(BERcodec_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.ENUMERATED
+class BERcodec_BIT_STRING(BERcodec_Object):
+    tag = ASN1_Class_UNIVERSAL.BIT_STRING
+    @classmethod
+    def do_dec(cls, s, context=None, safe=False):
+        # /!\ the unused_bits information is lost after this decoding
+        l,s,t = cls.check_type_check_len(s)
+        if len(s) > 0:
+            unused_bits = ord(s[0])
+            if safe and unused_bits > 7:
+                raise BER_Decoding_Error("BERcodec_BIT_STRING: too many unused_bits advertised", remaining=s)
+            s = "".join(binrepr(ord(x)).zfill(8) for x in s[1:])
+            if unused_bits > 0:
+                s = s[:-unused_bits]
+            return cls.tag.asn1_object(s),t
+        else:
+            raise BER_Decoding_Error("BERcodec_BIT_STRING found no content (not even unused_bits byte)", remaining=s)
+    @classmethod
+    def enc(cls,s):
+        # /!\ this is DER encoding (bit strings are only zero-bit padded)
+        if len(s) % 8 == 0:
+            unused_bits = 0
+        else:
+            unused_bits = 8 - len(s)%8
+            s += "0"*unused_bits
+        s = "".join(chr(int("".join(x),2)) for x in zip(*[iter(s)]*8))
+        s = chr(unused_bits) + s
+        return chr(cls.tag)+BER_len_enc(len(s))+s
+
+class BERcodec_STRING(BERcodec_Object):
+    tag = ASN1_Class_UNIVERSAL.STRING
+    @classmethod
+    def enc(cls,s):
+        return chr(cls.tag)+BER_len_enc(len(s))+s
+    @classmethod
+    def do_dec(cls, s, context=None, safe=False):
+        l,s,t = cls.check_type_check_len(s)
+        return cls.tag.asn1_object(s),t
 
 class BERcodec_NULL(BERcodec_INTEGER):
     tag = ASN1_Class_UNIVERSAL.NULL
@@ -237,23 +312,35 @@ class BERcodec_NULL(BERcodec_INTEGER):
         if i == 0:
             return chr(cls.tag)+"\0"
         else:
-            return BERcodec_INTEGER.enc(i)
-
-class BERcodec_SEP(BERcodec_NULL):
-    tag = ASN1_Class_UNIVERSAL.SEP
+            return super(cls,cls).enc(i)
 
-class BERcodec_STRING(BERcodec_Object):
-    tag = ASN1_Class_UNIVERSAL.STRING
+class BERcodec_OID(BERcodec_Object):
+    tag = ASN1_Class_UNIVERSAL.OID
     @classmethod
-    def enc(cls,s):
+    def enc(cls, oid):
+        lst = [int(x) for x in oid.strip(".").split(".")]
+        if len(lst) >= 2:
+            lst[1] += 40*lst[0]
+            del(lst[0])
+        s = "".join([BER_num_enc(k) for k in lst])
         return chr(cls.tag)+BER_len_enc(len(s))+s
     @classmethod
     def do_dec(cls, s, context=None, safe=False):
         l,s,t = cls.check_type_check_len(s)
-        return cls.tag.asn1_object(s),t
+        lst = []
+        while s:
+            l,s = BER_num_dec(s)
+            lst.append(l)
+        if (len(lst) > 0):
+            lst.insert(0,lst[0]/40)
+            lst[1] %= 40
+        return cls.asn1_object(".".join([str(k) for k in lst])), t
 
-class BERcodec_BIT_STRING(BERcodec_STRING):
-    tag = ASN1_Class_UNIVERSAL.BIT_STRING
+class BERcodec_ENUMERATED(BERcodec_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.ENUMERATED
+
+class BERcodec_UTF8_STRING(BERcodec_STRING):
+    tag = ASN1_Class_UNIVERSAL.UTF8_STRING
 
 class BERcodec_PRINTABLE_STRING(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
@@ -264,49 +351,20 @@ class BERcodec_T61_STRING (BERcodec_STRING):
 class BERcodec_IA5_STRING(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.IA5_STRING
 
-class BERcodec_NUMERIC_STRING(BERcodec_STRING):
-    tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
-
-class BERcodec_VIDEOTEX_STRING(BERcodec_STRING):
-    tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
-
-class BERcodec_IPADDRESS(BERcodec_STRING):
-    tag = ASN1_Class_UNIVERSAL.IPADDRESS
-    
-    @classmethod
-    def enc(cls, ipaddr_ascii):
-        try:
-            s = inet_aton(ipaddr_ascii)
-        except Exception:
-            raise BER_Encoding_Error("IPv4 address could not be encoded") 
-        return chr(cls.tag)+BER_len_enc(len(s))+s
-    
-    @classmethod
-    def do_dec(cls, s, context=None, safe=False):
-        l,s,t = cls.check_type_check_len(s)
-        try:
-            ipaddr_ascii = inet_ntoa(s)
-        except Exception:
-            raise BER_Decoding_Error("IP address could not be decoded", decoded=obj)
-        return cls.asn1_object(ipaddr_ascii), t
-
 class BERcodec_UTC_TIME(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.UTC_TIME
 
 class BERcodec_GENERALIZED_TIME(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
 
-class BERcodec_TIME_TICKS(BERcodec_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+class BERcodec_ISO646_STRING(BERcodec_STRING):
+    tag = ASN1_Class_UNIVERSAL.ISO646_STRING
 
-class BERcodec_GAUGE32(BERcodec_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.GAUGE32
+class BERcodec_UNIVERSAL_STRING(BERcodec_STRING):
+    tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING
 
-class BERcodec_COUNTER32(BERcodec_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.COUNTER32
-
-class BERcodec_COUNTER64(BERcodec_INTEGER):
-    tag = ASN1_Class_UNIVERSAL.COUNTER64
+class BERcodec_BMP_STRING (BERcodec_STRING):
+    tag = ASN1_Class_UNIVERSAL.BMP_STRING
 
 class BERcodec_SEQUENCE(BERcodec_Object):
     tag = ASN1_Class_UNIVERSAL.SEQUENCE
@@ -339,28 +397,29 @@ class BERcodec_SEQUENCE(BERcodec_Object):
 class BERcodec_SET(BERcodec_SEQUENCE):
     tag = ASN1_Class_UNIVERSAL.SET
 
-
-class BERcodec_OID(BERcodec_Object):
-    tag = ASN1_Class_UNIVERSAL.OID
-
+class BERcodec_IPADDRESS(BERcodec_STRING):
+    tag = ASN1_Class_UNIVERSAL.IPADDRESS
     @classmethod
-    def enc(cls, oid):
-        lst = [int(x) for x in oid.strip(".").split(".")]
-        if len(lst) >= 2:
-            lst[1] += 40*lst[0]
-            del(lst[0])
-        s = "".join([BER_num_enc(k) for k in lst])
+    def enc(cls, ipaddr_ascii):
+        try:
+            s = inet_aton(ipaddr_ascii)
+        except Exception:
+            raise BER_Encoding_Error("IPv4 address could not be encoded") 
         return chr(cls.tag)+BER_len_enc(len(s))+s
     @classmethod
     def do_dec(cls, s, context=None, safe=False):
         l,s,t = cls.check_type_check_len(s)
-        lst = []
-        while s:
-            l,s = BER_num_dec(s)
-            lst.append(l)
-        if (len(lst) > 0):
-            lst.insert(0,lst[0]/40)
-            lst[1] %= 40
-        return cls.asn1_object(".".join([str(k) for k in lst])), t
+        try:
+            ipaddr_ascii = inet_ntoa(s)
+        except Exception:
+            raise BER_Decoding_Error("IP address could not be decoded", decoded=obj)
+        return cls.asn1_object(ipaddr_ascii), t
+
+class BERcodec_COUNTER32(BERcodec_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.COUNTER32
+
+class BERcodec_TIME_TICKS(BERcodec_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+
 
 
diff --git a/scapy/asn1/mib.py b/scapy/asn1/mib.py
index cd0fa65ea1a287f5c23ebab81c90ea0b820de28d..c8065f00d62efb3493658fff38bbc32db8a765f3 100644
--- a/scapy/asn1/mib.py
+++ b/scapy/asn1/mib.py
@@ -1,6 +1,7 @@
 ## This file is part of Scapy
 ## See http://www.secdev.org/projects/scapy for more informations
 ## Copyright (C) Philippe Biondi <phil@secdev.org>
+## Modified by Maxence Tury <maxence.tury@ssi.gouv.fr>
 ## This program is published under a GPLv2 license
 
 """
@@ -143,5 +144,424 @@ def load_mib(filenames):
     conf.mib=newmib
 
 
+####################
+## OID references ##
+####################
 
-conf.mib = MIBDict(_name="MIB")
+####### pkcs1 #######
+
+pkcs1_oids = {
+        "rsaEncryption"                     : "1.2.840.113549.1.1.1",
+        "md2WithRSAEncryption"              : "1.2.840.113549.1.1.2",
+        "md4WithRSAEncryption"              : "1.2.840.113549.1.1.3",
+        "md5WithRSAEncryption"              : "1.2.840.113549.1.1.4",
+        "sha1-with-rsa-signature"           : "1.2.840.113549.1.1.5",
+        "rsaOAEPEncryptionSET"              : "1.2.840.113549.1.1.6",
+        "id-RSAES-OAEP"                     : "1.2.840.113549.1.1.7",
+        "id-mgf1"                           : "1.2.840.113549.1.1.8",
+        "id-pSpecified"                     : "1.2.840.113549.1.1.9",
+        "rsassa-pss"                        : "1.2.840.113549.1.1.10",
+        "sha256WithRSAEncryption"           : "1.2.840.113549.1.1.11",
+        "sha384WithRSAEncryption"           : "1.2.840.113549.1.1.12",
+        "sha512WithRSAEncryption"           : "1.2.840.113549.1.1.13",
+        "sha224WithRSAEncryption"           : "1.2.840.113549.1.1.14"
+        }
+
+####### pkcs9 #######
+
+pkcs9_oids = {
+        "modules"                           : "1.2.840.113549.1.9.0",
+        "emailAddress"                      : "1.2.840.113549.1.9.1",
+        "unstructuredName"                  : "1.2.840.113549.1.9.2",
+        "contentType"                       : "1.2.840.113549.1.9.3",
+        "messageDigest"                     : "1.2.840.113549.1.9.4",
+        "signing-time"                      : "1.2.840.113549.1.9.5",
+        "countersignature"                  : "1.2.840.113549.1.9.6",
+        "challengePassword"                 : "1.2.840.113549.1.9.7",
+        "unstructuredAddress"               : "1.2.840.113549.1.9.8",
+        "extendedCertificateAttributes"     : "1.2.840.113549.1.9.9",
+        "signingDescription"                : "1.2.840.113549.1.9.13",
+        "extensionRequest"                  : "1.2.840.113549.1.9.14",
+        "smimeCapabilities"                 : "1.2.840.113549.1.9.15",
+        "smime"                             : "1.2.840.113549.1.9.16",
+        "pgpKeyID"                          : "1.2.840.113549.1.9.17",
+        "friendlyName"                      : "1.2.840.113549.1.9.20",
+        "localKeyID"                        : "1.2.840.113549.1.9.21",
+        "certTypes"                         : "1.2.840.113549.1.9.22",
+        "crlTypes"                          : "1.2.840.113549.1.9.23",
+        "pkcs-9-oc"                         : "1.2.840.113549.1.9.24",
+        "pkcs-9-at"                         : "1.2.840.113549.1.9.25",
+        "pkcs-9-sx"                         : "1.2.840.113549.1.9.26",
+        "pkcs-9-mr"                         : "1.2.840.113549.1.9.27",
+        "id-aa-CMSAlgorithmProtection"      : "1.2.840.113549.1.9.52"
+        }
+
+####### x509 #######
+
+attributeType_oids = {
+        "objectClass"                       : "2.5.4.0",
+        "aliasedEntryName"                  : "2.5.4.1",
+        "knowledgeInformation"              : "2.5.4.2",
+        "commonName"                        : "2.5.4.3",
+        "surname"                           : "2.5.4.4",
+        "serialNumber"                      : "2.5.4.5",
+        "countryName"                       : "2.5.4.6",
+        "localityName"                      : "2.5.4.7",
+        "stateOrProvinceName"               : "2.5.4.8",
+        "streetAddress"                     : "2.5.4.9",
+        "organizationName"                  : "2.5.4.10",
+        "organizationUnitName"              : "2.5.4.11",
+        "title"                             : "2.5.4.12",
+        "description"                       : "2.5.4.13",
+        "searchGuide"                       : "2.5.4.14",
+        "businessCategory"                  : "2.5.4.15",
+        "postalAddress"                     : "2.5.4.16",
+        "postalCode"                        : "2.5.4.17",
+        "postOfficeBox"                     : "2.5.4.18",
+        "physicalDeliveryOfficeName"        : "2.5.4.19",
+        "telephoneNumber"                   : "2.5.4.20",
+        "telexNumber"                       : "2.5.4.21",
+        "teletexTerminalIdentifier"         : "2.5.4.22",
+        "facsimileTelephoneNumber"          : "2.5.4.23",
+        "x121Address"                       : "2.5.4.24",
+        "internationalISDNNumber"           : "2.5.4.25",
+        "registeredAddress"                 : "2.5.4.26",
+        "destinationIndicator"              : "2.5.4.27",
+        "preferredDeliveryMethod"           : "2.5.4.28",
+        "presentationAddress"               : "2.5.4.29",
+        "supportedApplicationContext"       : "2.5.4.30",
+        "member"                            : "2.5.4.31",
+        "owner"                             : "2.5.4.32",
+        "roleOccupant"                      : "2.5.4.33",
+        "seeAlso"                           : "2.5.4.34",
+        "userPassword"                      : "2.5.4.35",
+        "userCertificate"                   : "2.5.4.36",
+        "cACertificate"                     : "2.5.4.37",
+        "authorityRevocationList"           : "2.5.4.38",
+        "certificateRevocationList"         : "2.5.4.39",
+        "crossCertificatePair"              : "2.5.4.40",
+        "name"                              : "2.5.4.41",
+        "givenName"                         : "2.5.4.42",
+        "initials"                          : "2.5.4.43",
+        "generationQualifier"               : "2.5.4.44",
+        "uniqueIdentifier"                  : "2.5.4.45",
+        "dnQualifier"                       : "2.5.4.46",
+        "enhancedSearchGuide"               : "2.5.4.47",
+        "protocolInformation"               : "2.5.4.48",
+        "distinguishedName"                 : "2.5.4.49",
+        "uniqueMember"                      : "2.5.4.50",
+        "houseIdentifier"                   : "2.5.4.51",
+        "supportedAlgorithms"               : "2.5.4.52",
+        "deltaRevocationList"               : "2.5.4.53",
+        "dmdName"                           : "2.5.4.54",
+        "clearance"                         : "2.5.4.55",
+        "defaultDirQop"                     : "2.5.4.56",
+        "attributeIntegrityInfo"            : "2.5.4.57",
+        "attributeCertificate"              : "2.5.4.58",
+        "attributeCertificateRevocationList": "2.5.4.59",
+        "confKeyInfo"                       : "2.5.4.60",
+        "aACertificate"                     : "2.5.4.61",
+        "attributeDescriptorCertificate"    : "2.5.4.62",
+        "attributeAuthorityRevocationList"  : "2.5.4.63",
+        "family-information"                : "2.5.4.64",
+        "pseudonym"                         : "2.5.4.65",
+        "communicationsService"             : "2.5.4.66",
+        "communicationsNetwork"             : "2.5.4.67",
+        "certificationPracticeStmt"         : "2.5.4.68",
+        "certificatePolicy"                 : "2.5.4.69",
+        "pkiPath"                           : "2.5.4.70",
+        "privPolicy"                        : "2.5.4.71",
+        "role"                              : "2.5.4.72",
+        "delegationPath"                    : "2.5.4.73",
+        "protPrivPolicy"                    : "2.5.4.74",
+        "xMLPrivilegeInfo"                  : "2.5.4.75",
+        "xmlPrivPolicy"                     : "2.5.4.76",
+        "uuidpair"                          : "2.5.4.77",
+        "tagOid"                            : "2.5.4.78",
+        "uiiFormat"                         : "2.5.4.79",
+        "uiiInUrh"                          : "2.5.4.80",
+        "contentUrl"                        : "2.5.4.81",
+        "permission"                        : "2.5.4.82",
+        "uri"                               : "2.5.4.83",
+        "pwdAttribute"                      : "2.5.4.84",
+        "userPwd"                           : "2.5.4.85",
+        "urn"                               : "2.5.4.86",
+        "url"                               : "2.5.4.87",
+        "utmCoordinates"                    : "2.5.4.88",
+        "urnC"                              : "2.5.4.89",
+        "uii"                               : "2.5.4.90",
+        "epc"                               : "2.5.4.91",
+        "tagAfi"                            : "2.5.4.92",
+        "epcFormat"                         : "2.5.4.93",
+        "epcInUrn"                          : "2.5.4.94",
+        "ldapUrl"                           : "2.5.4.95",
+        "ldapUrl"                           : "2.5.4.96",
+        "organizationIdentifier"            : "2.5.4.97"
+        }
+
+certificateExtension_oids = {
+        "authorityKeyIdentifier"            : "2.5.29.1",
+        "keyAttributes"                     : "2.5.29.2",
+        "certificatePolicies"               : "2.5.29.3",
+        "keyUsageRestriction"               : "2.5.29.4",
+        "policyMapping"                     : "2.5.29.5",
+        "subtreesConstraint"                : "2.5.29.6",
+        "subjectAltName"                    : "2.5.29.7",
+        "issuerAltName"                     : "2.5.29.8",
+        "subjectDirectoryAttributes"        : "2.5.29.9",
+        "basicConstraints"                  : "2.5.29.10",
+        "subjectKeyIdentifier"              : "2.5.29.14",
+        "keyUsage"                          : "2.5.29.15",
+        "privateKeyUsagePeriod"             : "2.5.29.16",
+        "subjectAltName"                    : "2.5.29.17",
+        "issuerAltName"                     : "2.5.29.18",
+        "basicConstraints"                  : "2.5.29.19",
+        "cRLNumber"                         : "2.5.29.20",
+        "reasonCode"                        : "2.5.29.21",
+        "expirationDate"                    : "2.5.29.22",
+        "instructionCode"                   : "2.5.29.23",
+        "invalidityDate"                    : "2.5.29.24",
+        "cRLDistributionPoints"             : "2.5.29.25",
+        "issuingDistributionPoint"          : "2.5.29.26",
+        "deltaCRLIndicator"                 : "2.5.29.27",
+        "issuingDistributionPoint"          : "2.5.29.28",
+        "certificateIssuer"                 : "2.5.29.29",
+        "nameConstraints"                   : "2.5.29.30",
+        "cRLDistributionPoints"             : "2.5.29.31",
+        "certificatePolicies"               : "2.5.29.32",
+        "policyMappings"                    : "2.5.29.33",
+        "policyConstraints"                 : "2.5.29.34",
+        "authorityKeyIdentifier"            : "2.5.29.35",
+        "policyConstraints"                 : "2.5.29.36",
+        "extKeyUsage"                       : "2.5.29.37",
+        "authorityAttributeIdentifier"      : "2.5.29.38",
+        "roleSpecCertIdentifier"            : "2.5.29.39",
+        "cRLStreamIdentifier"               : "2.5.29.40",
+        "basicAttConstraints"               : "2.5.29.41",
+        "delegatedNameConstraints"          : "2.5.29.42",
+        "timeSpecification"                 : "2.5.29.43",
+        "cRLScope"                          : "2.5.29.44",
+        "statusReferrals"                   : "2.5.29.45",
+        "freshestCRL"                       : "2.5.29.46",
+        "orderedList"                       : "2.5.29.47",
+        "attributeDescriptor"               : "2.5.29.48",
+        "userNotice"                        : "2.5.29.49",
+        "sOAIdentifier"                     : "2.5.29.50",
+        "baseUpdateTime"                    : "2.5.29.51",
+        "acceptableCertPolicies"            : "2.5.29.52",
+        "deltaInfo"                         : "2.5.29.53",
+        "inhibitAnyPolicy"                  : "2.5.29.54",
+        "targetInformation"                 : "2.5.29.55",
+        "noRevAvail"                        : "2.5.29.56",
+        "acceptablePrivilegePolicies"       : "2.5.29.57",
+        "id-ce-toBeRevoked"                 : "2.5.29.58",
+        "id-ce-RevokedGroups"               : "2.5.29.59",
+        "id-ce-expiredCertsOnCRL"           : "2.5.29.60",
+        "indirectIssuer"                    : "2.5.29.61",
+        "id-ce-noAssertion"                 : "2.5.29.62",
+        "id-ce-aAissuingDistributionPoint"  : "2.5.29.63",
+        "id-ce-issuedOnBehaIFOF"            : "2.5.29.64",
+        "id-ce-singleUse"                   : "2.5.29.65",
+        "id-ce-groupAC"                     : "2.5.29.66",
+        "id-ce-allowedAttAss"               : "2.5.29.67",
+        "id-ce-attributeMappings"           : "2.5.29.68",
+        "id-ce-holderNameConstraints"       : "2.5.29.69"
+        }
+
+certExt_oids = {
+        "cert-type"                 : "2.16.840.1.113730.1.1",
+        "base-url"                  : "2.16.840.1.113730.1.2",
+        "revocation-url"            : "2.16.840.1.113730.1.3",
+        "ca-revocation-url"         : "2.16.840.1.113730.1.4",
+        "ca-crl-url"                : "2.16.840.1.113730.1.5",
+        "ca-cert-url"               : "2.16.840.1.113730.1.6",
+        "renewal-url"               : "2.16.840.1.113730.1.7",
+        "ca-policy-url"             : "2.16.840.1.113730.1.8",
+        "homepage-url"              : "2.16.840.1.113730.1.9",
+        "entity-logo"               : "2.16.840.1.113730.1.10",
+        "user-picture"              : "2.16.840.1.113730.1.11",
+        "ssl-server-name"           : "2.16.840.1.113730.1.12",
+        "comment"                   : "2.16.840.1.113730.1.13",
+        "lost-password-url"         : "2.16.840.1.113730.1.14",
+        "cert-renewal-time"         : "2.16.840.1.113730.1.15",
+        "aia"                       : "2.16.840.1.113730.1.16",
+        "cert-scope-of-use"         : "2.16.840.1.113730.1.17",
+        }
+
+certPkixPe_oids = {
+        "authorityInfoAccess"       : "1.3.6.1.5.5.7.1.1",
+        "biometricInfo"             : "1.3.6.1.5.5.7.1.2",
+        "qcStatements"              : "1.3.6.1.5.5.7.1.3",
+        "auditIdentity"             : "1.3.6.1.5.5.7.1.4",
+        "aaControls"                : "1.3.6.1.5.5.7.1.6",
+        "proxying"                  : "1.3.6.1.5.5.7.1.10",
+        "subjectInfoAccess"         : "1.3.6.1.5.5.7.1.11"
+        }
+
+certPkixQt_oids = {
+        "cps"                       : "1.3.6.1.5.5.7.2.1",
+        "unotice"                   : "1.3.6.1.5.5.7.2.2"
+        }
+
+certPkixKp_oids = {
+        "serverAuth"                : "1.3.6.1.5.5.7.3.1",
+        "clientAuth"                : "1.3.6.1.5.5.7.3.2",
+        "codeSigning"               : "1.3.6.1.5.5.7.3.3",
+        "emailProtection"           : "1.3.6.1.5.5.7.3.4",
+        "ipsecEndSystem"            : "1.3.6.1.5.5.7.3.5",
+        "ipsecTunnel"               : "1.3.6.1.5.5.7.3.6",
+        "ipsecUser"                 : "1.3.6.1.5.5.7.3.7",
+        "timeStamping"              : "1.3.6.1.5.5.7.3.8",
+        "ocspSigning"               : "1.3.6.1.5.5.7.3.9",
+        "dvcs"                      : "1.3.6.1.5.5.7.3.10",
+        "secureShellClient"         : "1.3.6.1.5.5.7.3.21",
+        "secureShellServer"         : "1.3.6.1.5.5.7.3.22"
+        }
+
+certPkixAd_oids = {
+        "ocsp"                          : "1.3.6.1.5.5.7.48.1",
+        "caIssuers"                     : "1.3.6.1.5.5.7.48.2",
+        "timestamping"                  : "1.3.6.1.5.5.7.48.3",
+        "id-ad-dvcs"                    : "1.3.6.1.5.5.7.48.4",
+        "id-ad-caRepository"            : "1.3.6.1.5.5.7.48.5",
+        "id-pkix-ocsp-archive-cutoff"   : "1.3.6.1.5.5.7.48.6",
+        "id-pkix-ocsp-service-locator"  : "1.3.6.1.5.5.7.48.7",
+        "id-ad-cmc"                     : "1.3.6.1.5.5.7.48.12"
+        }
+
+####### ansi-x962 #######
+
+x962KeyType_oids = {
+        "prime-field"               : "1.2.840.10045.1.1",
+        "characteristic-two-field"  : "1.2.840.10045.1.2",
+        "ecPublicKey"               : "1.2.840.10045.2.1",
+        }
+
+x962Signature_oids = {
+        "ecdsa-with-SHA1"           : "1.2.840.10045.4.1",
+        "ecdsa-with-Recommended"    : "1.2.840.10045.4.2",
+        "ecdsa-with-SHA224"         : "1.2.840.10045.4.3.1",
+        "ecdsa-with-SHA256"         : "1.2.840.10045.4.3.2",
+        "ecdsa-with-SHA384"         : "1.2.840.10045.4.3.3",
+        "ecdsa-with-SHA512"         : "1.2.840.10045.4.3.4"
+        }
+
+####### elliptic curves #######
+
+certicomCurve_oids = {
+        "ansit163k1"                : "1.3.132.0.1",
+        "ansit163r1"                : "1.3.132.0.2",
+        "ansit239k1"                : "1.3.132.0.3",
+        "sect113r1"                 : "1.3.132.0.4",
+        "sect113r2"                 : "1.3.132.0.5",
+        "secp112r1"                 : "1.3.132.0.6",
+        "secp112r2"                 : "1.3.132.0.7",
+        "ansip160r1"                : "1.3.132.0.8",
+        "ansip160k1"                : "1.3.132.0.9",
+        "ansip256k1"                : "1.3.132.0.10",
+        "ansit163r2"                : "1.3.132.0.15",
+        "ansit283k1"                : "1.3.132.0.16",
+        "ansit283r1"                : "1.3.132.0.17",
+        "sect131r1"                 : "1.3.132.0.22",
+        "ansit193r1"                : "1.3.132.0.24",
+        "ansit193r2"                : "1.3.132.0.25",
+        "ansit233k1"                : "1.3.132.0.26",
+        "ansit233r1"                : "1.3.132.0.27",
+        "secp128r1"                 : "1.3.132.0.28",
+        "secp128r2"                 : "1.3.132.0.29",
+        "ansip160r2"                : "1.3.132.0.30",
+        "ansip192k1"                : "1.3.132.0.31",
+        "ansip224k1"                : "1.3.132.0.32",
+        "ansip224r1"                : "1.3.132.0.33",
+        "ansip384r1"                : "1.3.132.0.34",
+        "ansip521r1"                : "1.3.132.0.35",
+        "ansit409k1"                : "1.3.132.0.36",
+        "ansit409r1"                : "1.3.132.0.37",
+        "ansit571k1"                : "1.3.132.0.38",
+        "ansit571r1"                : "1.3.132.0.39"
+        }
+
+####### policies #######
+
+certPolicy_oids = {
+        "anyPolicy"                 : "2.5.29.32.0"
+        }
+
+# from Chromium source code (ev_root_ca_metadata.cc)
+evPolicy_oids = {
+        "EV AC Camerfirma S.A. Chambers of Commerce Root - 2008"            : "1.3.6.1.4.1.17326.10.14.2.1.2",
+        "EV AC Camerfirma S.A. Chambers of Commerce Root - 2008"            : "1.3.6.1.4.1.17326.10.14.2.2.2",
+        "EV AC Camerfirma S.A. Global Chambersign Root - 2008"              : "1.3.6.1.4.1.17326.10.8.12.1.2",
+        "EV AC Camerfirma S.A. Global Chambersign Root - 2008"              : "1.3.6.1.4.1.17326.10.8.12.2.2",
+        "EV AddTrust/Comodo/USERTrust"                                      : "1.3.6.1.4.1.6449.1.2.1.5.1",
+        "EV AddTrust External CA Root"                                      : "1.3.6.1.4.1.782.1.2.1.8.1",
+        "EV Actualis Authentication Root CA"                                : "1.3.159.1.17.1",
+        "EV AffirmTrust Commercial"                                         : "1.3.6.1.4.1.34697.2.1",
+        "EV AffirmTrust Networking"                                         : "1.3.6.1.4.1.34697.2.2",
+        "EV AffirmTrust Premium"                                            : "1.3.6.1.4.1.34697.2.3",
+        "EV AffirmTrust Premium ECC"                                        : "1.3.6.1.4.1.34697.2.4",
+        "EV Autoridad de Certificacion Firmaprofesional CIF A62634068"      : "1.3.6.1.4.1.13177.10.1.3.10",
+        "EV Baltimore CyberTrust Root"                                      : "1.3.6.1.4.1.6334.1.100.1",
+        "EV Buypass Class 3"                                                : "2.16.578.1.26.1.3.3",
+        "EV Certificate Authority of WoSign"                                : "1.3.6.1.4.1.36305.2",
+        "EV CertPlus Class 2 Primary CA (KEYNECTIS)"                        : "1.3.6.1.4.1.22234.2.5.2.3.1",
+        "EV Certum Trusted Network CA"                                      : "1.2.616.1.113527.2.5.1.1",
+        "EV China Internet Network Information Center EV Certificates Root" : "1.3.6.1.4.1.29836.1.10",
+        "EV Cybertrust Global Root"                                         : "1.3.6.1.4.1.6334.1.100.1",
+        "EV DigiCert High Assurance EV Root CA"                             : "2.16.840.1.114412.2.1",
+        "EV D-TRUST Root Class 3 CA 2 EV 2009"                              : "1.3.6.1.4.1.4788.2.202.1",
+        "EV Entrust Certification Authority"                                : "2.16.840.1.114028.10.1.2",
+        "EV Equifax Secure Certificate Authority (GeoTrust)"                : "1.3.6.1.4.1.14370.1.6",
+        "EV E-Tugra Certification Authority"                                : "2.16.792.3.0.4.1.1.4",
+        "EV GeoTrust Primary Certification Authority"                       : "1.3.6.1.4.1.14370.1.6",
+        "EV GlobalSign Root CAs"                                            : "1.3.6.1.4.1.4146.1.1",
+        "EV Go Daddy Certification Authority"                               : "2.16.840.1.114413.1.7.23.3",
+        "EV Izenpe.com roots Business"                                      : "1.3.6.1.4.1.14777.6.1.1",
+        "EV Izenpe.com roots Government"                                    : "1.3.6.1.4.1.14777.6.1.2",
+        "EV Network Solutions Certificate Authority"                        : "1.3.6.1.4.1.781.1.2.1.8.1",
+        "EV QuoVadis Roots"                                                 : "1.3.6.1.4.1.8024.0.2.100.1.2",
+        "EV SecureTrust Corporation Roots"                                  : "2.16.840.1.114404.1.1.2.4.1",
+        "EV Security Communication RootCA1"                                 : "1.2.392.200091.100.721.1",
+        "EV Staat der Nederlanden EV Root CA"                               : "2.16.528.1.1003.1.2.7",
+        "EV StartCom Certification Authority"                               : "1.3.6.1.4.1.23223.1.1.1",
+        "EV Starfield Certificate Authority"                                : "2.16.840.1.114414.1.7.23.3",
+        "EV Starfield Service Certificate Authority"                        : "2.16.840.1.114414.1.7.24.3",
+        "EV SwissSign Gold CA - G2"                                         : "2.16.756.1.89.1.2.1.1",
+        "EV Swisscom Root EV CA 2"                                          : "2.16.756.1.83.21.0",
+        "EV thawte CAs"                                                     : "2.16.840.1.113733.1.7.48.1",
+        "EV TWCA Roots"                                                     : "1.3.6.1.4.1.40869.1.1.22.3",
+        "EV T-Telessec GlobalRoot Class 3"                                  : "1.3.6.1.4.1.7879.13.24.1",
+        "EV USERTrust Certification Authorities"                            : "1.3.6.1.4.1.6449.1.2.1.5.1",
+        "EV ValiCert Class 2 Policy Validation Authority"                   : "2.16.840.1.114413.1.7.23.3",
+        "EV VeriSign Certification Authorities"                             : "2.16.840.1.113733.1.7.23.6",
+        "EV Wells Fargo WellsSecure Public Root Certification Authority"    : "2.16.840.1.114171.500.9",
+        "EV XRamp Global Certification Authority"                           : "2.16.840.1.114404.1.1.2.4.1",
+        "jurisdictionOfIncorporationLocalityName"                           : "1.3.6.1.4.1.311.60.2.1.1",
+        "jurisdictionOfIncorporationStateOrProvinceName"                    : "1.3.6.1.4.1.311.60.2.1.2",
+        "jurisdictionOfIncorporationCountryName"                            : "1.3.6.1.4.1.311.60.2.1.3"
+        }
+
+
+x509_oids_sets = [
+                 pkcs1_oids,
+                 pkcs9_oids,
+                 attributeType_oids,
+                 certificateExtension_oids,
+                 certExt_oids,
+                 certPkixPe_oids,
+                 certPkixQt_oids,
+                 certPkixKp_oids,
+                 certPkixAd_oids,
+                 certPolicy_oids,
+                 evPolicy_oids,
+                 x962KeyType_oids,
+                 x962Signature_oids,
+                 certicomCurve_oids
+                 ]
+
+x509_oids = {}
+
+for oids_set in x509_oids_sets:
+    x509_oids.update(oids_set)
+
+conf.mib = MIBDict(_name="MIB", **x509_oids)
diff --git a/scapy/asn1fields.py b/scapy/asn1fields.py
index 1a59bd50d757db44e254a9ff7c8d3b74d5b62aff..0994e4a9afcd870cbf1856e31d980ac72f5e5294 100644
--- a/scapy/asn1fields.py
+++ b/scapy/asn1fields.py
@@ -1,6 +1,7 @@
 ## This file is part of Scapy
 ## See http://www.secdev.org/projects/scapy for more informations
 ## Copyright (C) Philippe Biondi <phil@secdev.org>
+## Enhanced by Maxence Tury <maxence.tury@ssi.gouv.fr>
 ## This program is published under a GPLv2 license
 
 """
@@ -9,51 +10,48 @@ Classes that implement ASN.1 data structures.
 
 from asn1.asn1 import *
 from asn1.ber import *
+from asn1.mib import *
 from volatile import *
 from base_classes import BasePacket
+from utils import binrepr
 
-
-#####################
-#### ASN1 Fields ####
-#####################
+FLEXIBLE_TAGS = False
 
 class ASN1F_badsequence(Exception):
     pass
 
-class ASN1F_element:
+class ASN1F_element(object):
     pass
 
-class ASN1F_optionnal(ASN1F_element):
-    def __init__(self, field):
-        self._field=field
-    def __getattr__(self, attr):
-        return getattr(self._field,attr)
-    def dissect(self,pkt,s):
-        try:
-            return self._field.dissect(pkt,s)
-        except ASN1F_badsequence:
-            self._field.set_val(pkt,None)
-            return s
-        except BER_Decoding_Error:
-            self._field.set_val(pkt,None)
-            return s
-    def build(self, pkt):
-        if self._field.is_empty(pkt):
-            return ""
-        return self._field.build(pkt)
 
-class ASN1F_field(ASN1F_element):
-    holds_packets=0
-    islist=0
+##########################
+#### Basic ASN1 Field ####
+##########################
 
+class ASN1F_field(ASN1F_element):
+    holds_packets = 0
+    islist = 0
     ASN1_tag = ASN1_Class_UNIVERSAL.ANY
-    context=ASN1_Class_UNIVERSAL
+    context = ASN1_Class_UNIVERSAL
     
-    def __init__(self, name, default, context=None):
-        if context is not None:
-            self.context = context
+    def __init__(self, name, default, context=None,
+                 implicit_tag=None, explicit_tag=None):
+        self.context = context
         self.name = name
-        self.default = default
+        if default is None:
+            self.default = None
+        elif type(default) is ASN1_NULL:
+            self.default = default
+        else:
+            self.default = self.ASN1_tag.asn1_object(default)
+        self.flexible_tag = False or FLEXIBLE_TAGS
+        if (implicit_tag is not None) and (explicit_tag is not None):
+            err_msg = "field cannot be both implicitly and explicitly tagged"
+            raise ASN1_Error(err_msg)
+        self.implicit_tag = implicit_tag
+        self.explicit_tag = explicit_tag
+        # network_tag gets useful for ASN1F_CHOICE
+        self.network_tag = implicit_tag or explicit_tag or self.ASN1_tag
 
     def i2repr(self, pkt, x):
         return repr(x)
@@ -61,20 +59,65 @@ class ASN1F_field(ASN1F_element):
         return x
     def any2i(self, pkt, x):
         return x
-    def m2i(self, pkt, x):
-        return self.ASN1_tag.get_codec(pkt.ASN1_codec).safedec(x, context=self.context)
+    def m2i(self, pkt, s):
+        """
+        The good thing about safedec is that it may still decode ASN1
+        even if there is a mismatch between the expected tag (self.ASN1_tag)
+        and the actual tag; the decoded ASN1 object will simply be put
+        into an ASN1_BADTAG object. However, safedec prevents the raising of
+        exceptions needed for ASN1F_optional processing.
+        Thus we use 'flexible_tag', which should be False with ASN1F_optional.
+
+        Regarding other fields, we might need to know whether encoding went
+        as expected or not. Noticeably, input methods from cert.py expect
+        certain exceptions to be raised. Hence default flexible_tag is False,
+        but we provide a FLEXIBLE_TAGS switch for debugging purposes.
+        """
+        s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,
+                            implicit_tag=self.implicit_tag,
+                            explicit_tag=self.explicit_tag,
+                            safe=self.flexible_tag)
+        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
+        if self.flexible_tag:
+            return codec.safedec(s, context=self.context)
+        else:
+            return codec.dec(s, context=self.context)
     def i2m(self, pkt, x):
         if x is None:
-            x = 0
+            return ""
         if isinstance(x, ASN1_Object):
             if ( self.ASN1_tag == ASN1_Class_UNIVERSAL.ANY
                  or x.tag == ASN1_Class_UNIVERSAL.RAW
                  or x.tag == ASN1_Class_UNIVERSAL.ERROR
                  or self.ASN1_tag == x.tag ):
-                return x.enc(pkt.ASN1_codec)
+                s = x.enc(pkt.ASN1_codec)
             else:
                 raise ASN1_Error("Encoding Error: got %r instead of an %r for field [%s]" % (x, self.ASN1_tag, self.name))
-        return self.ASN1_tag.get_codec(pkt.ASN1_codec).enc(x)
+        else:
+            s = self.ASN1_tag.get_codec(pkt.ASN1_codec).enc(x)
+        return BER_tagging_enc(s, implicit_tag=self.implicit_tag,
+                               explicit_tag=self.explicit_tag)
+    def extract_packet(self, cls, s):
+        if len(s) > 0:
+            try:
+                c = cls(s)
+            except ASN1F_badsequence:
+                c = packet.Raw(s)
+            cpad = c.getlayer(packet.Raw)
+            s = ""
+            if cpad is not None:
+                s = cpad.load
+                del(cpad.underlayer.payload)
+            return c,s
+        else:
+            return None,s
+ 
+    def build(self, pkt):
+        return self.i2m(pkt, getattr(pkt, self.name))
+    def dissect(self, pkt, s):
+        v,s = self.m2i(pkt, s)
+        self.set_val(pkt, v)
+        return s
 
     def do_copy(self, x):
         if hasattr(x, "copy"):
@@ -85,54 +128,41 @@ class ASN1F_field(ASN1F_element):
                 if isinstance(x[i], BasePacket):
                     x[i] = x[i].copy()
         return x
-
-    def build(self, pkt):
-        return self.i2m(pkt, getattr(pkt, self.name))
-
     def set_val(self, pkt, val):
         setattr(pkt, self.name, val)
     def is_empty(self, pkt):
-        return getattr(pkt,self.name) is None
-    
-    def dissect(self, pkt, s):
-        v,s = self.m2i(pkt, s)
-        self.set_val(pkt, v)
-        return s
-
+        return getattr(pkt, self.name) is None
     def get_fields_list(self):
         return [self]
-
+    
     def __hash__(self):
         return hash(self.name)
     def __str__(self):
-        return self.name
-    def __eq__(self, other):
-        return self.name == other
-    def __repr__(self):
-        return self.name
+        return repr(self)
     def randval(self):
         return RandInt()
 
 
-class ASN1F_INTEGER(ASN1F_field):
-    ASN1_tag= ASN1_Class_UNIVERSAL.INTEGER
-    def randval(self):
-        return RandNum(-2**64, 2**64-1)
+############################
+#### Simple ASN1 Fields ####
+############################
 
 class ASN1F_BOOLEAN(ASN1F_field):
-    ASN1_tag= ASN1_Class_UNIVERSAL.BOOLEAN
+    ASN1_tag = ASN1_Class_UNIVERSAL.BOOLEAN
     def randval(self):
-        return RandChoice(True,False)
+        return RandChoice(True, False)
 
-class ASN1F_NULL(ASN1F_INTEGER):
-    ASN1_tag= ASN1_Class_UNIVERSAL.NULL
-
-class ASN1F_SEP(ASN1F_NULL):
-    ASN1_tag= ASN1_Class_UNIVERSAL.SEP
+class ASN1F_INTEGER(ASN1F_field):
+    ASN1_tag = ASN1_Class_UNIVERSAL.INTEGER
+    def randval(self):
+        return RandNum(-2**64, 2**64-1)
 
 class ASN1F_enum_INTEGER(ASN1F_INTEGER):
-    def __init__(self, name, default, enum):
-        ASN1F_INTEGER.__init__(self, name, default)
+    def __init__(self, name, default, enum, context=None,
+                 implicit_tag=None, explicit_tag=None):
+        ASN1F_INTEGER.__init__(self, name, default, context=context,
+                               implicit_tag=implicit_tag,
+                               explicit_tag=explicit_tag)
         i2s = self.i2s = {}
         s2i = self.s2i = {}
         if type(enum) is list:
@@ -148,62 +178,96 @@ class ASN1F_enum_INTEGER(ASN1F_INTEGER):
         if type(x) is str:
             x = self.s2i[x]
         return x
-    def i2repr_one(self, pkt, x):
-        return self.i2s.get(x, repr(x))
-    
     def any2i(self, pkt, x):
         if type(x) is list:
             return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
         else:
-            return self.any2i_one(pkt,x)        
+            return self.any2i_one(pkt, x)        
+    def i2repr_one(self, pkt, x):
+        if x is not None:
+            r = self.i2s.get(x)
+            if r:
+                return r + " " + repr(x)
+        return repr(x)
     def i2repr(self, pkt, x):
         if type(x) is list:
-            return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
+            return map(lambda z,pkt=pkt:self.i2repr_one(pkt, z), x)
         else:
-            return self.i2repr_one(pkt,x)
-
-class ASN1F_ENUMERATED(ASN1F_enum_INTEGER):
-    ASN1_tag = ASN1_Class_UNIVERSAL.ENUMERATED
+            return self.i2repr_one(pkt, x)
 
+class ASN1F_BIT_STRING(ASN1F_field):
+    ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING
+    def __init__(self, name, default, default_readable=True, context=None,
+                 implicit_tag=None, explicit_tag=None):
+        if default is not None and default_readable:
+            default = "".join(binrepr(ord(x)).zfill(8) for x in default)
+        ASN1F_field.__init__(self, name, default, context=context,
+                             implicit_tag=implicit_tag,
+                             explicit_tag=explicit_tag)
+    def randval(self):
+        return RandString(RandNum(0, 1000))
+    
 class ASN1F_STRING(ASN1F_field):
     ASN1_tag = ASN1_Class_UNIVERSAL.STRING
     def randval(self):
         return RandString(RandNum(0, 1000))
 
+class ASN1F_NULL(ASN1F_INTEGER):
+    ASN1_tag = ASN1_Class_UNIVERSAL.NULL
+
+class ASN1F_OID(ASN1F_field):
+    ASN1_tag = ASN1_Class_UNIVERSAL.OID
+    def randval(self):
+        return RandOID()
+
+class ASN1F_ENUMERATED(ASN1F_enum_INTEGER):
+    ASN1_tag = ASN1_Class_UNIVERSAL.ENUMERATED
+
+class ASN1F_UTF8_STRING(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.UTF8_STRING
+
 class ASN1F_PRINTABLE_STRING(ASN1F_STRING):
     ASN1_tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
 
-class ASN1F_BIT_STRING(ASN1F_STRING):
-    ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING
-    
-class ASN1F_IPADDRESS(ASN1F_STRING):
-    ASN1_tag = ASN1_Class_UNIVERSAL.IPADDRESS    
-
-class ASN1F_TIME_TICKS(ASN1F_INTEGER):
-    ASN1_tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+class ASN1F_T61_STRING(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.T61_STRING
 
+class ASN1F_IA5_STRING(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.IA5_STRING
+   
 class ASN1F_UTC_TIME(ASN1F_STRING):
     ASN1_tag = ASN1_Class_UNIVERSAL.UTC_TIME
 
 class ASN1F_GENERALIZED_TIME(ASN1F_STRING):
     ASN1_tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
 
-class ASN1F_OID(ASN1F_field):
-    ASN1_tag = ASN1_Class_UNIVERSAL.OID
-    def randval(self):
-        return RandOID()
+class ASN1F_ISO646_STRING(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.ISO646_STRING
 
+class ASN1F_UNIVERSAL_STRING(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING
+   
+class ASN1F_BMP_STRING(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.BMP_STRING
+   
 class ASN1F_SEQUENCE(ASN1F_field):
     ASN1_tag = ASN1_Class_UNIVERSAL.SEQUENCE
-    def __init__(self, *seq, **kargs):
-        if "ASN1_tag" in kargs:
-            self.ASN1_tag = kargs["ASN1_tag"]
+    holds_packets = 1
+    def __init__(self, *seq, **kwargs):
+        name = "dummy_seq_name"
+        default = [field.default for field in seq]
+        for kwarg in ["context", "implicit_tag", "explicit_tag"]:
+            if kwarg in kwargs:
+                setattr(self, kwarg, kwargs[kwarg])
+            else:
+                setattr(self, kwarg, None)
+        ASN1F_field.__init__(self, name, default, context=self.context,
+                             implicit_tag=self.implicit_tag,
+                             explicit_tag=self.explicit_tag)
         self.seq = seq
+        self.islist = len(seq) > 1
     def __repr__(self):
-        return "<%s%r>" % (self.__class__.__name__,self.seq,)
-    def set_val(self, pkt, val):
-        for f in self.seq:
-            f.set_val(pkt,val)
+        return "<%s%r>" % (self.__class__.__name__, self.seq)
     def is_empty(self, pkt):
         for f in self.seq:
             if not f.is_empty(pkt):
@@ -211,120 +275,280 @@ class ASN1F_SEQUENCE(ASN1F_field):
         return True
     def get_fields_list(self):
         return reduce(lambda x,y: x+y.get_fields_list(), self.seq, [])
+    def m2i(self, pkt, s):
+        """
+        ASN1F_SEQUENCE behaves transparently, with nested ASN1_objects being
+        dissected one by one. Because we use obj.dissect (see loop below)
+        instead of obj.m2i (as we trust dissect to do the appropriate set_vals)
+        we do not directly retrieve the list of nested objects.
+        Thus m2i returns an empty list (along with the proper remainder).
+        It is discarded by dissect() and should not be missed elsewhere.
+        """
+        s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,
+                            implicit_tag=self.implicit_tag,
+                            explicit_tag=self.explicit_tag,
+                            safe=self.flexible_tag)
+        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
+        i,s,remain = codec.check_type_check_len(s)
+        if len(s) == 0:
+            for obj in self.seq:
+                obj.set_val(pkt, None)
+        else:
+            for obj in self.seq:
+                try:
+                    s = obj.dissect(pkt, s)
+                except ASN1F_badsequence,e:
+                    break
+            if len(s) > 0:
+                raise BER_Decoding_Error("unexpected remainder", remaining=s)
+        return [], remain
+    def dissect(self, pkt, s):
+        _,x = self.m2i(pkt, s)
+        return x
     def build(self, pkt):
         s = reduce(lambda x,y: x+y.build(pkt), self.seq, "")
         return self.i2m(pkt, s)
-    def dissect(self, pkt, s):
-        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
-        try:
-            i,s,remain = codec.check_type_check_len(s)
-            for obj in self.seq:
-                s = obj.dissect(pkt,s)
-            if s:
-                warning("Too many bytes to decode sequence: [%r]" % s) # XXX not reversible!
-            return remain
-        except ASN1_Error,e:
-            raise ASN1F_badsequence(e)
 
 class ASN1F_SET(ASN1F_SEQUENCE):
     ASN1_tag = ASN1_Class_UNIVERSAL.SET
 
-class ASN1F_SEQUENCE_OF(ASN1F_SEQUENCE):
+class ASN1F_SEQUENCE_OF(ASN1F_field):
+    ASN1_tag = ASN1_Class_UNIVERSAL.SEQUENCE
     holds_packets = 1
     islist = 1
-    def __init__(self, name, default, asn1pkt, ASN1_tag=0x30):
-        self.asn1pkt = asn1pkt
-        self.tag = chr(ASN1_tag)
-        self.name = name
+    def __init__(self, name, default, cls, context=None,
+                 implicit_tag=None, explicit_tag=None):
+        self.cls = cls
+        ASN1F_field.__init__(self, name, None, context=context,
+                        implicit_tag=implicit_tag, explicit_tag=explicit_tag)
         self.default = default
-    def i2repr(self, pkt, i):
-        if i is None:
-            return []
-        return i
-    def get_fields_list(self):
-        return [self]
-    def set_val(self, pkt, val):
-        ASN1F_field.set_val(self, pkt, val)
     def is_empty(self, pkt):
         return ASN1F_field.is_empty(self, pkt)
+    def m2i(self, pkt, s):
+        s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,
+                            implicit_tag=self.implicit_tag,
+                            explicit_tag=self.explicit_tag,
+                            safe=self.flexible_tag)
+        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
+        i,s,remain = codec.check_type_check_len(s)
+        lst = []
+        while s:
+            c,s = self.extract_packet(self.cls, s)
+            lst.append(c)
+        if len(s) > 0:
+            raise BER_Decoding_Error("unexpected remainder", remaining=s)
+        return lst, remain
     def build(self, pkt):
         val = getattr(pkt, self.name)
-        if isinstance(val, ASN1_Object) and val.tag == ASN1_Class_UNIVERSAL.RAW:
+        if isinstance(val, ASN1_Object) and val.tag==ASN1_Class_UNIVERSAL.RAW:
             s = val
         elif val is None:
             s = ""
         else:
-            s = "".join(map(str, val ))
+            s = "".join(map(str, val))
         return self.i2m(pkt, s)
-    def dissect(self, pkt, s):
-        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
-        i,s1,remain = codec.check_type_check_len(s)
-        lst = []
-        while s1:
-            try:
-                p = self.asn1pkt(s1)
-            except ASN1F_badsequence,e:
-                lst.append(conf.raw_layer(s1))
-                break
-            lst.append(p)
-            if conf.raw_layer in p:
-                s1 = p[conf.raw_layer].load
-                del(p[conf.raw_layer].underlayer.payload)
-            else:
-                break
-        self.set_val(pkt, lst)
-        return remain
+
     def randval(self):
         return fuzz(self.asn1pkt())
     def __repr__(self):
-        return "<%s %s>" % (self.__class__.__name__,self.name)
+        return "<%s %s>" % (self.__class__.__name__, self.name)
+
+class ASN1F_SET_OF(ASN1F_SEQUENCE_OF):
+    ASN1_tag = ASN1_Class_UNIVERSAL.SET
+
+class ASN1F_IPADDRESS(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.IPADDRESS    
+
+class ASN1F_TIME_TICKS(ASN1F_INTEGER):
+    ASN1_tag = ASN1_Class_UNIVERSAL.TIME_TICKS
+
+
+#############################
+#### Complex ASN1 Fields ####
+#############################
+
+class ASN1F_optional(ASN1F_element):
+    def __init__(self, field, by_default=False):
+        field.flexible_tag = False
+        self._field = field
+    def __getattr__(self, attr):
+        return getattr(self._field, attr)
+    def m2i(self, pkt, s):
+        try:
+            return self._field.m2i(pkt, s)
+        except (ASN1_Error, ASN1F_badsequence, BER_Decoding_Error):
+            # ASN1_Error may be raised by ASN1F_CHOICE
+            return None, s
+    def dissect(self, pkt, s):
+        try:
+            return self._field.dissect(pkt, s)
+        except (ASN1_Error, ASN1F_badsequence, BER_Decoding_Error):
+            self._field.set_val(pkt, None)
+            return s
+    def build(self, pkt):
+        if self._field.is_empty(pkt):
+            return ""
+        return self._field.build(pkt)
+    def any2i(self, pkt, x):
+        return self._field.any2i(pkt, x)
+    def i2repr(self, pkt, x):
+        return self._field.i2repr(pkt, x)
+
+class ASN1F_CHOICE(ASN1F_field):
+    """
+    Multiple types are allowed: ASN1_Packet, ASN1F_field and ASN1F_PACKET(),
+    See layers/x509.py for examples.
+    Other ASN1F_field instances than ASN1F_PACKET instances must not be used.
+    """
+    holds_packets = 1
+    ASN1_tag = ASN1_Class_UNIVERSAL.ANY
+    def __init__(self, name, default, *args, **kwargs):
+        if "implicit_tag" in kwargs:
+            err_msg = "ASN1F_CHOICE has been called with an implicit_tag"
+            raise ASN1_Error(err_msg)
+        self.implicit_tag = None
+        for kwarg in ["context", "explicit_tag"]:
+            if kwarg in kwargs:
+                setattr(self, kwarg, kwargs[kwarg])
+            else:
+                setattr(self, kwarg, None)
+        ASN1F_field.__init__(self, name, None, context=self.context,
+                             explicit_tag=self.explicit_tag)
+        self.default = default
+        self.current_choice = None
+        self.choices = {}
+        self.pktchoices = {}
+        for p in args:
+            if hasattr(p, "ASN1_root"):     # should be ASN1_Packet
+                if hasattr(p.ASN1_root, "choices"):
+                    for k,v in p.ASN1_root.choices.iteritems():
+                        self.choices[k] = v         # ASN1F_CHOICE recursion
+                else:
+                    self.choices[p.ASN1_root.network_tag] = p
+            elif hasattr(p, "ASN1_tag"):
+                if type(p) is type:         # should be ASN1F_field class
+                    self.choices[p.ASN1_tag] = p
+                else:                       # should be ASN1F_PACKET instance
+                    self.choices[p.network_tag] = p
+                    self.pktchoices[hash(p.cls)] = (p.implicit_tag, p.explicit_tag)
+            else:
+                raise ASN1_Error("ASN1F_CHOICE: no tag found for one field")
+    def m2i(self, pkt, s):
+        """
+        First we have to retrieve the appropriate choice.
+        Then we extract the field/packet, according to this choice.
+        """
+        if len(s) == 0:
+            raise ASN1_Error("ASN1F_CHOICE: got empty string")
+        s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,
+                            explicit_tag=self.explicit_tag,
+                            safe=self.flexible_tag)
+        tag,_ = BER_id_dec(s)
+        if tag not in self.choices:
+            if self.flexible_tag:
+                choice = ASN1F_field
+            else:
+                raise ASN1_Error("ASN1F_CHOICE: unexpected field")
+        else:
+            choice = self.choices[tag]
+        if hasattr(choice, "ASN1_root"):
+            return self.extract_packet(choice, s)
+        else:
+            if type(choice) is type:
+                return choice(self.name, "").m2i(pkt, s)
+            else:
+                # choice must be an ASN1F_PACKET instance here
+                return choice.m2i(pkt, s)
+    def i2m(self, pkt, x):
+        if x is None:
+            s = ""
+        else:
+            s = str(x)
+        if hash(type(x)) in self.pktchoices:
+            imp, exp = self.pktchoices[hash(type(x))]
+            s = BER_tagging_enc(s, implicit_tag=imp,
+                                explicit_tag=exp)
+        return BER_tagging_enc(s, explicit_tag=self.explicit_tag)
+    def randval(self):
+        return RandChoice(*map(lambda x:fuzz(x()), self.choice.values()))
 
 class ASN1F_PACKET(ASN1F_field):
     holds_packets = 1
-    def __init__(self, name, default, cls):
-        ASN1F_field.__init__(self, name, default)
+    def __init__(self, name, default, cls, context=None,
+                 implicit_tag=None, explicit_tag=None):
         self.cls = cls
+        ASN1F_field.__init__(self, name, None, context=context,
+                        implicit_tag=implicit_tag, explicit_tag=explicit_tag)
+        if cls.ASN1_root.ASN1_tag == ASN1_Class_UNIVERSAL.SEQUENCE:
+            if implicit_tag is None and explicit_tag is None:
+                self.network_tag = 16|0x20
+        self.default = default
+    def m2i(self, pkt, s):
+        s = BER_tagging_dec(s, hidden_tag=self.cls.ASN1_root.ASN1_tag,
+                            implicit_tag=self.implicit_tag,
+                            explicit_tag=self.explicit_tag,
+                            safe=self.flexible_tag)
+        p,s = self.extract_packet(self.cls, s)
+        return p,s
     def i2m(self, pkt, x):
         if x is None:
-            x = ""
-        return str(x)
-    def extract_packet(self, cls, x):
-        try:
-            c = cls(x)
-        except ASN1F_badsequence:
-            c = conf.raw_layer(x)
-        cpad = c.getlayer(conf.padding_layer)
-        x = ""
-        if cpad is not None:
-            x = cpad.load
-            del(cpad.underlayer.payload)
-        return c,x
-    def m2i(self, pkt, x):
-        return self.extract_packet(self.cls, x)
-
-
-class ASN1F_CHOICE(ASN1F_PACKET):
-    ASN1_tag = ASN1_Class_UNIVERSAL.NONE
-    def __init__(self, name, default, *args):
-        self.name=name
-        self.choice = {}
-        for p in args:
-            self.choice[p.ASN1_root.ASN1_tag] = p
-#        self.context=context
-        self.default=default
-    def m2i(self, pkt, x):
-        if len(x) == 0:
-            return conf.raw_layer(),""
-            raise ASN1_Error("ASN1F_CHOICE: got empty string")
-        if ord(x[0]) not in self.choice:
-            return conf.raw_layer(x),"" # XXX return RawASN1 packet ? Raise error 
-            raise ASN1_Error("Decoding Error: choice [%i] not found in %r" % (ord(x[0]), self.choice.keys()))
+            s = ""
+        else:
+            s = str(x)
+        return BER_tagging_enc(s, implicit_tag=self.implicit_tag,
+                               explicit_tag=self.explicit_tag)
+
+class ASN1F_BIT_STRING_ENCAPS(ASN1F_BIT_STRING):
+    """
+    We may emulate simple string encapsulation with explicit_tag=0x04,
+    but we need a specific class for bit strings because of unused bits, etc.
+    """
+    holds_packets = 1
+    def __init__(self, name, default, cls, context=None,
+                 implicit_tag=None, explicit_tag=None):
+        self.cls = cls
+        ASN1F_BIT_STRING.__init__(self, name, None, context=context,
+                                  implicit_tag=implicit_tag,
+                                  explicit_tag=explicit_tag)
+        self.default = default
+    def m2i(self, pkt, s):
+        bit_string, remain = ASN1F_BIT_STRING.m2i(self, pkt, s)
+        if len(bit_string.val) % 8 != 0:
+            raise BER_Decoding_Error("wrong bit string", remaining=s)
+        p,s = self.extract_packet(self.cls, bit_string.val_readable)
+        if len(s) > 0:
+            raise BER_Decoding_Error("unexpected remainder", remaining=s)
+        return p, remain
+    def i2m(self, pkt, x):
+        if x is None:
+            s = ""
+        else:
+            s = str(x)
+        s = "".join(binrepr(ord(x)).zfill(8) for x in s)
+        return ASN1F_BIT_STRING.i2m(self, pkt, s)
+
+class ASN1F_FLAGS(ASN1F_BIT_STRING):
+    def __init__(self, name, default, mapping, context=None,
+                 implicit_tag=None, explicit_tag=None):
+        self.mapping = mapping
+        ASN1F_BIT_STRING.__init__(self, name, default,
+                                  default_readable=False,
+                                  context=context,
+                                  implicit_tag=implicit_tag,
+                                  explicit_tag=explicit_tag)
+    def get_flags(self, pkt):
+        fbytes = getattr(pkt, self.name).val
+        flags = []
+        for i, positional in enumerate(fbytes):
+            if positional == '1' and i < len(self.mapping):
+                flags.append(self.mapping[i])
+        return flags
+    def i2repr(self, pkt, x):
+        if x is not None:
+            pretty_s = ", ".join(self.get_flags(pkt))
+            return pretty_s + " " + repr(x)
+        return repr(x)
 
-        z = ASN1F_PACKET.extract_packet(self, self.choice[ord(x[0])], x)
-        return z
-    def randval(self):
-        return RandChoice(*map(lambda x:fuzz(x()), self.choice.values()))
-            
-    
-# This import must come in last to avoid problems with cyclic dependencies
+
+# This import must come last to avoid problems with cyclic dependencies
 import packet
diff --git a/scapy/contrib/HomePlugAV.py b/scapy/contrib/HomePlugAV.py
index a3fb670c882bface713f954692b60e1b24e3acb8..1717f442ab53f1ed6141b35285ba666f901995d5 100644
--- a/scapy/contrib/HomePlugAV.py
+++ b/scapy/contrib/HomePlugAV.py
@@ -451,7 +451,6 @@ class ReadModuleDataConfirmation(Packet):
                 ]
 
     def post_build(self, p, pay):
-        import binascii
         if self.DataLen is None:
             _len = len(self.ModuleData)
             p = p[:6] + struct.pack('h', _len) + p[8:]
@@ -475,7 +474,6 @@ class WriteModuleDataRequest(Packet):
                 ]
 
     def post_build(self, p, pay):
-        import binascii
         if self.DataLen is None:
             _len = len(self.ModuleData)
             p = p[:2] + struct.pack('h', _len) + p[4:]
diff --git a/scapy/contrib/openflow.py b/scapy/contrib/openflow.py
index beab1f13158b812e9e43897728c99703c03679b4..3e5fcf73281471fa8dde592b43091e5342285129 100755
--- a/scapy/contrib/openflow.py
+++ b/scapy/contrib/openflow.py
@@ -11,9 +11,9 @@
 # scapy.contrib.description = openflow v1.0
 # scapy.contrib.status = loads
 
-import binascii
 import struct
 from scapy.all import *
+from scapy.utils import binrepr
 
 ### If prereq_autocomplete is True then match prerequisites will be
 ### automatically handled. See OFPMatch class.
@@ -129,58 +129,58 @@ class OFPMatch(Packet):
     ### with post_build we create the wildcards field bit by bit
     def post_build(self, p, pay):
         # first 10 bits of an ofp_match are always set to 0
-        l = ["0"*10]
+        l = "0"*10
 
         # when one field has not been declared, it is assumed to be wildcarded
         if self.wildcards1 is None:
-            if self.nw_tos is None: l.append("1")
-            else: l.append("0")
-            if self.dl_vlan_pcp is None: l.append("1")
-            else: l.append("0")
+            if self.nw_tos is None: l+="1"
+            else: l+="0"
+            if self.dl_vlan_pcp is None: l+="1"
+            else: l+="0"
         else:
-            w1 = bin(self.wildcards1)[2:]
-            l.append("0"*(2-len(w1)))
-            l.append(w1)
+            w1 = binrepr(self.wildcards1)
+            l+="0"*(2-len(w1))
+            l+=w1
                     
         # ip masks use 6 bits each
         if self.nw_dst_mask is None:
-            if self.nw_dst is "0": l.append("111111")
+            if self.nw_dst is "0": l+="111111"
             # 0x100000 would be ok too (32-bit IP mask)
-            else: l.append("0"*6)
+            else: l+="0"*6
         else:
-            m1 = bin(self.nw_dst_mask)[2:]
-            l.append("0"*(6-len(m1)))
-            l.append(m1)
+            m1 = binrepr(self.nw_dst_mask)
+            l+="0"*(6-len(m1))
+            l+=m1
         if self.nw_src_mask is None:
-            if self.nw_src is "0": l.append("111111")
-            else: l.append("0"*6)
+            if self.nw_src is "0": l+="111111"
+            else: l+="0"*6
         else:
-            m2 = bin(self.nw_src_mask)[2:]
-            l.append("0"*(6-len(m2)))
-            l.append(m2)
+            m2 = binrepr(self.nw_src_mask)
+            l+="0"*(6-len(m2))
+            l+=m2
 
         # wildcards2 works the same way as wildcards1
         if self.wildcards2 is None:
-            if self.tp_dst is None: l.append("1")
-            else: l.append("0")
-            if self.tp_src is None: l.append("1")
-            else: l.append("0")
-            if self.nw_proto is None: l.append("1")
-            else: l.append("0")
-            if self.dl_type is None: l.append("1")
-            else: l.append("0")
-            if self.dl_dst is None: l.append("1")
-            else: l.append("0")
-            if self.dl_src is None: l.append("1")
-            else: l.append("0")
-            if self.dl_vlan is None: l.append("1")
-            else: l.append("0")
-            if self.in_port is None: l.append("1")
-            else: l.append("0")
+            if self.tp_dst is None: l+="1"
+            else: l+="0"
+            if self.tp_src is None: l+="1"
+            else: l+="0"
+            if self.nw_proto is None: l+="1"
+            else: l+="0"
+            if self.dl_type is None: l+="1"
+            else: l+="0"
+            if self.dl_dst is None: l+="1"
+            else: l+="0"
+            if self.dl_src is None: l+="1"
+            else: l+="0"
+            if self.dl_vlan is None: l+="1"
+            else: l+="0"
+            if self.in_port is None: l+="1"
+            else: l+="0"
         else:
-            w2 = bin(self.wildcards2)[2:]
-            l.append("0"*(8-len(w2)))
-            l.append(w2)
+            w2 = binrepr(self.wildcards2)
+            l+="0"*(8-len(w2))
+            l+=w2
 
         ### In order to write OFPMatch compliant with the specifications,
         ### if prereq_autocomplete has been set to True
@@ -189,21 +189,15 @@ class OFPMatch(Packet):
             if self.dl_type is None:
                 if self.nw_src is not "0" or self.nw_dst is not "0" or self.nw_proto is not None or self.nw_tos is not None:
                     p = p[:22] + struct.pack("!H", 0x0800) + p[24:]
-                    l[-5] = "0"
+                    l = l[:-5] + "0" + l[-4:]
             if self.nw_proto is None:
                 if self.tp_src is not None or self.tp_dst is not None:
                     p = p[:22] + struct.pack("!H", 0x0800) + p[24:]
-                    l[-5] = "0"
+                    l = l[:-5] + "0" + l[-4:]
                     p = p[:25] + struct.pack("!B", 0x06) + p[26:]
-                    l[-6] = "0"
-
-        wild = "".join(l)
-        pad = ""
-        i = 0
-        while i < 32 and wild[i:i+4] == "0000":
-                    pad += "0"
-                    i += 4
-        ins = binascii.unhexlify(pad + "%x" % int(wild, 2))
+                    l = l[:-6] + "0" + l[-5:]
+
+        ins = "".join(chr(int("".join(x),2)) for x in zip(*[iter(l)]*8))
         p = ins + p[4:]
         return p + pay
 
diff --git a/scapy/layers/x509.py b/scapy/layers/x509.py
index 18aaa5e3391d401bdf95150cf1f8305c67f87a85..fa0389a555621e2a51b55f569abcc16093790605 100644
--- a/scapy/layers/x509.py
+++ b/scapy/layers/x509.py
@@ -1,6 +1,7 @@
 ## This file is part of Scapy
 ## See http://www.secdev.org/projects/scapy for more informations
 ## Copyright (C) Philippe Biondi <phil@secdev.org>
+## Enhanced by Maxence Tury <maxence.tury@ssi.gouv.fr>
 ## This program is published under a GPLv2 license
 
 """
@@ -10,99 +11,969 @@ X.509 certificates.
 from scapy.asn1packet import *
 from scapy.asn1fields import *
 
-##########
-## X509 ##
-##########
-
-######[ ASN1 class ]######
-
-class ASN1_Class_X509(ASN1_Class_UNIVERSAL):
-    name="X509"
-    CONT0 = 0xa0
-    CONT1 = 0xa1
-    CONT2 = 0xa2
-    CONT3 = 0xa3
-
-class ASN1_X509_CONT0(ASN1_SEQUENCE):
-    tag = ASN1_Class_X509.CONT0
-
-class ASN1_X509_CONT1(ASN1_SEQUENCE):
-    tag = ASN1_Class_X509.CONT1
-
-class ASN1_X509_CONT2(ASN1_SEQUENCE):
-    tag = ASN1_Class_X509.CONT2
-
-class ASN1_X509_CONT3(ASN1_SEQUENCE):
-    tag = ASN1_Class_X509.CONT3
-
-######[ BER codecs ]#######
-
-class BERcodec_X509_CONT0(BERcodec_SEQUENCE):
-    tag = ASN1_Class_X509.CONT0
-
-class BERcodec_X509_CONT1(BERcodec_SEQUENCE):
-    tag = ASN1_Class_X509.CONT1
-    
-class BERcodec_X509_CONT2(BERcodec_SEQUENCE):
-    tag = ASN1_Class_X509.CONT2
-    
-class BERcodec_X509_CONT3(BERcodec_SEQUENCE):
-    tag = ASN1_Class_X509.CONT3
-
-######[ ASN1 fields ]######
-
-class ASN1F_X509_CONT0(ASN1F_SEQUENCE):
-    ASN1_tag = ASN1_Class_X509.CONT0
-    
-class ASN1F_X509_CONT1(ASN1F_SEQUENCE):
-    ASN1_tag = ASN1_Class_X509.CONT1
-    
-class ASN1F_X509_CONT2(ASN1F_SEQUENCE):
-    ASN1_tag = ASN1_Class_X509.CONT2
-    
-class ASN1F_X509_CONT3(ASN1F_SEQUENCE):
-    ASN1_tag = ASN1_Class_X509.CONT3
-
-######[ X509 packets ]######
-
-class X509RDN(ASN1_Packet):
-    ASN1_codec = ASN1_Codecs.BER
-    ASN1_root = ASN1F_SET(
-                  ASN1F_SEQUENCE( ASN1F_OID("oid","2.5.4.6"),
-                                  ASN1F_PRINTABLE_STRING("value","")
-                                  )
-                  )
-
-class X509v3Ext(ASN1_Packet):
-    ASN1_codec = ASN1_Codecs.BER
-    ASN1_root = ASN1F_field("val",ASN1_NULL(0))
-    
-
-class X509Cert(ASN1_Packet):
-    ASN1_codec = ASN1_Codecs.BER
-    ASN1_root = ASN1F_SEQUENCE(
-        ASN1F_SEQUENCE(
-            ASN1F_optionnal(ASN1F_X509_CONT0(ASN1F_INTEGER("version",3))),
-            ASN1F_INTEGER("sn",1),
-            ASN1F_SEQUENCE(ASN1F_OID("sign_algo","1.2.840.113549.1.1.5"),
-                           ASN1F_field("sa_value",ASN1_NULL(0))),
-            ASN1F_SEQUENCE_OF("issuer",[],X509RDN),
-            ASN1F_SEQUENCE(ASN1F_UTC_TIME("not_before",ZuluTime(-600)),  # ten minutes ago
-                           ASN1F_UTC_TIME("not_after",ZuluTime(+86400))), # for 24h
-            ASN1F_SEQUENCE_OF("subject",[],X509RDN),
-            ASN1F_SEQUENCE(
-                ASN1F_SEQUENCE(ASN1F_OID("pubkey_algo","1.2.840.113549.1.1.1"),
-                               ASN1F_field("pk_value",ASN1_NULL(0))),
-                ASN1F_BIT_STRING("pubkey","")
-                ),
-            ASN1F_optionnal(ASN1F_X509_CONT3(ASN1F_SEQUENCE_OF("x509v3ext",[],X509v3Ext))),
-            
-        ),
-        ASN1F_SEQUENCE(ASN1F_OID("sign_algo2","1.2.840.113549.1.1.5"),
-                       ASN1F_field("sa2_value",ASN1_NULL(0))),
-        ASN1F_BIT_STRING("signature","")
-        )
+class ASN1P_OID(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_OID("oid", "0")
+
+class ASN1P_INTEGER(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_INTEGER("number", 0)
+
+
+#######################
+##### RSA packets #####
+#######################
+##### based on RFC 3447
+
+# It could be interesting to use os.urandom and try to generate
+# a new modulus each time RSAPublicKey is called with default values.
+# (We might have to dig into scapy field initialization mechanisms...)
+# NEVER rely on the key below, which is provided only for debugging purposes.
+class RSAPublicKey(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_INTEGER("modulus", 10),
+                    ASN1F_INTEGER("publicExponent", 3))
+
+class RSAOtherPrimeInfo(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.DER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_INTEGER("prime", 0),
+                    ASN1F_INTEGER("exponent", 0),
+                    ASN1F_INTEGER("coefficient", 0))
+
+class RSAPrivateKey(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_enum_INTEGER("version", 0, ["two-prime", "multi"]),
+                    ASN1F_INTEGER("modulus", 10),
+                    ASN1F_INTEGER("publicExponent", 3),
+                    ASN1F_INTEGER("privateExponent", 3),
+                    ASN1F_INTEGER("prime1", 2),
+                    ASN1F_INTEGER("prime2", 5),
+                    ASN1F_INTEGER("exponent1", 0),
+                    ASN1F_INTEGER("exponent2", 3),
+                    ASN1F_INTEGER("coefficient", 1),
+                    ASN1F_optional(
+                        ASN1F_SEQUENCE_OF("otherPrimeInfos", None,
+                                          RSAOtherPrimeInfo)))
+
+####################################
+########## ECDSA packets ###########
+####################################
+#### based on RFC 3279 & 5480 & 5915
+
+class ECFieldID(ASN1_Packet):
+# No characteristic-two-field support for now.
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("fieldType", "prime-field"),
+                    ASN1F_INTEGER("prime", 0))
+
+class ECCurve(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_STRING("a", ""),
+                    ASN1F_STRING("b", ""),
+                    ASN1F_optional(
+                        ASN1F_BIT_STRING("seed", None)))
+
+class ECSpecifiedDomain(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_enum_INTEGER("version", 1, {1: "ecpVer1"}),
+                    ASN1F_PACKET("fieldID", ECFieldID(), ECFieldID),
+                    ASN1F_PACKET("curve", ECCurve(), ECCurve),
+                    ASN1F_STRING("base", ""),
+                    ASN1F_INTEGER("order", 0),
+                    ASN1F_optional(
+                        ASN1F_INTEGER("cofactor", None)))
+
+class ECParameters(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_CHOICE("curve", ASN1_OID("ansip384r1"),
+                    ASN1F_OID,      # for named curves
+                    ASN1F_NULL,     # for implicit curves
+                    ECSpecifiedDomain)
+
+class ECDSAPublicKey(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_BIT_STRING("ecPoint", "")
+
+class ECDSAPrivateKey(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_enum_INTEGER("version", 1, {1: "ecPrivkeyVer1"}),
+                    ASN1F_STRING("privateKey", ""),
+                    ASN1F_optional(
+                        ASN1F_PACKET("parameters", None, ECParameters,
+                                     explicit_tag=0xa0)),
+                    ASN1F_optional(
+                        ASN1F_PACKET("publicKey", None,
+                                     ECDSAPublicKey,
+                                     explicit_tag=0xa1)))
+
+class ECDSASignature(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_INTEGER("r", 0),
+                    ASN1F_INTEGER("s", 0))
+
+
+######################
+#### X509 packets ####
+######################
+#### based on RFC 5280
+
+
+####### Names #######
+
+class ASN1F_X509_DirectoryString(ASN1F_CHOICE):
+# we include ASN1 bit strings for rare instances of x500 addresses
+    def __init__(self, name, default, **kwargs):
+        ASN1F_CHOICE.__init__(self, name, default,
+                              ASN1F_PRINTABLE_STRING, ASN1F_UTF8_STRING,
+                              ASN1F_IA5_STRING, ASN1F_T61_STRING,
+                              ASN1F_UNIVERSAL_STRING, ASN1F_BIT_STRING,
+                              **kwargs)
+
+class X509_AttributeValue(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_CHOICE("value", ASN1_PRINTABLE_STRING("FR"),
+                             ASN1F_PRINTABLE_STRING, ASN1F_UTF8_STRING,
+                             ASN1F_IA5_STRING, ASN1F_T61_STRING,
+                             ASN1F_UNIVERSAL_STRING)
+
+class X509_Attribute(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("type", "2.5.4.6"),
+                    ASN1F_SET_OF("values",
+                                 [X509_AttributeValue()],
+                                 X509_AttributeValue))
 
+class X509_AttributeTypeAndValue(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root =  ASN1F_SEQUENCE(
+                     ASN1F_OID("type", "2.5.4.6"),
+                     ASN1F_X509_DirectoryString("value",
+                         ASN1_PRINTABLE_STRING("FR")))
+
+class X509_RDN(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SET_OF("rdn", [X509_AttributeTypeAndValue()],
+                             X509_AttributeTypeAndValue)
 
+class X509_OtherName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("type_id", "0"),
+                    ASN1F_CHOICE("value", None,
+                        ASN1F_IA5_STRING, ASN1F_ISO646_STRING,
+                        ASN1F_BMP_STRING, ASN1F_UTF8_STRING,
+                        explicit_tag=0xa0))
+
+class X509_RFC822Name(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_IA5_STRING("rfc822Name", "")
+
+class X509_DNSName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_IA5_STRING("dNSName", "")
+
+#XXX write me
+class X509_X400Address(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_field("x400Address", "")
+
+default_directoryName = [
+        X509_RDN(),
+        X509_RDN(
+            rdn=[X509_AttributeTypeAndValue(
+                 type="2.5.4.10",
+                 value=ASN1_PRINTABLE_STRING("Scapy, Inc."))]),
+        X509_RDN(
+            rdn=[X509_AttributeTypeAndValue(
+                 type="2.5.4.3",
+                 value=ASN1_PRINTABLE_STRING("Scapy Default Name"))])
+            ]
+
+class X509_DirectoryName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("directoryName", default_directoryName,
+                    X509_RDN)
+
+class X509_EDIPartyName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_X509_DirectoryString("nameAssigner", None,
+                                                   explicit_tag=0xa0)),
+                    ASN1F_X509_DirectoryString("partyName", None,
+                                               explicit_tag=0xa1))
+
+class X509_URI(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_IA5_STRING("uniformResourceIdentifier", "")
+
+class X509_IPAddress(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_STRING("iPAddress", "")
+
+class X509_RegisteredID(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_OID("registeredID", "")
+
+class X509_GeneralName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_CHOICE("generalName", X509_DirectoryName(),
+                    ASN1F_PACKET("otherName", None, X509_OtherName,
+                                 implicit_tag=0xa0),
+                    ASN1F_PACKET("rfc822Name", None, X509_RFC822Name,
+                                 implicit_tag=0x81),
+                    ASN1F_PACKET("dNSName", None, X509_DNSName,
+                                 implicit_tag=0x82),
+                    ASN1F_PACKET("x400Address", None, X509_X400Address,
+                                 explicit_tag=0xa3),
+                    ASN1F_PACKET("directoryName", None, X509_DirectoryName,
+                                 explicit_tag=0xa4),
+                    ASN1F_PACKET("ediPartyName", None, X509_EDIPartyName,
+                                 explicit_tag=0xa5),
+                    ASN1F_PACKET("uniformResourceIdentifier", None, X509_URI,
+                                 implicit_tag=0x86),
+                    ASN1F_PACKET("ipAddress", None, X509_IPAddress,
+                                 implicit_tag=0x87),
+                    ASN1F_PACKET("registeredID", None, X509_RegisteredID,
+                                 implicit_tag=0x88))
+
+
+####### Extensions #######
+
+class X509_ExtAuthorityKeyIdentifier(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_STRING("keyIdentifier", "\xff"*20,
+                                     implicit_tag=0x80)),
+                    ASN1F_optional(
+                        ASN1F_SEQUENCE_OF("authorityCertIssuer", None,
+                                          X509_GeneralName,
+                                          implicit_tag=0xa1)),
+                    ASN1F_optional(
+                        ASN1F_INTEGER("authorityCertSerialNumber", None,
+                                      implicit_tag=0x82)))
+
+class X509_ExtSubjectDirectoryAttributes(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("subjectDirectoryAttributes",
+                                  [X509_Attribute()],
+                                  X509_Attribute)
+
+class X509_ExtSubjectKeyIdentifier(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_STRING("keyIdentifier", "xff"*20)
+
+class X509_ExtFullName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("fullName", [X509_GeneralName()],
+                                  X509_GeneralName, implicit_tag=0xa0)
+
+class X509_ExtNameRelativeToCRLIssuer(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_PACKET("nameRelativeToCRLIssuer", X509_RDN(), X509_RDN,
+                             implicit_tag=0xa1)
+
+class X509_ExtDistributionPointName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_CHOICE("distributionPointName", None,
+                    X509_ExtFullName, X509_ExtNameRelativeToCRLIssuer)
+
+reasons_mapping = ["unused",
+                   "keyCompromise",
+                   "cACompromise",
+                   "affiliationChanged",
+                   "superseded",
+                   "cessationOfOperation",
+                   "certificateHold",
+                   "privilegeWithdrawn",
+                   "aACompromise"]
+
+class X509_ExtDistributionPoint(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_PACKET("distributionPoint",
+                                     X509_ExtDistributionPointName(),
+                                     X509_ExtDistributionPointName,
+                                     explicit_tag=0xa0)),
+                    ASN1F_optional(
+                        ASN1F_FLAGS("reasons", None, reasons_mapping,
+                                    implicit_tag=0x81)),
+                    ASN1F_optional(
+                        ASN1F_SEQUENCE_OF("cRLIssuer", None,
+                                          X509_GeneralName,
+                                          implicit_tag=0xa2)))
+
+ku_mapping = ["digitalSignature",
+              "nonRepudiation",
+              "keyEncipherment",
+              "dataEncipherment",
+              "keyAgreement",
+              "keyCertSign",
+              "cRLSign",
+              "encipherOnly",
+              "decipherOnly"]
+
+class X509_ExtKeyUsage(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_FLAGS("keyUsage", "101", ku_mapping)
+    def get_keyUsage(self):
+        return self.ASN1_root.get_flags(self)
+
+class X509_ExtPrivateKeyUsagePeriod(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_GENERALIZED_TIME("notBefore",
+                                               str(GeneralizedTime(-600)),
+                                               implicit_tag=0x80)),
+                    ASN1F_optional(
+                        ASN1F_GENERALIZED_TIME("notAfter",
+                                               str(GeneralizedTime(+86400)),
+                                               implicit_tag=0x81)))
+
+class X509_PolicyMapping(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("issuerDomainPolicy", None),
+                    ASN1F_OID("subjectDomainPolicy", None))
+
+class X509_ExtPolicyMappings(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("policyMappings", [], X509_PolicyMapping)
+
+class X509_ExtBasicConstraints(ASN1_Packet):
+# The cA field should not be optional, but some certs omit it for False.
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_BOOLEAN("cA", False)),
+                    ASN1F_optional(
+                        ASN1F_INTEGER("pathLenConstraint", None)))
+
+class X509_ExtCRLNumber(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_INTEGER("cRLNumber", 0)
 
+cRL_reasons = ["unspecified",
+               "keyCompromise",
+               "cACompromise",
+               "affiliationChanged",
+               "superseded",
+               "cessationOfOperation",
+               "certificateHold",
+               "unused_reasonCode",
+               "removeFromCRL",
+               "privilegeWithdrawn",
+               "aACompromise"]
+
+class X509_ExtReasonCode(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_ENUMERATED("cRLReason", 0, cRL_reasons)
+
+class X509_ExtDeltaCRLIndicator(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_INTEGER("deltaCRLIndicator", 0)
+
+class X509_ExtIssuingDistributionPoint(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_PACKET("distributionPoint",
+                                     X509_ExtDistributionPointName(),
+                                     X509_ExtDistributionPointName,
+                                     explicit_tag=0xa0)),
+                    ASN1F_BOOLEAN("onlyContainsUserCerts", False,
+                                  implicit_tag=0x81),
+                    ASN1F_BOOLEAN("onlyContainsCACerts", False,
+                                  implicit_tag=0x82),
+                    ASN1F_optional(
+                        ASN1F_FLAGS("onlySomeReasons", None,
+                                    reasons_mapping,
+                                    implicit_tag=0x83)),
+                    ASN1F_BOOLEAN("indirectCRL", False,
+                                  implicit_tag=0x84),
+                    ASN1F_BOOLEAN("onlyContainsAttributeCerts", False,
+                                  implicit_tag=0x85))
+
+class X509_ExtCertificateIssuer(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("certificateIssuer", [], X509_GeneralName)
+
+class X509_ExtInvalidityDate(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_GENERALIZED_TIME("invalidityDate", str(ZuluTime(+86400)))
+
+class X509_ExtSubjectAltName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("subjectAltName", [], X509_GeneralName)
+
+class X509_ExtIssuerAltName(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("issuerAltName", [], X509_GeneralName)
+
+class X509_ExtGeneralSubtree(ASN1_Packet):
+# 'minimum' is not optional in RFC 5280, yet it is in some implementations.
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_PACKET("base", X509_GeneralName(), X509_GeneralName),
+                    ASN1F_optional(
+                        ASN1F_INTEGER("minimum", None, implicit_tag=0x80)),
+                    ASN1F_optional(
+                        ASN1F_INTEGER("maximum", None, implicit_tag=0x81)))
+
+class X509_ExtNameConstraints(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_SEQUENCE_OF("permittedSubtrees", None,
+                                          X509_ExtGeneralSubtree,
+                                          implicit_tag=0xa0)),
+                    ASN1F_optional(
+                        ASN1F_SEQUENCE_OF("excludedSubtrees", None,
+                                          X509_ExtGeneralSubtree,
+                                          implicit_tag=0xa1)))
+
+class X509_ExtPolicyConstraints(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_INTEGER("requireExplicitPolicy", None,
+                                      implicit_tag=0x80)),
+                    ASN1F_optional(
+                        ASN1F_INTEGER("inhibitPolicyMapping", None,
+                                      implicit_tag=0x81)))
+
+class X509_ExtExtendedKeyUsage(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("extendedKeyUsage", [], ASN1P_OID)
+    def get_extendedKeyUsage(self):
+        eku_array = self.extendedKeyUsage
+        return [eku.oid.oidname for eku in eku_array]
+
+class X509_ExtNoticeReference(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_CHOICE("organization",
+                                 ASN1_UTF8_STRING("Dummy Organization"),
+                        ASN1F_IA5_STRING, ASN1F_ISO646_STRING,
+                        ASN1F_BMP_STRING, ASN1F_UTF8_STRING),
+                    ASN1F_SEQUENCE_OF("noticeNumbers", [], ASN1P_INTEGER))
+
+class X509_ExtUserNotice(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_PACKET("noticeRef", None,
+                                     X509_ExtNoticeReference)),
+                    ASN1F_optional(
+                        ASN1F_CHOICE("explicitText",
+                                     ASN1_UTF8_STRING("Dummy ExplicitText"),
+                            ASN1F_IA5_STRING, ASN1F_ISO646_STRING,
+                            ASN1F_BMP_STRING, ASN1F_UTF8_STRING)))
+
+class X509_ExtPolicyQualifierInfo(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("policyQualifierId", "1.3.6.1.5.5.7.2.1"),
+                    ASN1F_CHOICE("qualifier", ASN1_IA5_STRING("cps_str"),
+                        ASN1F_IA5_STRING, X509_ExtUserNotice))
+
+class X509_ExtPolicyInformation(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("policyIdentifier", "2.5.29.32.0"),
+                    ASN1F_optional(
+                        ASN1F_SEQUENCE_OF("policyQualifiers", None,
+                            X509_ExtPolicyQualifierInfo)))
+
+class X509_ExtCertificatePolicies(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("certificatePolicies",
+                                  [X509_ExtPolicyInformation()],
+                                  X509_ExtPolicyInformation)
+
+class X509_ExtCRLDistributionPoints(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("cRLDistributionPoints",
+                                  [X509_ExtDistributionPoint()],
+                                  X509_ExtDistributionPoint)
+
+class X509_ExtInhibitAnyPolicy(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_INTEGER("skipCerts", 0)
+
+class X509_ExtFreshestCRL(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("cRLDistributionPoints",
+                                  [X509_ExtDistributionPoint()],
+                                  X509_ExtDistributionPoint)
+
+class X509_AccessDescription(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("accessMethod", "0"),
+                    ASN1F_PACKET("accessLocation", X509_GeneralName(),
+                                 X509_GeneralName))
+
+class X509_ExtAuthInfoAccess(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("authorityInfoAccess", 
+                                  [X509_AccessDescription()],
+                                  X509_AccessDescription)
+
+class X509_ExtQcStatement(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("statementId", "0.4.0.1862.1.1"),
+                    ASN1F_optional(
+                        ASN1F_field("statementInfo", None)))
+
+class X509_ExtQcStatements(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("qcStatements",
+                                  [X509_ExtQcStatement()],
+                                  X509_ExtQcStatement)
+
+class X509_ExtSubjInfoAccess(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE_OF("subjectInfoAccess",
+                                  [X509_AccessDescription()],
+                                  X509_AccessDescription)
+
+class X509_ExtNetscapeCertType(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_BIT_STRING("netscapeCertType", "")
+
+class X509_ExtComment(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_CHOICE("comment",
+                             ASN1_UTF8_STRING("Dummy comment."),
+                    ASN1F_IA5_STRING, ASN1F_ISO646_STRING,
+                    ASN1F_BMP_STRING, ASN1F_UTF8_STRING)
+
+class X509_ExtDefault(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_field("value", None)
+
+# oid-info.com shows that some extensions share multiple OIDs.
+# Here we only reproduce those written in RFC5280.
+ext_mapping = {
+        "2.5.29.9"      : X509_ExtSubjectDirectoryAttributes,
+        "2.5.29.14"     : X509_ExtSubjectKeyIdentifier,
+        "2.5.29.15"     : X509_ExtKeyUsage,
+        "2.5.29.16"     : X509_ExtPrivateKeyUsagePeriod,
+        "2.5.29.17"     : X509_ExtSubjectAltName,
+        "2.5.29.18"     : X509_ExtIssuerAltName,
+        "2.5.29.19"     : X509_ExtBasicConstraints,
+        "2.5.29.20"     : X509_ExtCRLNumber,
+        "2.5.29.21"     : X509_ExtReasonCode,
+        "2.5.29.24"     : X509_ExtInvalidityDate,
+        "2.5.29.27"     : X509_ExtDeltaCRLIndicator,
+        "2.5.29.28"     : X509_ExtIssuingDistributionPoint,
+        "2.5.29.29"     : X509_ExtCertificateIssuer,
+        "2.5.29.30"     : X509_ExtNameConstraints,
+        "2.5.29.31"     : X509_ExtCRLDistributionPoints,
+        "2.5.29.32"     : X509_ExtCertificatePolicies,
+        "2.5.29.33"     : X509_ExtPolicyMappings,
+        "2.5.29.35"     : X509_ExtAuthorityKeyIdentifier,
+        "2.5.29.36"     : X509_ExtPolicyConstraints,
+        "2.5.29.37"     : X509_ExtExtendedKeyUsage,
+        "2.5.29.46"     : X509_ExtFreshestCRL,
+        "2.5.29.54"     : X509_ExtInhibitAnyPolicy,
+        "2.16.840.1.113730.1.1"    : X509_ExtNetscapeCertType,
+        "2.16.840.1.113730.1.13"   : X509_ExtComment,
+        "1.3.6.1.5.5.7.1.1"        : X509_ExtAuthInfoAccess,
+        "1.3.6.1.5.5.7.1.3"        : X509_ExtQcStatements,
+        "1.3.6.1.5.5.7.1.11"       : X509_ExtSubjInfoAccess
+        }
+
+class ASN1F_EXT_SEQUENCE(ASN1F_SEQUENCE):
+# We use explicit_tag=0x04 with extnValue as STRING encapsulation.
+    def __init__(self, **kargs):
+        seq = [ASN1F_OID("extnID", "2.5.29.19"),
+               ASN1F_optional(
+                   ASN1F_BOOLEAN("critical", False)),
+               ASN1F_PACKET("extnValue",
+                   X509_ExtBasicConstraints(),
+                   X509_ExtBasicConstraints,
+                   explicit_tag=0x04)]
+        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
+    def dissect(self, pkt, s):
+        s = BER_tagging_dec(s, implicit_tag=self.implicit_tag,
+                            explicit_tag=self.explicit_tag,
+                            safe=self.flexible_tag)
+        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
+        i,s,remain = codec.check_type_check_len(s)
+        extnID = self.seq[0]
+        critical = self.seq[1]
+        try:
+            oid,s = extnID.m2i(pkt, s)
+            extnID.set_val(pkt, oid)
+            s = critical.dissect(pkt, s)
+            encapsed = X509_ExtDefault
+            if oid.val in ext_mapping:
+                encapsed = ext_mapping[oid.val]
+            self.seq[2].cls = encapsed
+            self.seq[2].cls.ASN1_root.flexible_tag = True
+            # there are too many private extensions not to be flexible here
+            self.seq[2].default = encapsed()
+            s = self.seq[2].dissect(pkt, s)
+            if not self.flexible_tag and len(s) > 0:
+                err_msg = "extension sequence length issue"
+                raise BER_Decoding_Error(err_msg, remaining=s)
+        except ASN1F_badsequence,e:
+            raise Exception("could not parse extensions")
+        return remain
+
+class X509_Extension(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_EXT_SEQUENCE()
+
+
+####### Public key wrapper #######
+
+class X509_AlgorithmIdentifier(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_OID("algorithm", "1.2.840.113549.1.1.11"),
+                    ASN1F_optional(
+                        ASN1F_CHOICE("parameters", ASN1_NULL(0),
+                            ASN1F_NULL, ECParameters)))
+
+class ASN1F_X509_SubjectPublicKeyInfoRSA(ASN1F_SEQUENCE):
+    def __init__(self, **kargs):
+        seq = [ASN1F_PACKET("signatureAlgorithm",
+                            X509_AlgorithmIdentifier(),
+                            X509_AlgorithmIdentifier),
+               ASN1F_BIT_STRING_ENCAPS("subjectPublicKey",
+                            RSAPublicKey(),
+                            RSAPublicKey)]
+        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
+
+class ASN1F_X509_SubjectPublicKeyInfo(ASN1F_SEQUENCE):
+    def __init__(self, **kargs):
+        seq = [ASN1F_PACKET("signatureAlgorithm",
+                            X509_AlgorithmIdentifier(),
+                            X509_AlgorithmIdentifier),
+               ASN1F_BIT_STRING("subjectPublicKey", None)]
+        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
+    def m2i(self, pkt, x):
+        c,s = ASN1F_SEQUENCE.m2i(self, pkt, x)
+        keytype = pkt.fields["signatureAlgorithm"].algorithm.oidname
+        if "rsa" in keytype.lower():
+            return ASN1F_X509_SubjectPublicKeyInfoRSA().m2i(pkt, x)
+        elif keytype == "ecPublicKey":
+            return c,s
+        else:
+            raise Exception("could not parse subjectPublicKeyInfo")
+    def dissect(self, pkt, s):
+        c,x = self.m2i(pkt, s)
+        return x
+    def build(self, pkt):
+        if "signatureAlgorithm" in pkt.fields:
+            ktype = pkt.fields['signatureAlgorithm'].algorithm.oidname
+        else:
+            ktype = pkt.default_fields["signatureAlgorithm"].algorithm.oidname
+        if "rsa" in ktype.lower():
+            pkt.default_fields["subjectPublicKey"] = RSAPublicKey()
+            return ASN1F_X509_SubjectPublicKeyInfoRSA().build(pkt)
+        elif ktype == "ecPublicKey":
+            return ASN1F_SEQUENCE.build(self, pkt)
+        else:
+            raise Exception("could not build subjectPublicKeyInfo")
+
+class X509_SubjectPublicKeyInfo(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_X509_SubjectPublicKeyInfo()
+
+
+####### TBSCertificate & Certificate #######
+
+default_issuer = [
+        X509_RDN(),
+        X509_RDN(
+            rdn=[X509_AttributeTypeAndValue(
+                 type="2.5.4.10",
+                 value=ASN1_PRINTABLE_STRING("Scapy, Inc."))]),
+        X509_RDN(
+            rdn=[X509_AttributeTypeAndValue(
+                 type="2.5.4.3",
+                 value=ASN1_PRINTABLE_STRING("Scapy Default Issuer"))])
+            ]
+
+default_subject = [
+        X509_RDN(),
+        X509_RDN(
+            rdn=[X509_AttributeTypeAndValue(
+                 type="2.5.4.10",
+                 value=ASN1_PRINTABLE_STRING("Scapy, Inc."))]),
+        X509_RDN(
+            rdn=[X509_AttributeTypeAndValue(
+                 type="2.5.4.3",
+                 value=ASN1_PRINTABLE_STRING("Scapy Default Subject"))])
+            ]
+
+class X509_Validity(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root =  ASN1F_SEQUENCE(
+                     ASN1F_CHOICE("not_before",
+                                  ASN1_UTC_TIME(str(ZuluTime(-600))),
+                                  ASN1F_UTC_TIME, ASN1F_GENERALIZED_TIME),
+                     ASN1F_CHOICE("not_after",
+                                  ASN1_UTC_TIME(str(ZuluTime(+86400))),
+                                  ASN1F_UTC_TIME, ASN1F_GENERALIZED_TIME))
+
+attrName_mapping = [
+        ("countryName"               , "C"),
+        ("stateOrProvinceName"       , "ST"),
+        ("localityName"              , "L"),
+        ("organizationName"          , "O"),
+        ("organizationUnitName"      , "OU"),
+        ("commonName"                , "CN")
+        ]
+attrName_specials = [name for name, symbol in attrName_mapping]
+
+class X509_TBSCertificate(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_enum_INTEGER("version", 0x2, ["v1", "v2", "v3"],
+                                           explicit_tag=0xa0)),
+                    ASN1F_INTEGER("serialNumber", 1),
+                    ASN1F_PACKET("signature",
+                                 X509_AlgorithmIdentifier(),
+                                 X509_AlgorithmIdentifier),
+                    ASN1F_SEQUENCE_OF("issuer", default_issuer, X509_RDN),
+                    ASN1F_PACKET("validity",
+                                 X509_Validity(),
+                                 X509_Validity),
+                    ASN1F_SEQUENCE_OF("subject", default_subject, X509_RDN),
+                    ASN1F_PACKET("subjectPublicKeyInfo",
+                                 X509_SubjectPublicKeyInfo(),
+                                 X509_SubjectPublicKeyInfo),
+                    ASN1F_optional(
+                        ASN1F_BIT_STRING("issuerUniqueID", None,
+                                         implicit_tag=0x81)),
+                    ASN1F_optional(
+                        ASN1F_BIT_STRING("subjectUniqueID", None,
+                                         implicit_tag=0x82)),
+                    ASN1F_optional(
+                           ASN1F_SEQUENCE_OF("extensions",
+                                             [X509_Extension()],
+                                             X509_Extension,
+                                             explicit_tag=0xa3)))
+    def get_issuer(self):
+        attrs = self.issuer
+        attrsDict = {}
+        for attr in attrs:
+            # we assume there is only one name in each rdn ASN1_SET
+            attrsDict[attr.rdn[0].type.oidname] = attr.rdn[0].value.val
+        return attrsDict
+    def get_issuer_str(self):
+        """
+        Returns a one-line string containing every type/value
+        in a rather specific order. sorted() built-in ensures unicity.
+        """
+        name_str = ""
+        attrsDict = self.get_issuer()
+        for attrType, attrSymbol in attrName_mapping:
+            if attrType in attrsDict:
+                name_str += "/" + attrSymbol + "="
+                name_str += attrsDict[attrType]
+        for attrType in sorted(attrsDict):
+            if attrType not in attrName_specials:
+                name_str += "/" + attrType + "="
+                name_str += attrsDict[attrType]
+        return name_str
+    def get_subject(self):
+        attrs = self.subject
+        attrsDict = {}
+        for attr in attrs:
+            # we assume there is only one name in each rdn ASN1_SET
+            attrsDict[attr.rdn[0].type.oidname] = attr.rdn[0].value.val
+        return attrsDict
+    def get_subject_str(self):
+        name_str = ""
+        attrsDict = self.get_subject()
+        for attrType, attrSymbol in attrName_mapping:
+            if attrType in attrsDict:
+                name_str += "/" + attrSymbol + "="
+                name_str += attrsDict[attrType]
+        for attrType in sorted(attrsDict):
+            if attrType not in attrName_specials:
+                name_str += "/" + attrType + "="
+                name_str += attrsDict[attrType]
+        return name_str
+
+class ASN1F_X509_CertECDSA(ASN1F_SEQUENCE):
+    def __init__(self, **kargs):
+        seq = [ASN1F_PACKET("tbsCertificate",
+                            X509_TBSCertificate(),
+                            X509_TBSCertificate),
+               ASN1F_PACKET("signatureAlgorithm",
+                            X509_AlgorithmIdentifier(),
+                            X509_AlgorithmIdentifier),
+               ASN1F_BIT_STRING_ENCAPS("signatureValue",
+                            ECDSASignature(),
+                            ECDSASignature)]
+        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
+
+class ASN1F_X509_Cert(ASN1F_SEQUENCE):
+    def __init__(self, **kargs):
+        seq = [ASN1F_PACKET("tbsCertificate",
+                            X509_TBSCertificate(),
+                            X509_TBSCertificate),
+               ASN1F_PACKET("signatureAlgorithm",
+                            X509_AlgorithmIdentifier(),
+                            X509_AlgorithmIdentifier),
+               ASN1F_BIT_STRING("signatureValue",
+                                "defaultsignature"*2)]
+        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
+    def m2i(self, pkt, x):
+        c,s = ASN1F_SEQUENCE.m2i(self, pkt, x)
+        sigtype = pkt.fields["signatureAlgorithm"].algorithm.oidname
+        if "rsa" in sigtype.lower():
+            return c,s
+        elif "ecdsa" in sigtype.lower():
+            return ASN1F_X509_CertECDSA().m2i(pkt, x)
+        else:
+            raise Exception("could not parse certificate")
+    def dissect(self, pkt, s):
+        c,x = self.m2i(pkt, s)
+        return x
+    def build(self, pkt):
+        if "signatureAlgorithm" in pkt.fields:
+            sigtype = pkt.fields['signatureAlgorithm'].algorithm.oidname
+        else:
+            sigtype = pkt.default_fields["signatureAlgorithm"].algorithm.oidname
+        if "rsa" in sigtype.lower():
+            return ASN1F_SEQUENCE.build(self, pkt)
+        elif "ecdsa" in sigtype.lower():
+            pkt.default_fields["signatureValue"] = ECDSASignature()
+            return ASN1F_X509_CertECDSA().build(pkt)
+        else:
+            raise Exception("could not build certificate")
+
+class X509_Cert(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_X509_Cert()
+
+
+####### TBSCertList & CRL #######
+
+class X509_RevokedCertificate(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(ASN1F_INTEGER("serialNumber", 1),
+                               ASN1F_UTC_TIME("revocationDate",
+                                              str(ZuluTime(+86400))),
+                               ASN1F_optional(
+                                   ASN1F_SEQUENCE_OF("crlEntryExtensions",
+                                                     None, X509_Extension)))
+
+class X509_TBSCertList(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_SEQUENCE(
+                    ASN1F_optional(
+                        ASN1F_enum_INTEGER("version", 1, ["v1", "v2"])),
+                    ASN1F_PACKET("signature",
+                                 X509_AlgorithmIdentifier(),
+                                 X509_AlgorithmIdentifier),
+                    ASN1F_SEQUENCE_OF("issuer", default_issuer, X509_RDN),
+                    ASN1F_UTC_TIME("this_update", str(ZuluTime(-1))),
+                    ASN1F_optional(
+                        ASN1F_UTC_TIME("next_update", None)),
+                    ASN1F_optional(
+                        ASN1F_SEQUENCE_OF("revokedCertificates", None,
+                                          X509_RevokedCertificate)),
+                    ASN1F_optional(
+                              ASN1F_SEQUENCE_OF("crlExtensions", None,
+                                                X509_Extension,
+                                                explicit_tag=0xa0)))
+    def get_issuer(self):
+        attrs = self.issuer
+        attrsDict = {}
+        for attr in attrs:
+            # we assume there is only one name in each rdn ASN1_SET
+            attrsDict[attr.rdn[0].type.oidname] = attr.rdn[0].value.val
+        return attrsDict
+    def get_issuer_str(self):
+        """
+        Returns a one-line string containing every type/value
+        in a rather specific order. sorted() built-in ensures unicity.
+        """
+        name_str = ""
+        attrsDict = self.get_issuer()
+        for attrType, attrSymbol in attrName_mapping:
+            if attrType in attrsDict:
+                name_str += "/" + attrSymbol + "="
+                name_str += attrsDict[attrType]
+        for attrType in sorted(attrsDict):
+            if attrType not in attrName_specials:
+                name_str += "/" + attrType + "="
+                name_str += attrsDict[attrType]
+        return name_str
+
+class ASN1F_X509_CRLECDSA(ASN1F_SEQUENCE):
+    def __init__(self, **kargs):
+        seq = [ASN1F_PACKET("tbsCertList",
+                            X509_TBSCertList(),
+                            X509_TBSCertList),
+               ASN1F_PACKET("signatureAlgorithm",
+                            X509_AlgorithmIdentifier(),
+                            X509_AlgorithmIdentifier),
+               ASN1F_BIT_STRING_ENCAPS("signatureValue",
+                            ECDSASignature(),
+                            ECDSASignature)]
+        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
+
+class ASN1F_X509_CRL(ASN1F_SEQUENCE):
+    def __init__(self, **kargs):
+        seq = [ASN1F_PACKET("tbsCertList",
+                            X509_TBSCertList(),
+                            X509_TBSCertList),
+               ASN1F_PACKET("signatureAlgorithm",
+                            X509_AlgorithmIdentifier(),
+                            X509_AlgorithmIdentifier),
+               ASN1F_BIT_STRING("signatureValue",
+                                "defaultsignature"*2)]
+        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
+    def m2i(self, pkt, x):
+        c,s = ASN1F_SEQUENCE.m2i(self, pkt, x)
+        sigtype = pkt.fields["signatureAlgorithm"].algorithm.oidname
+        if "rsa" in sigtype.lower():
+            return c,s
+        elif "ecdsa" in sigtype.lower():
+            return ASN1F_X509_CRLECDSA().m2i(pkt, x)
+        else:
+            raise Exception("could not parse certificate")
+    def dissect(self, pkt, s):
+        c,x = self.m2i(pkt, s)
+        return x
+    def build(self, pkt):
+        if "signatureAlgorithm" in pkt.fields:
+            sigtype = pkt.fields['signatureAlgorithm'].algorithm.oidname
+        else:
+            sigtype = pkt.default_fields["signatureAlgorithm"].algorithm.oidname
+        if "rsa" in sigtype.lower():
+            return ASN1F_SEQUENCE.build(self, pkt)
+        elif "ecdsa" in sigtype.lower():
+            pkt.default_fields["signatureValue"] = ECDSASignature()
+            return ASN1F_X509_CRLECDSA().build(pkt)
+        else:
+            raise Exception("could not build certificate")
+
+class X509_CRL(ASN1_Packet):
+    ASN1_codec = ASN1_Codecs.BER
+    ASN1_root = ASN1F_X509_CRL()
 
diff --git a/scapy/volatile.py b/scapy/volatile.py
index 8d8d4ad76c75e53fa1693a4be4f69fc9ffffebf9..1a1f00024a80f8f14f1c423094113883f3bbe25f 100644
--- a/scapy/volatile.py
+++ b/scapy/volatile.py
@@ -642,10 +642,19 @@ class IntAutoTime(AutoTime):
 
 
 class ZuluTime(AutoTime):
-    def __init__(self, diff=None):
-        self.diff=diff
+    def __init__(self, diff=0):
+        self.diff = diff
     def _fix(self):
-        return time.strftime("%y%m%d%H%M%SZ",time.gmtime(time.time()+self.diff))
+        return time.strftime("%y%m%d%H%M%SZ",
+                             time.gmtime(time.time() + self.diff))
+
+
+class GeneralizedTime(AutoTime):
+    def __init__(self, diff=0):
+        self.diff = diff
+    def _fix(self):
+        return time.strftime("%Y%m%d%H%M%SZ",
+                             time.gmtime(time.time() + self.diff))
 
 
 class DelayedEval(VolatileValue):
diff --git a/test/regression.uts b/test/regression.uts
index af22f521ec7d1f3942fb1d629f4e5909ac03cbcf..3cf4b298e4a57fda22d9f9297ac961509f19bedf 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -540,103 +540,6 @@ assert(x.PDU.varbindlist[0].value == "172.31.19.2")
 assert(x.PDU.varbindlist[2].oid == "1.3.6.1.4.1.253.8.64.4.2.1.5.10.14130400")
 assert(x.PDU.varbindlist[2].value == 1)
 
-############
-############
-+ X509 tests
-
-= X509 certificate assembling
-~ X509 ASN1
-c=X509Cert( pubkey='\x00'+str(ASN1_SEQUENCE([ASN1_INTEGER(1),ASN1_INTEGER(2)])), signature="xxxxxx")
-c.show()
-str(c) == str(X509Cert(str(c)))
-
-= Small X509 certificate disassembling
-~ X509 ASN1
-* This cert has neither the version field nor X509v3 extensions
-small="""MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgw
-FgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRy
-dXN0IFJvb3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQsw
-CQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQD
-ExNHVEUgQ3liZXJUcnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8K
-DPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPw
-KfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44AwID
-AQABMA0GCSqGSIb3DQEBBAUAA4GBABKzdcZfHeFhVYAA1IFLezEPI2PnPfMD
- +fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWlIjeaY8JIILTbcuPI9tl8vrGv
-U9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9ApybW1EDp3zdHSo1TRJ6V6e
-6bR64eVaH4QwnNOfpSXY """.decode("base64")
-c = X509Cert(small)
-c.show()
-assert( str(c) == small )
-assert( c.version == None )
-assert( c.sn == 419 )
-assert( "/".join(rdn.value.val for rdn in c.issuer) == "US/GTE Corporation/GTE CyberTrust Root")
-assert( c.not_after == '060223235900Z' )
-assert( c.x509v3ext == None )
-assert( c.signature == '\x00\x12\xb3u\xc6_\x1d\xe1aU\x80\x00\xd4\x81K{1\x0f#c\xe7=\xf3\x03\xf9\xf46\xa8\xbb\xd9\xe3\xa5\x97M\xea+)\xe0\xd6js\x81\xe6\xc0\x89\xa3\xd3\xf1\xe0\xa5\xa5"7\x9ac\xc2H \xb4\xdbr\xe3\xc8\xf6\xd9|\xbe\xb1\xafS\xda\x14\xb4!\xb8\xd6\xd5\x96\xe3\xfeN\x0cYb\xb6\x9aJ\xf9B\xdd\x8co\x81\xa9q\xff\xf4\nrmmD\x0e\x9d\xf3tt\xa8\xd54I\xe9^\x9e\xe9\xb4z\xe1\xe5Z\x1f\x840\x9c\xd3\x9f\xa5%\xd8' )
-
-
-= Big X509 certificate disassembling
-~ X509 ASN1
-small="""MIIIODCCB6GgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYT
-AkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEu
-MCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5s
-LjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1
-MjE0MDIGA1UECxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9u
-IEF1dGhvcml0eTE0MDIGA1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0
-aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwu
-aXBzLmVzMB4XDTAxMTIyOTAxMTAxOFoXDTI1MTIyNzAxMTAxOFowggEeMQsw
-CQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYDVQQHEwlCYXJj
-ZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5nIFNlcnZp
-Y2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4gIEIt
-NjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3RhbXBpbmcgQ2VydGlm
-aWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBUaW1lc3RhbXBp
-bmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lw
-c0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLju
-VqWajOY2ycJioGaBjRrVetJznw6EZLqVtJCneK/K/lRhW86yIFcBrkSSQxA4
-Efdo/BdApWgnMjvEp+ZCccWZ73b/K5Uk9UmSGGjKALWkWi9uy9YbLA1UZ2t6
-KaFYq6JaANZbuxjC3/YeE1Z2m6Vo4pjOxgOKNNtMg0GmqaMCAwEAAaOCBIAw
-ggR8MB0GA1UdDgQWBBSL0BBQCYHynQnVDmB4AyKiP8jKZjCCAVAGA1UdIwSC
-AUcwggFDgBSL0BBQCYHynQnVDmB4AyKiP8jKZqGCASakggEiMIIBHjELMAkG
-A1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vs
-b25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNl
-cyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYw
-OTI5NDUyMTQwMgYDVQQLEytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5MTQwMgYDVQQDEytJUFMgQ0EgVGltZXN0YW1waW5n
-IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNA
-bWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsG
-A1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUF
-BwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGC
-NwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMw
-EYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlwcy5l
-czBHBglghkgBhvhCAQ0EOhY4VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl
-IGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgECBBwW
-Gmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMEAGCWCGSAGG+EIBBAQzFjFo
-dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcu
-Y3JsMEUGCWCGSAGG+EIBAwQ4FjZodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAy
-L3Jldm9jYXRpb25UaW1lc3RhbXBpbmcuaHRtbD8wQgYJYIZIAYb4QgEHBDUW
-M2h0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmVuZXdhbFRpbWVzdGFtcGlu
-Zy5odG1sPzBABglghkgBhvhCAQgEMxYxaHR0cDovL3d3dy5pcHMuZXMvaXBz
-MjAwMi9wb2xpY3lUaW1lc3RhbXBpbmcuaHRtbDB/BgNVHR8EeDB2MDegNaAz
-hjFodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBp
-bmcuY3JsMDugOaA3hjVodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9p
-cHMyMDAyVGltZXN0YW1waW5nLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYB
-BQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEA
-ZbrBzAAalZHK6Ww6vzoeFAh8+4Pua2JR0zORtWB5fgTYXXk36MNbsMRnLWha
-sl8OCvrNPzpFoeo2zyYepxEoxZSPhExTCMWTs/zif/WN87GphV+I3pGW7hdb
-rqXqcGV4LCFkAZXOzkw+UPS2Wctjjba9GNSHSl/c7+lW8AoM6HU= """.decode("base64")
-c = X509Cert(small)
-c.show()
-assert( str(c) == small )
-assert( c.version == 2 )
-assert( c.sn == ASN1_NULL(0) )
-assert( "/".join(rdn.value.val for rdn in c.issuer if isinstance(rdn.value,ASN1_PRINTABLE_STRING)) == "ES/Barcelona/Barcelona/IPS Internet publishing Services s.l./IPS CA Timestamping Certification Authority/IPS CA Timestamping Certification Authority")
-assert( c.not_after == '251227011018Z' )
-assert( len(c.x509v3ext) == 16 )
-assert( c.signature == '\x00e\xba\xc1\xcc\x00\x1a\x95\x91\xca\xe9l:\xbf:\x1e\x14\x08|\xfb\x83\xeekbQ\xd33\x91\xb5`y~\x04\xd8]y7\xe8\xc3[\xb0\xc4g-hZ\xb2_\x0e\n\xfa\xcd?:E\xa1\xea6\xcf&\x1e\xa7\x11(\xc5\x94\x8f\x84LS\x08\xc5\x93\xb3\xfc\xe2\x7f\xf5\x8d\xf3\xb1\xa9\x85_\x88\xde\x91\x96\xee\x17[\xae\xa5\xeapex,!d\x01\x95\xce\xceL>P\xf4\xb6Y\xcbc\x8d\xb6\xbd\x18\xd4\x87J_\xdc\xef\xe9V\xf0\n\x0c\xe8u' )
-
-
-
 
 ############
 ############
@@ -658,7 +561,6 @@ dns_ans = sr1(IP(dst="resolver1.opendns.com")/UDP()/DNS(rd=1,qd=DNSQR(qname="www
 DNS in dns_ans
 
 
-
 ############
 ############
 + More complex tests
diff --git a/test/x509.uts b/test/x509.uts
new file mode 100644
index 0000000000000000000000000000000000000000..3505c10d99a0487795b51f2128b27e307474b0e5
--- /dev/null
+++ b/test/x509.uts
@@ -0,0 +1,183 @@
+% Tests for X.509 objects
+# 
+# Launch me with:
+# sudo bash test/run_tests -t test/x509.uts -F
+
+########### Key class ###############################################
+
++ Private RSA & ECDSA keys class tests
+= Key class : Importing DER encoded RSA private key
+k='MIIEowIBAAKCAQEAmFdqP+nTEZukS0lLP+yj1gNImsEIf7P2ySTunceYxwkm4VE5QReDbb2L5/HL\nA9pPmIeQLSq/BgO1meOcbOSJ2YVHQ28MQ56+8Crb6n28iycX4hp0H3AxRAjh0edX+q3yilvYJ4W9\n/NnIb/wAZwS0oJif/tTkVF77HybAfJde5Eqbp+bCKIvMWnambh9DRUyjrBBZo5dA1o32zpuFBrJd\nI8dmUpw9gtf0F0Ba8lGZm8Uqc0GyXeXOJUE2u7CiMu3M77BM6ZLLTcow5+bQImkmTL1SGhzwfinM\nE1e6p3Hm//pDjuJvFaY22k05LgLuyqc59vFiB3Toldz8+AbMNjvzAwIDAQABAoIBAH3KeJZL2hhI\n/1GXNMaU/PfDgFkgmYbxMA8JKusnm/SFjxAwBGnGI6UjBXpBgpQs2Nqm3ZseF9u8hmCKvGiCEX2G\nesCo2mSfmSQxD6RBrMTuQ99UXpxzBIscFnM/Zrs8lPBARGzmF2nI3qPxXtex4ABX5o0Cd4NfZlZj\npj96skUoO8+bd3I4OPUFYFFFuv81LoSQ6Hew0a8xtJXtKkDp9h1jTGGUOc189WACNoBLH0MGeVoS\nUfc1++RcC3cypUZ8fNP1OO6GBfv06f5oXES4ZbxGYpa+nCfNwb6V2gWbkvaYm7aFn0KWGNZXS1P3\nOcWv6IWdOmg2CI7MMBLJ0LyWVCECgYEAyMJYw195mvHl8VyxJ3HkxeQaaozWL4qhNQ0Kaw+mzD+j\nYdkbHb3aBYghsgEDZjnyOVblC7I+4smvAZJLWJaf6sZ5HAw3zmj1ibCkXx7deoRc/QVcOikl3dE/\nymO0KGJNiGzJZmxbRS3hTokmVPuxSWW4p5oSiMupFHKa18Uv8DECgYEAwkJ7iTOUL6b4e3lQuHQn\nJbsiQpd+P/bsIPP7kaaHObewfHpfOOtIdtN4asxVFf/PgW5uWmBllqAHZYR14DEYIdL+hdLrdvk5\nnYQ3YfhOnp+haHUPCdEiXrRZuGXjmMA4V0hL3HPF5ZM8H80fLnN8Pgn2rIC7CZQ46y4PnoV1nXMC\ngYBBwCUCF8rkDEWa/ximKo8aoNJmAypC98xEa7j1x3KBgnYoHcrbusok9ajTe7F5UZEbZnItmnsu\nG4/Nm/RBV1OYuNgBb573YzjHl6q93IX9EkzCMXc7NS7JrzaNOopOj6OFAtwTR3m89oHMDu8W9jfi\nKgaIHdXkJ4+AuugrstE4gQKBgFK0d1/8g7SeA+Cdz84YNaqMt5NeaDPXbsTA23QxUBU0rYDxoKTd\nFybv9a6SfA83sCLM31K/A8FTNJL2CDGA9WNBL3fOSs2GYg88AVBGpUJHeDK+0748OcPUSPaG+pVI\nETSn5RRgffq16r0nWYUvSdAn8cuTqw3y+yC1pZS6AU8dAoGBAL5QCi0dTWKN3kf3cXaCAnYiWe4Q\ng2S+SgLE+F1U4Xws2rqAuSvIiuT5i5+Mqk9ZCGdoReVbAovJFoRqe7Fj9yWM+b1awGjL0bOTtnqx\n0iljob6uFyhpl1xgW3a3ICJ/ZYLvkgb4IBEteOwWpp37fX57vzhW8EmUV2UX7ve1uNRI'.decode('base64')
+x=RSAPrivateKey(k)
+
+= Key class : key version
+x.version == ASN1_INTEGER(0L)
+
+= Key class : key modulus
+x.modulus == ASN1_INTEGER(19231328316532061413420367242571475005688288081144416166988378525696075445024135424022026378563116068168327239354659928492979285632474448448624869172454076124150405352043642781483254546569202103296262513098482624188672299255268092629150366527784294463900039290024710152521604731213565912934889752122898104556895316819303096201441834849255370122572613047779766933573375974464479123135292080801384304131606933504677232323037116557327478512106367095125103346134248056463878553619525193565824925835325216545121044922690971718737998420984924512388011040969150550056783451476150234324593710633552558175109683813482739004163L)
+
+= Key class : key public exponent
+x.publicExponent == ASN1_INTEGER(65537L)
+
+= Key class : key private exponent
+x.privateExponent == ASN1_INTEGER(15879630313397508329451198152673380989865598204237760057319927734227125481903063742175442230739018051313441697936698689753842471306305671266572085925009572141819112648211571007521954312641597446020984266846581125287547514750428503480880603089110687015181510081018160579576523796170439894692640171752302225125980423560965987469457505107324833137678663960560798216976668670722016960863268272661588745006387723814962668678285659376534048525020951633874488845649968990679414325096323920666486328886913648207836459784281744709948801682209478580185160477801656666089536527545026197569990716720623647770979759861119273292833L)
+
+= Key class : key prime1
+x.prime1 == ASN1_INTEGER(140977881300857803928857666115326329496639762170623218602431133528876162476487960230341078724702018316260690172014674492782486113504117653531825010840338251572887403113276393351318549036549656895326851872473595350667293402676143426484331639796163189182788306480699144107905869179435145810212051656274284113969L)
+
+= Key class : key prime2
+x.prime2 == ASN1_INTEGER(136413798668820291889092636919077529673097927884427227010121877374504825870002258140616512268521246045642663981036167305976907058413796938050224182519965099316625879807962173794483933183111515251808827349718943344770056106787713032506379905031673992574818291891535689493330517205396872699985860522390496583027L)
+
+= Key class : key exponent1
+x.exponent1 == ASN1_INTEGER(46171616708754015342920807261537213121074749458020000367465429453038710215532257783908950878847126373502288079285334594398328912526548076894076506899568491565992572446455658740752572386903609191774044411412991906964352741123956581870694330173563737928488765282233340389888026245745090096745219902501964298369L)
+
+= Key class : key exponent2
+x.exponent2 == ASN1_INTEGER(58077388505079936284685944662039782610415160654764308528562806086690474868010482729442634318267235411531220690585030443434512729356878742778542733733189895801341155353491318998637269079682889033003797865508917973141494201620317820971253064836562060222814287812344611566640341960495346782352037479526674026269L)
+
+= Key class : key coefficient
+x.coefficient == ASN1_INTEGER(133642091354977099805228515340626956943759840737228695249787077343495440064451558090846230978708992851702164116059746794777336918772240719297253693109788134358485382183551757562334253896010728509892421673776502933574360356472723011839127418477652997263867089539752161307227878233961465798519818890416647361608L)
+
+
+########### Cert class ##############################################
+
++ X509_Cert class tests
+= Cert class : Importing DER encoded X.509 Certificate with RSA public key
+c='MIIFEjCCA/qgAwIBAgIJALRecEPnCQtxMA0GCSqGSIb3DQEBBQUAMIG2MQswCQYDVQQGEwJGUjEO\nMAwGA1UECBMFUGFyaXMxDjAMBgNVBAcTBVBhcmlzMRcwFQYDVQQKEw5NdXNocm9vbSBDb3JwLjEe\nMBwGA1UECxMVTXVzaHJvb20gVlBOIFNlcnZpY2VzMSUwIwYDVQQDExxJS0V2MiBYLjUwOSBUZXN0\nIGNlcnRpZmljYXRlMScwJQYJKoZIhvcNAQkBFhhpa2V2Mi10ZXN0QG11c2hyb29tLmNvcnAwHhcN\nMDYwNzEzMDczODU5WhcNMjYwMzMwMDczODU5WjCBtjELMAkGA1UEBhMCRlIxDjAMBgNVBAgTBVBh\ncmlzMQ4wDAYDVQQHEwVQYXJpczEXMBUGA1UEChMOTXVzaHJvb20gQ29ycC4xHjAcBgNVBAsTFU11\nc2hyb29tIFZQTiBTZXJ2aWNlczElMCMGA1UEAxMcSUtFdjIgWC41MDkgVGVzdCBjZXJ0aWZpY2F0\nZTEnMCUGCSqGSIb3DQEJARYYaWtldjItdGVzdEBtdXNocm9vbS5jb3JwMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAmFdqP+nTEZukS0lLP+yj1gNImsEIf7P2ySTunceYxwkm4VE5QReD\nbb2L5/HLA9pPmIeQLSq/BgO1meOcbOSJ2YVHQ28MQ56+8Crb6n28iycX4hp0H3AxRAjh0edX+q3y\nilvYJ4W9/NnIb/wAZwS0oJif/tTkVF77HybAfJde5Eqbp+bCKIvMWnambh9DRUyjrBBZo5dA1o32\nzpuFBrJdI8dmUpw9gtf0F0Ba8lGZm8Uqc0GyXeXOJUE2u7CiMu3M77BM6ZLLTcow5+bQImkmTL1S\nGhzwfinME1e6p3Hm//pDjuJvFaY22k05LgLuyqc59vFiB3Toldz8+AbMNjvzAwIDAQABo4IBHzCC\nARswHQYDVR0OBBYEFPPYTt6Q9+Zd0s4zzVxWjG+XFDFLMIHrBgNVHSMEgeMwgeCAFPPYTt6Q9+Zd\n0s4zzVxWjG+XFDFLoYG8pIG5MIG2MQswCQYDVQQGEwJGUjEOMAwGA1UECBMFUGFyaXMxDjAMBgNV\nBAcTBVBhcmlzMRcwFQYDVQQKEw5NdXNocm9vbSBDb3JwLjEeMBwGA1UECxMVTXVzaHJvb20gVlBO\nIFNlcnZpY2VzMSUwIwYDVQQDExxJS0V2MiBYLjUwOSBUZXN0IGNlcnRpZmljYXRlMScwJQYJKoZI\nhvcNAQkBFhhpa2V2Mi10ZXN0QG11c2hyb29tLmNvcnCCCQC0XnBD5wkLcTAMBgNVHRMEBTADAQH/\nMA0GCSqGSIb3DQEBBQUAA4IBAQA2zt0BvXofiVvHMWlftZCstQaawej1SmxrAfDB4NUM24NsG+UZ\nI88XA5XM6QolmfyKnNromMLC1+6CaFxjq3jC/qdS7ifalFLQVo7ik/te0z6Olo0RkBNgyagWPX2L\nR5kHe9RvSDuoPIsbSHMmJA98AZwatbvEhmzMINJNUoHVzhPeHZnIaBgUBg02XULk/ElidO51Rf3g\nh8dR/kgFQSQT687vs1x9TWD00z0Q2bs2UF3Ob3+NYkEGEo5F9RePQm0mY94CT2xs6WpHo060Fo7f\nVpAFktMWx1vpu+wsEbQAhgGqV0fCR2QwKDIbTrPW/p9HJtJDYVjYdAFxr3s7V77y'.decode('base64')
+x=X509_Cert(c)
+
+= Cert class : Rebuild certificate
+str(x) == c
+
+= Cert class : Version
+tbs = x.tbsCertificate
+tbs.version == ASN1_INTEGER(2L)
+
+= Cert class : Serial
+tbs.serialNumber == ASN1_INTEGER(0xb45e7043e7090b71)
+
+= Cert class : Signature algorithm (as advertised by TBSCertificate)
+assert(type(tbs.signature) is X509_AlgorithmIdentifier)
+tbs.signature.algorithm == ASN1_OID("sha1-with-rsa-signature")
+
+= Cert class : Issuer structure
+assert(type(tbs.issuer) is list)
+assert(len(tbs.issuer) == 7)
+assert(type(tbs.issuer[0]) is X509_RDN)
+assert(type(tbs.issuer[0].rdn) is list)
+assert(type(tbs.issuer[0].rdn[0]) is X509_AttributeTypeAndValue)
+
+= Cert class : Issuer first attribute
+tbs.issuer[0].rdn[0].type == ASN1_OID("countryName") and tbs.issuer[0].rdn[0].value == ASN1_PRINTABLE_STRING("FR")
+
+= Cert class : Issuer string
+tbs.get_issuer_str() == '/C=FR/ST=Paris/L=Paris/O=Mushroom Corp./OU=Mushroom VPN Services/CN=IKEv2 X.509 Test certificate/emailAddress=ikev2-test@mushroom.corp'
+
+= Cert class : Validity
+assert(type(tbs.validity) is X509_Validity)
+tbs.validity.not_before == ASN1_UTC_TIME("060713073859Z") and tbs.validity.not_after == ASN1_UTC_TIME("260330073859Z")
+
+= Cert class : Subject structure
+assert(type(tbs.subject) is list)
+assert(len(tbs.subject) == 7)
+assert(type(tbs.subject[0]) is X509_RDN)
+assert(type(tbs.subject[0].rdn) is list)
+assert(type(tbs.subject[0].rdn[0]) is X509_AttributeTypeAndValue)
+
+= Cert class : Subject last attribute
+tbs.issuer[6].rdn[0].type == ASN1_OID("emailAddress") and tbs.issuer[6].rdn[0].value == ASN1_IA5_STRING("ikev2-test@mushroom.corp")
+
+= Cert class : Subject string
+tbs.get_subject_str() == '/C=FR/ST=Paris/L=Paris/O=Mushroom Corp./OU=Mushroom VPN Services/CN=IKEv2 X.509 Test certificate/emailAddress=ikev2-test@mushroom.corp'
+
+= Cert class : SubjectPublicKey algorithm
+assert(type(tbs.subjectPublicKeyInfo) is X509_SubjectPublicKeyInfo)
+spki = tbs.subjectPublicKeyInfo
+spki.signatureAlgorithm.algorithm == ASN1_OID("rsaEncryption")
+
+= Cert class : SubjectPublicKey value
+assert(type(spki.subjectPublicKey) is RSAPublicKey)
+spki.subjectPublicKey.modulus == ASN1_INTEGER(19231328316532061413420367242571475005688288081144416166988378525696075445024135424022026378563116068168327239354659928492979285632474448448624869172454076124150405352043642781483254546569202103296262513098482624188672299255268092629150366527784294463900039290024710152521604731213565912934889752122898104556895316819303096201441834849255370122572613047779766933573375974464479123135292080801384304131606933504677232323037116557327478512106367095125103346134248056463878553619525193565824925835325216545121044922690971718737998420984924512388011040969150550056783451476150234324593710633552558175109683813482739004163L) and spki.subjectPublicKey.publicExponent == ASN1_INTEGER(65537L)
+
+= Cert class : Extensions structure
+ext = tbs.extensions
+assert(type(ext) is list)
+assert(len(ext) == 3)
+
+= Cert class : Subject key identifier extension info
+assert(type(ext[0]) is X509_Extension)
+ext[0].extnID == ASN1_OID("subjectKeyIdentifier") and ext[0].critical == None
+
+= Cert class : Subject key identifier extension value
+assert(type(ext[0].extnValue) is X509_ExtSubjectKeyIdentifier)
+ext[0].extnValue.keyIdentifier == ASN1_STRING('\xf3\xd8N\xde\x90\xf7\xe6]\xd2\xce3\xcd\\V\x8co\x97\x141K')
+
+= Cert class : Signature algorithm
+assert(type(x.signatureAlgorithm) is X509_AlgorithmIdentifier)
+x.signatureAlgorithm.algorithm == ASN1_OID("sha1-with-rsa-signature")
+
+= Cert class : Signature value
+x.signatureValue == ASN1_BIT_STRING("6\xce\xdd\x01\xbdz\x1f\x89[\xc71i_\xb5\x90\xac\xb5\x06\x9a\xc1\xe8\xf5Jlk\x01\xf0\xc1\xe0\xd5\x0c\xdb\x83l\x1b\xe5\x19#\xcf\x17\x03\x95\xcc\xe9\n%\x99\xfc\x8a\x9c\xda\xe8\x98\xc2\xc2\xd7\xee\x82h\\c\xabx\xc2\xfe\xa7R\xee'\xda\x94R\xd0V\x8e\xe2\x93\xfb^\xd3>\x8e\x96\x8d\x11\x90\x13`\xc9\xa8\x16=}\x8bG\x99\x07{\xd4oH;\xa8<\x8b\x1bHs&$\x0f|\x01\x9c\x1a\xb5\xbb\xc4\x86l\xcc \xd2MR\x81\xd5\xce\x13\xde\x1d\x99\xc8h\x18\x14\x06\r6]B\xe4\xfcIbt\xeeuE\xfd\xe0\x87\xc7Q\xfeH\x05A$\x13\xeb\xce\xef\xb3\\}M`\xf4\xd3=\x10\xd9\xbb6P]\xceo\x7f\x8dbA\x06\x12\x8eE\xf5\x17\x8fBm&c\xde\x02Oll\xe9jG\xa3N\xb4\x16\x8e\xdfV\x90\x05\x92\xd3\x16\xc7[\xe9\xbb\xec,\x11\xb4\x00\x86\x01\xaaWG\xc2Gd0(2\x1bN\xb3\xd6\xfe\x9fG&\xd2CaX\xd8t\x01q\xaf{;W\xbe\xf2", readable=True)
+
+= Cert class : Default X509_Cert from scratch
+str(X509_Cert(str(X509_Cert()))) == str(X509_Cert())
+
+
+############ CRL class ###############################################
+
++ X509_CRL class tests
+= CRL class : Importing DER encoded X.509 CRL
+c='MIICHjCCAYcwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWdu\nLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\naG9yaXR5Fw0wNjExMDIwMDAwMDBaFw0wNzAyMTcyMzU5NTlaMIH2MCECECzSS2LEl6QXzW6jyJx6\nLcgXDTA0MDQwMTE3NTYxNVowIQIQOkXeVssCzdzcTndjIhvU1RcNMDEwNTA4MTkyMjM0WjAhAhBB\nXYg2gRUg1YCDRqhZkngsFw0wMTA3MDYxNjU3MjNaMCECEEc5gf/9hIHxlfnrGMJ8DfEXDTAzMDEw\nOTE4MDYxMlowIQIQcFR+auK62HZ/R6mZEEFeZxcNMDIwOTIzMTcwMDA4WjAhAhB+C13eGPI5ZoKm\nj2UiOCPIFw0wMTA1MDgxOTA4MjFaMCICEQDQVEhgGGfTrTXKLw1KJ5VeFw0wMTEyMTExODI2MjFa\nMA0GCSqGSIb3DQEBBQUAA4GBACLJ9rsdoaU9JMf/sCIRs3AGW8VV3TN2oJgiCGNEac9PRyV3mRKE\n0hmuIJTKLFSaa4HSAzimWpWNKuJhztsZzXUnWSZ8VuHkgHEaSbKqzUlb2g+o/848CvzJrcbeyEBk\nDCYJI5C3nLlQA49LGJ+w4GUPYBwaZ+WFxCX1C8kzglLm'.decode('base64')
+x=X509_CRL(c)
+
+= CRL class : Rebuild crl
+str(x) == c
+
+= CRL class : Version
+tbs = x.tbsCertList
+tbs.version == None
+
+= CRL class : Signature algorithm (as advertised by TBSCRLificate)
+assert(type(tbs.signature) is X509_AlgorithmIdentifier)
+tbs.signature.algorithm == ASN1_OID("sha1-with-rsa-signature")
+
+= CRL class : Issuer structure
+assert(type(tbs.issuer) is list)
+assert(len(tbs.issuer) == 3)
+assert(type(tbs.issuer[0]) is X509_RDN)
+assert(type(tbs.issuer[0].rdn) is list)
+assert(type(tbs.issuer[0].rdn[0]) is X509_AttributeTypeAndValue)
+
+= CRL class : Issuer first attribute
+tbs.issuer[0].rdn[0].type == ASN1_OID("countryName") and tbs.issuer[0].rdn[0].value == ASN1_PRINTABLE_STRING("US")
+
+= CRL class : Issuer string
+tbs.get_issuer_str() == '/C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority'
+
+= CRL class : This update
+tbs.this_update == ASN1_UTC_TIME("061102000000Z")
+
+= CRL class : Optional next update
+tbs.next_update == ASN1_UTC_TIME("070217235959Z")
+
+= CRL class : Optional revoked_certificates structure
+assert(type(tbs.revokedCertificates) is list)
+assert(len(tbs.revokedCertificates) == 7)
+assert(type(tbs.revokedCertificates[0]) is X509_RevokedCertificate)
+
+= CRL class : Revoked_certificates first attribute
+tbs.revokedCertificates[0].serialNumber == ASN1_INTEGER(59577943160751197113872490992424857032L) and tbs.revokedCertificates[0].revocationDate == ASN1_UTC_TIME("040401175615Z")
+
+= CRL class : Extensions structure
+tbs.crlExtensions == None
+
+= CRL class : Signature algorithm
+assert(type(x.signatureAlgorithm) is X509_AlgorithmIdentifier)
+x.signatureAlgorithm.algorithm == ASN1_OID("sha1-with-rsa-signature")
+
+= CRL class : Signature value
+x.signatureValue == ASN1_BIT_STRING('"\xc9\xf6\xbb\x1d\xa1\xa5=$\xc7\xff\xb0"\x11\xb3p\x06[\xc5U\xdd3v\xa0\x98"\x08cDi\xcfOG%w\x99\x12\x84\xd2\x19\xae \x94\xca,T\x9ak\x81\xd2\x038\xa6Z\x95\x8d*\xe2a\xce\xdb\x19\xcdu\'Y&|V\xe1\xe4\x80q\x1aI\xb2\xaa\xcdI[\xda\x0f\xa8\xff\xce<\n\xfc\xc9\xad\xc6\xde\xc8@d\x0c&\t#\x90\xb7\x9c\xb9P\x03\x8fK\x18\x9f\xb0\xe0e\x0f`\x1c\x1ag\xe5\x85\xc4%\xf5\x0b\xc93\x82R\xe6', readable=True)
+
+= CRL class : Default X509_CRL from scratch
+str(X509_CRL(str(X509_CRL()))) == str(X509_CRL())
+
+