X.509证书解析和验签

实现了ASN.1语法,对数字证书进行解析,并对RSA WITH SHA256的证书进行验签。使用.net core c#编写。

ASN.1语法解析代码

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Globalization;

namespace ASN1
{
    enum TLVType {
        Boolean = 0x1,
        Integer = 0x2,
        BitString = 0x3,
        OctetString = 0x4,
        Null = 0x5,
        Object = 0x6,
        PrintableString = 0x13,
        UTCTime = 0x17,
        Sequence = 0x30,
        Set = 0x31,
        Version = 0xA0,
        Extensions = 0xA3

    }

    class Bytes
    {
        public static byte[] SubBytes(byte[] bytes, int start)
        {
            byte[] t = new byte[bytes.Length - start];
            Array.Copy(bytes, start, t, 0, t.Length);
            return t;
        }

        public static byte[] SubBytes(byte[] bytes, int start, int len)
        {
            byte[] t = new byte[len];
            Array.Copy(bytes, start, t, 0, t.Length);
            return t;
        }

        public static byte[] Concat(byte[] b1, byte[] b2)
        {
            byte[] t = new byte[b1.Length + b2.Length];
            Array.Copy(b1, t, b1.Length);
            Array.Copy(b2, 0, t, b1.Length, b2.Length);
            return t;
        }

    }

    abstract class TLV
    {
        protected byte _tag;
        protected byte[] _length = null;
        protected byte[] _data = null;
        protected byte[] _ori = null;

        protected TLV(byte[] buf)
        {
            _tag = buf[0];
            int lengthSize = getTLVLengthSize(Bytes.SubBytes(buf, 1));
            _length = Bytes.SubBytes(buf, 1, lengthSize);
            int dataSize = getTLVDataSize(_length);
            _data = Bytes.SubBytes(buf, 1 + lengthSize, dataSize);

            _ori = Bytes.SubBytes(buf, 0, 1 + lengthSize + _data.Length);
        }

        public byte Tag {  get { return _tag;  } }
        public byte[] Data {  get { return _data;  } }
        public int LenthSize { get { return _length.Length;  } }
        public int DataSize {  get { return  _data.Length;  } }
        public int Size { get { return 1 + _length.Length + _data.Length; } }
        public byte[] Original { get { return _ori;  } }

        int getTLVDataSize(byte[] buf)
        {
            int len = 0;

            if (buf[0] < 0x80)
            {
                len = buf[0];
            }
            else if (buf[0] > 0x80)
            {
                int i = buf[0] - 0x80;

                if (i > 0) len = buf[1];
                if (i > 1) len = len << 8 | buf[2];
                if (i > 2) len = len << 8 | buf[3];
                if (i > 3) len = len << 8 | buf[4];
            }
            else if (buf[0] == 0x80)
            {
                int i = 0;
                while (buf[i + 2] != 0 && buf[i + 3] != 0)
                {
                    i++;
                }

                if (i > 0) len = buf[1];
                if (i > 1) len = len << 8 | buf[2];
                if (i > 2) len = len << 8 | buf[3];
                if (i > 3) len = len << 8 | buf[4];
            }
            return len;
        }

        int getTLVLengthSize(byte[] buf)
        {
            if (buf[0] < 0x80)
                return 1;
            else if (buf[0] > 0x80)
                return 1 + buf[0] - 0x80;
            else if (buf[0] == 0x80)
            {
            }
            throw new NotSupportedException();
        }

        int getTLVSize(TLV tlv)
        {
            return 1 + getTLVLengthSize(_length) + getTLVDataSize(_length);
        }

    }

    class BooleanTLV : TLV
    {
        private bool b;

        public BooleanTLV(byte[] buf) : base(buf)
        {
            b = Data[0] != 0;
        }

        public bool Value { get { return b;  } }
    }

    class ObjectTLV : TLV
    {
        private uint[] identifer;

        public ObjectTLV(byte[] buf) : base(buf)
        {
            byte[] data = Data;

            List<uint> r = new List<uint>();
            r.Add((uint)data[0] / 40);
            r.Add((uint)data[0] % 40);
            int i = 1;
            uint m = 0;
            while (i < data.Length)
            {
                m = (uint)((uint)(m << 7) | (uint)(data[i] & 0x7f));

                if ((data[i] & 0x80) == 0)
                {
                    r.Add(m);
                    m = 0;
                }

                i++;
            }

            identifer = r.ToArray();
        }

        public uint[] Identifer { get { return identifer;  } }

    }

    class PrintableStringTLV : TLV
    {
        string s = "";

        public PrintableStringTLV(byte[] buf) : base(buf)
        {
            for (int i=0; i<Data.Length; i++)
            {
                s += (char)Data[i];
            }
        }

        public string GetPrintableString()
        {
            return s;
        }
    }

    class OctetStringTLV : TLV
    {
        public OctetStringTLV(byte[] buf) : base(buf)
        {

        }

        public byte[] Bytes { get { return Data;  } }
    }

    class IntegerTLV : TLV
    {
        private BigInteger _intValue;

        public IntegerTLV(byte[] buf) :  base(buf)
        {
//            byte[] t = new byte[Data.Length];
 //           Array.Copy(Data, t, Data.Length);
   //         Array.Reverse(t);

            _intValue = new BigInteger(Data, true, true);
        }

        public BigInteger IntValue {  get { return _intValue;  } }
        public byte[] ByteValue { get { return _intValue.ToByteArray(); } }
    }

    class NullTLV : TLV
    {
        public NullTLV(byte[] buf) : base(buf)
        {

        }
    }

    class UTCTimeTLV : TLV
    {
        private DateTime date;

