Esempio n. 1
0
        private object[] GetData()
        {
            GXAsn1ObjectIdentifier alg;

            if (PublicKey.Scheme == Ecdsa.Enums.Ecc.P256)
            {
                alg = new GXAsn1ObjectIdentifier("1.2.840.10045.3.1.7");
            }
            else
            {
                alg = new GXAsn1ObjectIdentifier("1.3.132.0.34");
            }
            object subjectPKInfo = new GXAsn1BitString(PublicKey.RawValue, 0);

            object[] tmp = new object[] { new GXAsn1ObjectIdentifier("1.2.840.10045.2.1"),
                                          alg };
            GXAsn1Context attributes = new GXAsn1Context();

            foreach (KeyValuePair <PkcsObjectIdentifier, object[]> it in Attributes)
            {
                GXAsn1Sequence s = new GXAsn1Sequence();
                s.Add(new GXAsn1ObjectIdentifier(PkcsObjectIdentifierConverter.GetString(it.Key)));
                //Convert object array to list.
                List <object> values = new List <object>();
                foreach (object v in it.Value)
                {
                    values.Add(v);
                }
                s.Add(new KeyValuePair <object, object>(values, null));
                attributes.Add(s);
            }
            return(new object[] { (sbyte)Version, GXAsn1Converter.EncodeSubject(Subject), new object[] { tmp, subjectPKInfo }, attributes });
        }