        public UTCTimeTLV(byte[] buf) : base(buf)
        {
            string s = "";
            for (int i=0; i<Data.Length; i++)
            {
                s += (char) (Data[i]);
            }
            date = DateTime.ParseExact(s, "yyMMddHHmmssZ", null, DateTimeStyles.AdjustToUniversal);


        }

        public DateTime Date { get { return date;  } }
    }

    class BitStringTLV : TLV
    {
        public BitStringTLV(byte[] buf) : base(buf)
        {

        }
        public byte[] ValidData() {
            byte fill = Data[0];
            if (fill != 0)
            {
                throw new NotImplementedException();
            }
            return Bytes.SubBytes(Data, 1);
        }

    }

    class ExtensionsTLV : TLV
    {
        private SequenceTLV seq;

        public ExtensionsTLV(byte[] buf) : base(buf)
        {
            seq = new SequenceTLV(Data);
        }
        public SequenceTLV Sequence { get { return seq; } }
    }

    class SequenceTLV : TLV
    {
        protected TLV[] children;
        public SequenceTLV(byte[] buf) : base(buf)
        {
            List<TLV> tlvs = new List<TLV>();

            int i = 0;
            while (i < Data.Length)
            {
                byte[] bs = Bytes.SubBytes(Data, i);
                TLV tlv = null;

                if ((byte)TLVType.Boolean == Data[i])
                {
                    tlv = new BooleanTLV(bs);
                }
                else if ((byte)TLVType.Integer ==  Data[i])
                {
                    tlv = new IntegerTLV(bs);
                }
                else if ((byte) TLVType.OctetString == Data[i])
                {
                    tlv = new OctetStringTLV(bs);
                }
                else if ((byte) TLVType.PrintableString == Data[i])
                {
                    tlv = new PrintableStringTLV(bs);
                }
                else if ((byte) TLVType.Version == Data[i])
                {
                    tlv = new VersionTLV(bs);
                }
                else if ((byte)TLVType.Sequence == Data[i])
                {
                    tlv = new SequenceTLV(bs);
                }
                else if ((byte)TLVType.Object == Data[i])
                {
                    tlv = new ObjectTLV(bs);
                }
                else if ((byte)TLVType.Null == Data[i])
                {
                    tlv = new NullTLV(bs);
                }
                else if ((byte)TLVType.Set == Data[i])
                {
                    tlv = new SetTLV(bs);
                }
                else if ((byte)TLVType.UTCTime == Data[i])
                {
                    tlv = new UTCTimeTLV(bs);
                }
                else if ((byte)TLVType.BitString == Data[i])
                {
                    tlv = new BitStringTLV(bs);
                }
                else if ((byte)TLVType.Extensions == Data[i])
                {
                    tlv = new ExtensionsTLV(bs);
                }
                else
                {
                    throw new NotSupportedException();
                }

                if (tlv != null)
                    tlvs.Add(tlv);

                i += tlv.Size;
            }

            children = tlvs.ToArray();

        }

        public TLV[] Children { get { return children; } }
    }

    class SetTLV : SequenceTLV
    {
        public SetTLV(byte[] buf) :  base(buf)
        {

        }
    }

    class VersionTLV : TLV
    {
        private IntegerTLV ver;

        public VersionTLV(byte[] buf) : base(buf)
        {
            ver = new IntegerTLV(Data);
        }

        public string Version { get { return ver.IntValue.ToString(); } }
    }



}

对证书字段进行显示:

数字证书验签代码:

        private byte[] RSADecrypt(BigInteger? PublicKey)
        {
            if (PublicKey == null) // 如果是自签名证书,不需要传入上级公钥,传入null
            {
                PublicKey = _tbsCertificate.SubjectPublicKeyInfo.Modules;  // 取自己的公钥
            }

            BigInteger exponent = _tbsCertificate.SubjectPublicKeyInfo.Exponent;

            BigInteger msg = new BigInteger(_signatureValue.ValidData(), true, true);
            BigInteger value = BigInteger.ModPow(msg, exponent, PublicKey.Value);

            // return value.ToByteArray(false, true); ?? why miss 0
            // fix code For ==> BigInteger.ToByteArray(false, true) 
            byte[] t = new byte[value.GetByteCount() + 1];
            Array.Copy(value.ToByteArray(false, true), 0, t, 1, t.Length - 1);
            return t;
        }

        private byte[] RSA_PKCS1_PADDING(byte[] buf)
        {
            const int BT = 1;
            int PS;

            if (BT == 0)
                PS = 0;
            else if (BT == 1)
                PS = 0xFF;
            else
                PS = new Random().Next(1, 255);

            if (buf[0] != 0 && buf[1] != BT)
                throw new Exception();

            int p = 2;
            while (p < buf.Length)
            {
                if (buf[p++] == 0)
                    break;
            }

            int n = buf.Length - p;

            byte[] r = new byte[n];
            Array.Copy(buf, p, r, 0,  r.Length);
            return r;
        }

       public bool Verify(BigInteger? PublicKey)
        {
            // RSA PublicKey Decrypt
            byte[] decrypt = RSADecrypt(PublicKey);

            // RDA Padding
            byte[] values = RSA_PKCS1_PADDING(decrypt);

            SequenceTLV tlvs = new SequenceTLV(values);
            OctetStringTLV otlv = (OctetStringTLV)tlvs.Children[1];

            byte[] result = otlv.Bytes;

            // SHA-256 
            byte[] hash = SHA256Managed.Create().ComputeHash(msg);

            // compare hash And values

            if (hash.Length != result.Length)
                return false;

            for (int i = 0; i < result.Length; i++)
            {
                if (result[i] != hash[i])
                {
                    return false;
                }

            }
            return true;

        }

对于自签名证书,利用自己的公钥进行验签

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值