Esempio n. 2
0
        private static void GetValue(GXByteBuffer bb, IList <object> objects, GXAsn1Settings s)
        {
            int            len;
            short          type;
            IList <object> tmp;

            byte[] tmp2;
            type = bb.GetUInt8();
            len  = GXCommon.GetObjectCount(bb);
            if (len > bb.Available)
            {
                throw new OutOfMemoryException("GXAsn1Converter.GetValue");
            }
            int connectPos = 0;

            if (s != null)
            {
                connectPos = s.XmlLength;
            }
            int    start     = bb.Position;
            string tagString = null;

            if (s != null)
            {
                s.AppendSpaces();
                if (type == (byte)BerType.Integer)
                {
                    if (len == 1 || len == 2 || len == 4 || len == 8)
                    {
                        tagString = s.GetTag((short)-len);
                    }
                    else
                    {
                        tagString = s.GetTag((byte)BerType.Integer);
                    }
                }
                else
                {
                    tagString = s.GetTag(type);
                }
                s.Append("<" + tagString + ">");
            }

            switch (type)
            {
            case (byte)(BerType.Constructed | BerType.Context):
            case ((byte)(BerType.Constructed | BerType.Context) | 1):
            case ((byte)(BerType.Constructed | BerType.Context) | 2):
            case ((byte)(BerType.Constructed | BerType.Context) | 3):
            case ((byte)(BerType.Constructed | BerType.Context) | 4):
                if (s != null)
                {
                    s.Increase();
                }
                tmp = new GXAsn1Context()
                {
                    Index = type & 0xF
                };
                objects.Add(tmp);
                while (bb.Position < start + len)
                {
                    GetValue(bb, tmp, s);
                }
                if (s != null)
                {
                    s.Decrease();
                }
                break;

            case (byte)(BerType.Constructed | BerType.Sequence):
                if (s != null)
                {
                    s.Increase();
                }
                tmp = new GXAsn1Sequence();
                objects.Add(tmp);
                int cnt = 0;
                while (bb.Position < start + len)
                {
                    ++cnt;
                    GetValue(bb, tmp, s);
                }
                if (s != null)
                {
                    // Append comment.
                    s.AppendComment(connectPos, Convert.ToString(cnt) + " elements.");
                    s.Decrease();
                }
                break;

            case (byte)(BerType.Constructed | BerType.Set):
                if (s != null)
                {
                    s.Increase();
                }
                tmp = new List <object>();
                GetValue(bb, tmp, s);
                if (tmp[0] is GXAsn1Sequence)
                {
                    tmp = (GXAsn1Sequence)tmp[0];
                    objects.Add(new KeyValuePair <object, object>(tmp[0], tmp[1]));
                }
                else
                {
                    KeyValuePair <object, object> e = new KeyValuePair <object, object>(tmp, null);
                    objects.Add(e);
                }
                if (s != null)
                {
                    s.Decrease();
                }
                break;

            case (byte)BerType.ObjectIdentifier:
                GXAsn1ObjectIdentifier oi = new GXAsn1ObjectIdentifier(bb, len);
                objects.Add(oi);
                if (s != null)
                {
                    string str = oi.Description;
                    if (str != null)
                    {
                        s.AppendComment(connectPos, str);
                    }
                    s.Append(oi.ToString());
                }

                break;

            case (byte)BerType.PrintableString:
                objects.Add(bb.GetString(len));
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }

                break;

            case (byte)BerType.Utf8StringTag:
                objects.Add(new GXAsn1Utf8String(bb.GetString(bb.Position, len)));
                bb.Position = bb.Position + len;
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }

                break;

            case (byte)BerType.Ia5String:
                objects.Add(new GXAsn1Ia5String(bb.GetString(len)));
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }
                break;

            case (byte)BerType.Integer:
                if (len == 1)
                {
                    objects.Add(bb.GetInt8());
                }
                else if (len == 2)
                {
                    objects.Add(bb.GetInt16());
                }
                else if (len == 4)
                {
                    objects.Add(bb.GetInt32());
                }
                else
                {
                    tmp2 = new byte[len];
                    bb.Get(tmp2);
                    objects.Add(new GXAsn1Integer(tmp2));
                }
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }
                break;

            case (byte)BerType.Null:
                objects.Add(null);
                break;

            case (byte)BerType.BitString:
                GXAsn1BitString tmp3 = new GXAsn1BitString(bb.SubArray(bb.Position, len));
                objects.Add(tmp3);
                bb.Position = bb.Position + len;
                if (s != null)
                {
                    // Append comment.
                    s.AppendComment(connectPos, Convert.ToString(tmp3.Length) + " bit.");
                    s.Append(tmp3.asString());
                }
                break;

            case (byte)BerType.UtcTime:
                tmp2 = new byte[len];
                bb.Get(tmp2);
                objects.Add(GetUtcTime(ASCIIEncoding.ASCII.GetString(tmp2)));
                if (s != null)
                {
                    s.Append(((DateTimeOffset)objects[objects.Count - 1]).UtcDateTime.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture));
                }
                break;

            case (byte)BerType.GeneralizedTime:
                tmp2 = new byte[len];
                bb.Get(tmp2);
                objects.Add(GXCommon.GetGeneralizedTime(ASCIIEncoding.ASCII.GetString(tmp2)));
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }
                break;

            case (byte)BerType.Context:
            case (byte)BerType.Context | 1:
            case (byte)BerType.Context | 2:
            case (byte)BerType.Context | 3:
                tmp = new GXAsn1Context()
                {
                    Constructed = false, Index = type & 0xF
                };
                tmp2 = new byte[len];
                bb.Get(tmp2);
                tmp.Add(tmp2);
                objects.Add(tmp);
                if (s != null)
                {
                    s.Append(GXCommon.ToHex(tmp2, false));
                }
                break;

            case (byte)BerType.OctetString:
                int t = bb.GetUInt8(bb.Position);
                switch (t)
                {
                case (byte)(BerType.Constructed | BerType.Sequence):
                case (byte)BerType.BitString:
                    if (s != null)
                    {
                        s.Increase();
                    }
                    GetValue(bb, objects, s);
                    if (s != null)
                    {
                        s.Decrease();
                    }
                    break;

                default:
                    tmp2 = new byte[len];
                    bb.Get(tmp2);
                    objects.Add(tmp2);
                    if (s != null)
                    {
                        s.Append(GXCommon.ToHex(tmp2, false));
                    }
                    break;
                }
                break;

            case (byte)BerType.Boolean:
                bool b = bb.GetUInt8() != 0;
                objects.Add(b);
                if (s != null)
                {
                    s.Append(Convert.ToString(b));
                }
                break;

            default:
                throw new System.ArgumentException("Invalid type: " + type);
            }
            if (s != null)
            {
                s.Append("</" + tagString + ">\r\n");
            }
        }
Esempio n. 3
0
        private object[] GetDataList()
        {
            if (string.IsNullOrEmpty(Issuer))
            {
                throw new ArgumentNullException("Issuer is empty.");
            }
            if (string.IsNullOrEmpty(Subject))
            {
                throw new ArgumentNullException("Subject is empty.");
            }
            GXAsn1ObjectIdentifier a = new GXAsn1ObjectIdentifier(HashAlgorithmConverter.GetString(SignatureAlgorithm));
            GXAsn1Sequence         seq;
            GXAsn1Context          p = new GXAsn1Context();

            p.Add((sbyte)Version);
            GXAsn1Sequence s = new GXAsn1Sequence();
            GXAsn1Sequence s1;

            if (SubjectKeyIdentifier != null)
            {
                s1 = new GXAsn1Sequence();
                s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.SubjectKeyIdentifier)));
                GXByteBuffer bb = new GXByteBuffer();
                bb.SetUInt8(BerType.OctetString);
                GXCommon.SetObjectCount(SubjectKeyIdentifier.Length, bb);
                bb.Set(SubjectKeyIdentifier);
                s1.Add(bb.Array());
                s.Add(s1);
            }
            if (AuthorityKeyIdentifier != null || AuthorityCertIssuer != null || AuthorityCertificationSerialNumber != null)
            {
                s1 = new GXAsn1Sequence();
                s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.AuthorityKeyIdentifier)));
                s.Add(s1);
                GXAsn1Context s2 = new GXAsn1Context()
                {
                    Index = 3
                };
                GXAsn1Sequence c1 = new GXAsn1Sequence();
                if (AuthorityKeyIdentifier != null)
                {
                    GXAsn1Context c4 = new GXAsn1Context()
                    {
                        Constructed = false, Index = 0
                    };
                    c4.Add(AuthorityKeyIdentifier);
                    c1.Add(c4);
                    s1.Add(GXAsn1Converter.ToByteArray(c1));
                }
                if (AuthorityCertIssuer != null)
                {
                    GXAsn1Context c2 = new GXAsn1Context();
                    c2.Index = 1;
                    c1.Add(c2);
                    GXAsn1Context c3 = new GXAsn1Context()
                    {
                        Index = 4
                    };
                    c2.Add(c3);
                    c3.Add(GXAsn1Converter.EncodeSubject(AuthorityCertIssuer));
                    s2.Add(c1);
                }
                if (AuthorityCertificationSerialNumber != null)
                {
                    GXAsn1Context c4 = new GXAsn1Context()
                    {
                        Constructed = false, Index = 2
                    };
                    c4.Add(AuthorityCertificationSerialNumber);
                    c1.Add(c4);
                    s1.Add(GXAsn1Converter.ToByteArray(c1));
                }
            }
            // BasicConstraints
            s1 = new GXAsn1Sequence();
            s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.BasicConstraints)));
            seq = new GXAsn1Sequence();
            if (BasicConstraints)
            {
                //BasicConstraints is critical if it exists.
                s1.Add(BasicConstraints);
            }
            else if (KeyUsage == KeyUsage.None)
            {
                throw new Exception("Key usage not present.");
            }
            s1.Add(GXAsn1Converter.ToByteArray(seq));
            s.Add(s1);
            s1 = new GXAsn1Sequence();
            s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.KeyUsage)));
            byte value    = 0;
            int  min      = 255;
            byte keyUsage = GXCommon.SwapBits((byte)KeyUsage);

            foreach (KeyUsage it in Enum.GetValues(typeof(KeyUsage)))
            {
                if ((((byte)it) & keyUsage) != 0)
                {
                    byte val = (byte)it;
                    value |= val;
                    if (val < min)
                    {
                        min = val;
                    }
                }
            }
            int ignore = 0;

            while ((min >>= 1) != 0)
            {
                ++ignore;
            }
            byte[] tmp = GXAsn1Converter.ToByteArray(new GXAsn1BitString(new byte[] { (byte)(ignore % 8), value }));
            s1.Add(tmp);
            s.Add(s1);
            GXAsn1Sequence valid = new GXAsn1Sequence();

            valid.Add(ValidFrom);
            valid.Add(ValidTo);
            GXAsn1ObjectIdentifier alg;

            if (PublicKey.Scheme == Ecdsa.Enums.Ecc.P256)
            {
                alg = new GXAsn1ObjectIdentifier("1.2.840.10045.3.1.7");
            }
            else
            {
                alg = new GXAsn1ObjectIdentifier("1.3.132.0.34");
            }
            object[] list;
            object[] tmp3 = new object[] { new GXAsn1ObjectIdentifier("1.2.840.10045.2.1"),
                                           alg };
            GXAsn1Context tmp4 = new GXAsn1Context();

            tmp4.Index = 3;
            tmp4.Add(s);
            object[] tmp2 = new object[] { tmp3, new GXAsn1BitString(PublicKey.RawValue, 0) };
            object[] p2;
            if (SignatureParameters == null)
            {
                p2 = new object[] { a };
            }
            else
            {
                p2 = new object[] { a, SignatureParameters };
            }
            list = new object[] { p, new GXAsn1Integer(SerialNumber.ToByteArray()), p2, GXAsn1Converter.EncodeSubject(Issuer), valid, GXAsn1Converter.EncodeSubject(Subject), tmp2, tmp4 };
            return(list);
        }
Esempio n. 4
0
        //  https://tools.ietf.org/html/rfc5280#section-4.1
        private void Init(byte[] data)
        {
            rawData = data;
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count != 3)
            {
                throw new GXDLMSCertificateException("Invalid Certificate Version. Wrong number of elements in sequence.");
            }
            if (!(seq[0] is GXAsn1Sequence))
            {
                PkcsType type = GXAsn1Converter.GetCertificateType(data, seq);
                switch (type)
                {
                case PkcsType.Pkcs8:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS 8 private key, not x509 certificate.");

                case PkcsType.Pkcs10:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS 10 certification requests, not x509 certificate.");
                }
                throw new GXDLMSCertificateException("Invalid Certificate Version.");
            }
            GXAsn1Sequence reqInfo = (GXAsn1Sequence)seq[0];

            if ((reqInfo[0] is GXAsn1Integer))
            {
                throw new GXDLMSCertificateException("Invalid Certificate. DLMS certificate version number must be 3.");
            }
            Version = (CertificateVersion)((GXAsn1Context)reqInfo[0])[0];
            if (reqInfo[1] is sbyte)
            {
                SerialNumber = Convert.ToUInt64(reqInfo[1]);
            }
            else
            {
                SerialNumber = new BigInteger(((GXAsn1Integer)reqInfo[1]).Value);
            }
            string tmp = ((GXAsn1Sequence)reqInfo[2])[0].ToString();

            // Signature Algorithm
            SignatureAlgorithm = HashAlgorithmConverter.FromString(tmp);
            if (SignatureAlgorithm != HashAlgorithm.Sha256WithEcdsa)
            {
                throw new Exception("DLMS certificate must be signed with ecdsa-with-SHA256.");
            }
            // Optional.
            if (((GXAsn1Sequence)reqInfo[2]).Count > 1)
            {
                SignatureParameters = ((GXAsn1Sequence)reqInfo[2])[1];
            }
            // Issuer
            Issuer = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[3]);
            bool basicConstraintsExists = false;

            // Validity
            ValidFrom = (DateTime)((GXAsn1Sequence)reqInfo[4])[0];
            ValidTo   = (DateTime)((GXAsn1Sequence)reqInfo[4])[1];
            Subject   = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[5]);
            string CN = X509NameConverter.GetString(X509Name.CN);
            // Subject public key Info
            GXAsn1Sequence subjectPKInfo = (GXAsn1Sequence)reqInfo[6];

            PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)subjectPKInfo[1]).Value);
            GXEcdsa.Validate(PublicKey);
            // Get Standard Extensions.
            if (reqInfo.Count > 7)
            {
                foreach (GXAsn1Sequence s in (GXAsn1Sequence)((GXAsn1Context)reqInfo[7])[0])
                {
                    GXAsn1ObjectIdentifier id = (GXAsn1ObjectIdentifier)s[0];
                    object value          = s[1];
                    X509CertificateType t = X509CertificateTypeConverter.FromString(id.ToString());
                    switch (t)
                    {
                    case X509CertificateType.SubjectKeyIdentifier:
                        SubjectKeyIdentifier = (byte[])value;
                        break;

                    case X509CertificateType.AuthorityKeyIdentifier:
                        foreach (GXAsn1Context it in (GXAsn1Sequence)value)
                        {
                            switch (it.Index)
                            {
                            case 0:
                                //Authority Key Identifier.
                                AuthorityKeyIdentifier = (byte[])it[0];
                                break;

                            case 1:
                            {
                                StringBuilder sb = new StringBuilder();
                                //authorityCertIssuer
                                foreach (KeyValuePair <object, object> it2 in ((GXAsn1Sequence)((GXAsn1Context)it[0])[0]))
                                {
                                    if (sb.Length != 0)
                                    {
                                        sb.Append(", ");
                                    }
                                    sb.Append(X509NameConverter.FromString(Convert.ToString(it2.Key)));
                                    sb.Append("=");
                                    sb.Append(Convert.ToString(it2.Value));
                                }
                                AuthorityCertIssuer = sb.ToString();
                            }
                            break;

                            case 2:
                                //Authority cert serial number .
                                AuthorityCertificationSerialNumber = (byte[])it[0];
                                break;

                            default:
                                throw new ArgumentOutOfRangeException("Invalid context." + it.Index);
                            }
                        }
                        break;

                    case X509CertificateType.KeyUsage:
                        if (value is GXAsn1BitString)
                        {
                            // critical is optional. BOOLEAN DEFAULT FALSE,
                            KeyUsage = (KeyUsage)((GXAsn1BitString)value).ToInteger();
                        }
                        else if (value is bool?)
                        {
                            value    = s[2];
                            KeyUsage = (KeyUsage)((GXAsn1BitString)value).ToInteger();
                        }
                        else
                        {
                            throw new ArgumentException("Invalid key usage.");
                        }
                        break;

                    case X509CertificateType.BasicConstraints:
                        basicConstraintsExists = true;
                        if (value is GXAsn1Sequence)
                        {
                            if (((GXAsn1Sequence)value).Count != 0)
                            {
                                BasicConstraints = (bool)((GXAsn1Sequence)value)[0];
                            }
                        }
                        else if (value is bool?)
                        {
                            BasicConstraints = (bool)value;
                        }
                        else
                        {
                            throw new ArgumentException("Invalid key usage.");
                        }
                        break;

                    default:
                        System.Diagnostics.Debug.WriteLine("Unknown extensions: " + t.ToString());
                        break;
                    }
                }
            }
            if (!basicConstraintsExists)
            {
                // Verify that subject Common Name includes system title.
                bool commonNameFound = false;
                foreach (KeyValuePair <object, object> it in (GXAsn1Sequence)reqInfo[5])
                {
                    if (CN == it.Key.ToString())
                    {
                        if (Convert.ToString(it.Value).Length != 16)
                        {
                            throw new GXDLMSCertificateException("System title is not included in Common Name.");
                        }
                        commonNameFound = true;
                        break;
                    }
                }
                if (!commonNameFound)
                {
                    throw new GXDLMSCertificateException("Common name doesn't exist.");
                }
            }

            if (KeyUsage == KeyUsage.None)
            {
                throw new Exception("Key usage not present. It's mandotory.");
            }
            if ((KeyUsage & (KeyUsage.KeyCertSign | KeyUsage.CrlSign)) != 0 && !basicConstraintsExists)
            {
                throw new Exception("Basic Constraints value not present. It's mandotory.");
            }
            PublicKeyAlgorithm = HashAlgorithmConverter.FromString(((GXAsn1Sequence)seq[1])[0].ToString());
            if (PublicKeyAlgorithm != HashAlgorithm.Sha256WithEcdsa)
            {
                throw new Exception("DLMS certificate must be signed with ecdsa-with-SHA256.");
            }
            // Optional.
            if (((GXAsn1Sequence)seq[1]).Count > 1)
            {
                PublicKeyParameters = ((GXAsn1Sequence)seq[1])[1];
            }
            /////////////////////////////
            //Get signature.
            Signature = ((GXAsn1BitString)seq[2]).Value;
        }
        private object[] GetData()
        {
            GXAsn1ObjectIdentifier a = new GXAsn1ObjectIdentifier(HashAlgorithmConverter.GetString(SignatureAlgorithm));
            GXAsn1Context          p = new GXAsn1Context();

            p.Add((sbyte)Version);
            object         subjectPKInfo = GXAsn1Converter.FromByteArray(PublicKey.RawValue);
            GXAsn1Sequence s             = new GXAsn1Sequence();
            GXAsn1Sequence s1;

            if (SubjectKeyIdentifier != null)
            {
                s1 = new GXAsn1Sequence();
                s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.SubjectKeyIdentifier)));
                GXByteBuffer bb = new GXByteBuffer();
                bb.SetUInt8(BerType.OctetString);
                GXCommon.SetObjectCount(SubjectKeyIdentifier.Length, bb);
                bb.Set(SubjectKeyIdentifier);
                s1.Add(bb.Array());
                s.Add(s1);
            }
            if (AuthorityKeyIdentifier != null)
            {
                s1 = new GXAsn1Sequence();
                s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.AuthorityKeyIdentifier)));
                GXAsn1Sequence seq = new GXAsn1Sequence();
                seq.Add(AuthorityKeyIdentifier);
                s1.Add(GXAsn1Converter.ToByteArray(seq));
                s.Add(s1);
            }
            if (BasicConstraints)
            {
                s1 = new GXAsn1Sequence();
                s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.BasicConstraints)));
                GXAsn1Sequence seq = new GXAsn1Sequence();
                seq.Add(BasicConstraints);
                s1.Add(GXAsn1Converter.ToByteArray(seq));
                s.Add(s1);
            }
            if (KeyUsage == KeyUsage.None)
            {
                throw new Exception("Key usage not present.");
            }
            s1 = new GXAsn1Sequence();
            s1.Add(new GXAsn1ObjectIdentifier(X509CertificateTypeConverter.GetString(Enums.X509CertificateType.KeyUsage)));
            byte value = 0;
            int  min   = 255;

            foreach (KeyUsage it in Enum.GetValues(typeof(KeyUsage)))
            {
                if ((it & KeyUsage) != 0)
                {
                    byte val = (byte)it;
                    value |= val;
                    if (val < min)
                    {
                        min = val;
                    }
                }
            }
            int offset = 7;

            while ((min >>= 2) != 0)
            {
                ++offset;
            }
            byte[] tmp = GXAsn1Converter.ToByteArray(new GXAsn1BitString(new byte[] { 0, value }));
            s1.Add(tmp);
            s.Add(s1);
            GXAsn1Sequence valid = new GXAsn1Sequence();

            valid.Add(ValidFrom);
            valid.Add(ValidTo);
            object[] list;
            if (s.Count == 0)
            {
                list = new object[] { p, SerialNumber, new object[] { a, SignatureParameters }, GXAsn1Converter.EncodeSubject(Issuer), valid, GXAsn1Converter.EncodeSubject(Subject), subjectPKInfo };
            }
            else
            {
                GXAsn1Context tmp2 = new GXAsn1Context();
                tmp2.Index = 3;
                tmp2.Add(s);
                list = new object[] { p, SerialNumber, new object[] { a, SignatureParameters }, GXAsn1Converter.EncodeSubject(Issuer), valid, GXAsn1Converter.EncodeSubject(Subject), subjectPKInfo, tmp2 };
            }
            return(list);
        }
        //  https://tools.ietf.org/html/rfc5280#section-4.1
        private void Init(byte[] data)
        {
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count != 3)
            {
                throw new ArgumentException("Wrong number of elements in sequence.");
            }
            GXAsn1Sequence reqInfo = (GXAsn1Sequence)seq[0];

            Version = (CertificateVersion)((GXAsn1Context)reqInfo[0])[0];
            if (reqInfo[1] is sbyte)
            {
                SerialNumber = new GXAsn1Integer(Convert.ToUInt64(reqInfo[1]));
            }
            else
            {
                SerialNumber = (GXAsn1Integer)reqInfo[1];
            }
            string tmp = ((GXAsn1Sequence)reqInfo[2])[0].ToString();

            // Signature Algorithm
            SignatureAlgorithm = HashAlgorithmConverter.FromString(tmp);
            if (SignatureAlgorithm != HashAlgorithm.Sha256withecdsa)
            {
                throw new Exception("DLMS certificate must be signed with ecdsa-with-SHA256.");
            }
            // Optional.
            if (((GXAsn1Sequence)reqInfo[2]).Count > 1)
            {
                SignatureParameters = ((GXAsn1Sequence)reqInfo[2])[1];
            }
            // Issuer
            Issuer = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[3]);
            // Validity
            ValidFrom = (DateTime)((GXAsn1Sequence)reqInfo[4])[0];
            ValidTo   = (DateTime)((GXAsn1Sequence)reqInfo[4])[1];
            Subject   = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[5]);
            // Subject public key Info
            GXAsn1Sequence subjectPKInfo = (GXAsn1Sequence)reqInfo[6];

            PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)subjectPKInfo[1]).Value);
            // Get Standard Extensions.
            if (reqInfo.Count > 7)
            {
                foreach (GXAsn1Sequence s in (GXAsn1Sequence)((GXAsn1Context)reqInfo[7])[0])
                {
                    GXAsn1ObjectIdentifier id = (GXAsn1ObjectIdentifier)s[0];
                    object value = s[1];
                    Enums.X509CertificateType t = Enums.X509CertificateTypeConverter.FromString(id.ToString());
                    switch (t)
                    {
                    case Enums.X509CertificateType.SubjectKeyIdentifier:
                        SubjectKeyIdentifier = (byte[])value;
                        break;

                    case Enums.X509CertificateType.AuthorityKeyIdentifier:
                        AuthorityKeyIdentifier = (byte[])((GXAsn1Sequence)value)[0];
                        break;

                    case Enums.X509CertificateType.KeyUsage:
                        if (value is GXAsn1BitString)
                        {
                            // critical is optional. BOOLEAN DEFAULT FALSE,
                            KeyUsage = (KeyUsage)((GXAsn1BitString)value).Value[0];
                        }
                        else if (value is bool?)
                        {
                            value    = s[2];
                            KeyUsage = (KeyUsage)((GXAsn1BitString)value).Value[0];
                        }
                        else
                        {
                            throw new ArgumentException("Invalid key usage.");
                        }
                        break;

                    default:
                        System.Diagnostics.Debug.WriteLine("Unknown extensions: " + t.ToString());
                        break;
                    }
                }
            }
            if (KeyUsage == KeyUsage.None)
            {
                throw new Exception("Key usage not present.");
            }
            PublicKeySignature = HashAlgorithmConverter.FromString(((GXAsn1Sequence)seq[1])[0].ToString());
            // Optional.
            if (((GXAsn1Sequence)seq[1]).Count > 1)
            {
                SignatureParameters = ((GXAsn1Sequence)seq[1])[1];
            }
            // signature
            Signature = ((GXAsn1BitString)seq[2]).Value;
        }