c# 导入PKCS1和PKCS8密钥

之前在RSA PKCS1和PKCS8的ASN格式一文里,我们已经分析过了PKCS1和PKCS8格式的密钥了

那么,我们现在就做一个c#通用的解析代码,即能解析PKCS1的密钥,也能解析PKCS8的密钥

    public static partial class Encryption
    {
        public static class AsnParser
        {
            public static RSAParameters ParseRSAPrivateKey(byte[] bt)
            {
                RSAParameters rsap = new RSAParameters();
                // Initial value
                List<byte> octets = new List<byte>();
                octets.AddRange(bt);
                int initialCount = bt.Length;
                // Current value
                byte[] value = null;
                // Checkpoint
                int position = CurrentPosition(initialCount, octets);
                // Sanity Check
                int length = 0;
                byte b = 0;
                length = NextSequence(ref initialCount, ref octets, out b);
                if (length != RemainingBytes(octets))
                {
                    StringBuilder sb = new StringBuilder("Incorrect Sequence Size. ");
                    sb.AppendFormat("Specified: {0}, Remaining: {1}",
                      length.ToString(CultureInfo.InvariantCulture), RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                // Checkpoint
                position = CurrentPosition(initialCount, octets);
                // Version
                value = NextInteger(ref initialCount, ref octets);
                if (0x00 != value[0])
                {
                    StringBuilder sb = new StringBuilder("Incorrect PrivateKeyInfo Version. ");
                    BigInteger v = new BigInteger(value);
                    sb.AppendFormat("Expected: 0, Specified: {0}", v.ToString(10));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                // Checkpoint
                position = CurrentPosition(initialCount, octets);
                // Ignore Sequence - AlgorithmIdentifier
                length = NextSequence(ref initialCount, ref octets, out b);
                if (0x30 == b)  // PKCS8
                {
                    if (length > RemainingBytes(octets))
                    {
                        StringBuilder sb = new StringBuilder("Incorrect AlgorithmIdentifier Size. ");
                        sb.AppendFormat("Specified: {0}, Remaining: {1}",
                          length.ToString(CultureInfo.InvariantCulture),
                          RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    // Checkpoint
                    position = CurrentPosition(initialCount, octets);
                    // Grab the OID
                    value = NextOID(ref initialCount, ref octets);
                    byte[] oid = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
                    if (!EqualOid(value, oid))
                    {
                        //throw new BerDecodeException("Expected OID 1.2.840.113549.1.1.1", position);
                        throw new Exception("Expected OID 1.2.840.113549.1.1.1");
                    }
                    // Optional Parameters
                    if (IsNextNull(octets))
                    {
                        NextNull(ref initialCount, ref octets);
                        // Also OK: value = parser.Next();
                    }
                    else
                    {
                        // Gracefully skip the optional data
                        value = Next(ref initialCount, ref octets);
                    }
                    // Checkpoint
                    position = CurrentPosition(initialCount, octets);
                    // Ignore OctetString - PrivateKey
                    length = NextOctetString(ref initialCount, ref octets);
                    if (length > RemainingBytes(octets))
                    {
                        StringBuilder sb = new StringBuilder("Incorrect PrivateKey Size. ");
                        sb.AppendFormat("Specified: {0}, Remaining: {1}",
                          length.ToString(CultureInfo.InvariantCulture),
                          RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    // Checkpoint
                    position = CurrentPosition(initialCount, octets);
                    // Ignore Sequence - RSAPrivateKey
                    length = NextSequence(ref initialCount, ref octets, out b);
                    if (length < RemainingBytes(octets))
                    {
                        StringBuilder sb = new StringBuilder("Incorrect RSAPrivateKey Size. ");
                        sb.AppendFormat("Specified: {0}, Remaining: {1}",
                          length.ToString(CultureInfo.InvariantCulture),
                          RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    // Checkpoint
                    position = CurrentPosition(initialCount, octets);
                    // Version
                    value = NextInteger(ref initialCount, ref octets);
                    if (0x00 != value[0])
                    {
                        StringBuilder sb = new StringBuilder("Incorrect RSAPrivateKey Version. ");
                        BigInteger v = new BigInteger(value);
                        sb.AppendFormat("Expected: 0, Specified: {0}", v.ToString(10));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    rsap.Modulus = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                    rsap.Exponent = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                    rsap.D = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                    rsap.P = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                    rsap.Q = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                    rsap.DP = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                    rsap.DQ = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                    rsap.InverseQ = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                }
                if (0x02 == b)  // PKCS1
                {
                    rsap.Modulus = TrimLeadingZero(GetOctets(ref initialCount, ref octets, length));
                    rsap.Exponent = TrimLeadingZero(GetOctets(ref initialCount, ref octets, NextSequence(ref initialCount, ref octets, out b)));
                    rsap.D = TrimLeadingZero(GetOctets(ref initialCount, ref octets, NextSequence(ref initialCount, ref octets, out b)));
                    rsap.P = TrimLeadingZero(GetOctets(ref initialCount, ref octets, NextSequence(ref initialCount, ref octets, out b)));
                    rsap.Q = TrimLeadingZero(GetOctets(ref initialCount, ref octets, NextSequence(ref initialCount, ref octets, out b)));
                    rsap.DP = TrimLeadingZero(GetOctets(ref initialCount, ref octets, NextSequence(ref initialCount, ref octets, out b)));
                    rsap.DQ = TrimLeadingZero(GetOctets(ref initialCount, ref octets, NextSequence(ref initialCount, ref octets, out b)));
                    rsap.InverseQ = TrimLeadingZero(GetOctets(ref initialCount, ref octets, NextSequence(ref initialCount, ref octets, out b)));
                }
                return rsap;
            }
            public static RSAParameters ParseRSAPublicKey(byte[] bt)
            {
                RSAParameters rsap = new RSAParameters();
                // Initial value
                List<byte> octets = new List<byte>();
                octets.AddRange(bt);
                int initialCount = bt.Length;
                byte b = 0;
                // Current value
                byte[] value = null;
                // Sanity Check
                int length = 0;
                // Checkpoint
                int position = CurrentPosition(initialCount, octets);
                // Ignore Sequence - PublicKeyInfo
                length = NextSequence(ref initialCount, ref octets, out b);
                if (length != RemainingBytes(octets))
                {
                    StringBuilder sb = new StringBuilder("Incorrect Sequence Size. ");
                    sb.AppendFormat("Specified: {0}, Remaining: {1}",
                      length.ToString(CultureInfo.InvariantCulture),
                      RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                // Checkpoint
                position = CurrentPosition(initialCount, octets);
                // Ignore Sequence - AlgorithmIdentifier
                length = NextSequence(ref initialCount, ref octets, out b);
                if (length > RemainingBytes(octets))
                {
                    StringBuilder sb = new StringBuilder("Incorrect AlgorithmIdentifier Size. ");
                    sb.AppendFormat("Specified: {0}, Remaining: {1}",
                      length.ToString(CultureInfo.InvariantCulture),
                      RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                // Checkpoint
                position = CurrentPosition(initialCount, octets);
                // Grab the OID
                value = NextOID(ref initialCount, ref octets);
                byte[] oid = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
                if (!EqualOid(value, oid))
                {
                    //throw new BerDecodeException("Expected OID 1.2.840.113549.1.1.1", position);
                    throw new Exception("Expected OID 1.2.840.113549.1.1.1");
                }
                // Optional Parameters
                if (IsNextNull(octets))
                {
                    NextNull(ref initialCount, ref octets);
                    // Also OK: value = parser.Next();
                }
                else
                {
                    // Gracefully skip the optional data
                    value = Next(ref initialCount, ref octets);
                }
                // Checkpoint
                position = CurrentPosition(initialCount, octets);
                // Ignore BitString - PublicKey
                length = NextBitString(ref initialCount, ref octets);
                if (length > RemainingBytes(octets))
                {
                    StringBuilder sb = new StringBuilder("Incorrect PublicKey Size. ");
                    sb.AppendFormat("Specified: {0}, Remaining: {1}",
                      length.ToString(CultureInfo.InvariantCulture),
                      (RemainingBytes(octets)).ToString(CultureInfo.InvariantCulture));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                // Checkpoint
                position = CurrentPosition(initialCount, octets);
                // Ignore Sequence - RSAPublicKey
                length = NextSequence(ref initialCount, ref octets, out b);
                if (length < RemainingBytes(octets))
                {
                    StringBuilder sb = new StringBuilder("Incorrect RSAPublicKey Size. ");
                    sb.AppendFormat("Specified: {0}, Remaining: {1}",
                      length.ToString(CultureInfo.InvariantCulture),
                      RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                rsap.Modulus = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                rsap.Exponent = TrimLeadingZero(NextInteger(ref initialCount, ref octets));
                return rsap;
            }
            public static byte[] ExportRSAPrivateKey(RSAParameters rp, RSA.PaddingType padding)
            {
                int count = 0;
                List<byte[]> bytes = new List<byte[]>();
                bytes.Add(rp.InverseQ);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 129, 128 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.DQ);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 129, 128 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.DP);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 129, 128 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.Q);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 129, 128 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.P);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 129, 128 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.D);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 130, 1, 0 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.Exponent);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 3 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.Modulus);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 130, 1, 0 });
                count += bytes[bytes.Count - 1].Length;
                switch (padding)
                {
                    case RSA.PaddingType.PKCS1:
                        break;
                    case RSA.PaddingType.PKCS8:
                        bytes.Add(new byte[] { 2, 1, 0 });
                        count += bytes[bytes.Count - 1].Length;
                        bytes.Add(IntToByte(count));
                        count += bytes[bytes.Count - 1].Length;
                        bytes.Add(new byte[] { 48, 130 });
                        count += bytes[bytes.Count - 1].Length;
                        bytes.Add(IntToByte(count));
                        count += bytes[bytes.Count - 1].Length;
                        bytes.Add(new byte[] { 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 4, 130 });
                        count += bytes[bytes.Count - 1].Length;
                        break;
                    default:
                        throw new Exception("Invalid RSA PaddingType");
                }
                bytes.Add(new byte[] { 2, 1, 0 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(IntToByte(count));
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 48, 130 });
                count += bytes[bytes.Count - 1].Length;
                byte[] result = new byte[count];
                int cur = 0;
                for (var i = 0; i < bytes.Count; i++)
                {
                    Array.Copy(bytes[i], 0, result, count - bytes[i].Length - cur, bytes[i].Length);
                    cur += bytes[i].Length;
                }
                return result;
            }
            public static byte[] ExportRSAPublicKey(RSAParameters rp)
            {
                int count = 0;
                List<byte[]> bytes = new List<byte[]>();
                bytes.Add(rp.Exponent);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 3 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(rp.Modulus);
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 2, 130, 1, 1, 0 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(IntToByte(count));
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 48, 130 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 0 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(IntToByte(count));
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130 });
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(IntToByte(count));
                count += bytes[bytes.Count - 1].Length;
                bytes.Add(new byte[] { 48, 130 });
                count += bytes[bytes.Count - 1].Length;
                byte[] result = new byte[count];
                int cur = 0;
                for (var i = 0; i < bytes.Count; i++)
                {
                    Array.Copy(bytes[i], 0, result, count - bytes[i].Length - cur, bytes[i].Length);
                    cur += bytes[i].Length;
                }
                return result;
            }
            private static byte[] IntToByte(int i)
            {
                if (i < 256)
                {
                    return new byte[] { (byte)i };
                }
                string h = i.ToString("x");
                MatchCollection mc = RegexExpand.Matches(h, @"[a-f0-9]{1,2}(?=([a-f0-9]{2})*$)", RegexOptions.IgnoreCase);
                List<byte> result = new List<byte>();
                for (int ii = 0; ii < mc.Count; ii++)
                {
                    result.Add((byte)Convert.ToInt16(mc[ii].Value, 16));
                }
                return result.ToArray();
            }
            private static byte[] TrimLeadingZero(byte[] values)
            {
                byte[] r = null;
                if ((0x00 == values[0]) && (values.Length > 1))
                {
                    r = new byte[values.Length - 1];
                    Array.Copy(values, 1, r, 0, values.Length - 1);
                }
                else
                {
                    r = new byte[values.Length];
                    Array.Copy(values, r, values.Length);
                }
                return r;
            }
            private static int NextBitString(ref int initialCount, ref List<byte> octets)
            {
                int position = CurrentPosition(initialCount, octets);
                try
                {
                    byte b = GetNextOctet(ref initialCount, ref octets);
                    if (0x03 != b)
                    {
                        StringBuilder sb = new StringBuilder("Expected Bit String. ");
                        sb.AppendFormat("Specified Identifier: {0}", b.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    int length = GetLength(ref initialCount, ref octets);
                    // We need to consume unused bits, which is the first
                    //   octet of the remaing values
                    b = octets[0];
                    octets.RemoveAt(0);
                    length--;
                    if (0x00 != b)
                    {
                        //throw new BerDecodeException("The first octet of BitString must be 0", position);
                        throw new Exception("The first octet of BitString must be 0");
                    }
                    return length;
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
            }
            private static int NextOctetString(ref int initialCount, ref List<byte> octets)
            {
                int position = CurrentPosition(initialCount, octets);
                try
                {
                    byte b = GetNextOctet(ref initialCount, ref octets);
                    if (0x04 != b)
                    {
                        StringBuilder sb = new StringBuilder("Expected Octet String. ");
                        sb.AppendFormat("Specified Identifier: {0}", b.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    int length = GetLength(ref initialCount, ref octets);
                    if (length > RemainingBytes(octets))
                    {
                        StringBuilder sb = new StringBuilder("Incorrect Octet String Size. ");
                        sb.AppendFormat("Specified: {0}, Remaining: {1}",
                          length.ToString(CultureInfo.InvariantCulture),
                          RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    return length;
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
            }
            private static byte[] Next(ref int initialCount, ref List<byte> octets)
            {
                int position = CurrentPosition(initialCount, octets);

                try
                {
                    byte b = GetNextOctet(ref initialCount, ref octets);

                    int length = GetLength(ref initialCount, ref octets);
                    if (length > RemainingBytes(octets))
                    {
                        StringBuilder sb = new StringBuilder("Incorrect Size. ");
                        sb.AppendFormat("Specified: {0}, Remaining: {1}",
                          length.ToString(CultureInfo.InvariantCulture),
                          RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    return GetOctets(ref initialCount, ref octets, length);
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
            }
            private static int NextNull(ref int initialCount, ref List<byte> octets)
            {
                int position = CurrentPosition(initialCount, octets);
                try
                {
                    byte b = GetNextOctet(ref initialCount, ref octets);
                    if (0x05 != b)
                    {
                        StringBuilder sb = new StringBuilder("Expected Null. ");
                        sb.AppendFormat("Specified Identifier: {0}", b.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    // Next octet must be 0
                    b = GetNextOctet(ref initialCount, ref octets);
                    if (0x00 != b)
                    {
                        StringBuilder sb = new StringBuilder("Null has non-zero size. ");
                        sb.AppendFormat("Size: {0}", b.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    return 0;
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
            }
            private static bool IsNextNull(List<byte> octets)
            {
                return 0x05 == octets[0];
            }
            private static bool EqualOid(byte[] first, byte[] second)
            {
                if (first.Length != second.Length) { return false; }
                for (int i = 0; i < first.Length; i++)
                {
                    if (first[i] != second[i]) { return false; }
                }
                return true;
            }
            private static byte[] NextOID(ref int initialCount, ref List<byte> octets)
            {
                int position = CurrentPosition(initialCount, octets);
                try
                {
                    byte b = GetNextOctet(ref initialCount, ref octets);
                    if (0x06 != b)
                    {
                        StringBuilder sb = new StringBuilder("Expected Object Identifier. ");
                        sb.AppendFormat("Specified Identifier: {0}",
                          b.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    int length = GetLength(ref initialCount, ref octets);
                    if (length > RemainingBytes(octets))
                    {
                        StringBuilder sb = new StringBuilder("Incorrect Object Identifier Size. ");
                        sb.AppendFormat("Specified: {0}, Remaining: {1}",
                          length.ToString(CultureInfo.InvariantCulture),
                          RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    byte[] values = new byte[length];
                    for (int i = 0; i < length; i++)
                    {
                        values[i] = octets[0];
                        octets.RemoveAt(0);
                    }
                    return values;
                }

                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
            }
            private static byte[] NextInteger(ref int initialCount, ref List<byte> octets)
            {
                int position = CurrentPosition(initialCount, octets);
                try
                {
                    byte b = GetNextOctet(ref initialCount, ref octets);
                    if (0x02 != b)
                    {
                        StringBuilder sb = new StringBuilder("Expected Integer. ");
                        sb.AppendFormat("Specified Identifier: {0}", b.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    int length = GetLength(ref initialCount, ref octets);
                    if (length > RemainingBytes(octets))
                    {
                        StringBuilder sb = new StringBuilder("Incorrect Integer Size. ");
                        sb.AppendFormat("Specified: {0}, Remaining: {1}",
                          length.ToString(CultureInfo.InvariantCulture),
                          RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    return GetOctets(ref initialCount, ref octets, length);
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
            }
            private static int CurrentPosition(int initialCount, List<byte> octets)
            {
                return initialCount - octets.Count;
            }
            private static int RemainingBytes(List<byte> octets)
            {
                return octets.Count;
            }
            private static byte[] GetOctets(ref int initialCount, ref List<byte> octets, int octetCount)
            {
                int position = CurrentPosition(initialCount, octets);
                if (octetCount > RemainingBytes(octets))
                {
                    StringBuilder sb = new StringBuilder("Incorrect Size. ");
                    sb.AppendFormat("Specified: {0}, Remaining: {1}",
                      octetCount.ToString(CultureInfo.InvariantCulture),
                      RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                byte[] values = new byte[octetCount];
                try
                {
                    octets.CopyTo(0, values, 0, octetCount);
                    octets.RemoveRange(0, octetCount);
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
                return values;
            }
            private static byte GetNextOctet(ref int initialCount, ref List<byte> octets)
            {
                int position = CurrentPosition(initialCount, octets);
                if (0 == RemainingBytes(octets))
                {
                    StringBuilder sb = new StringBuilder("Incorrect Size. ");
                    sb.AppendFormat("Specified: {0}, Remaining: {1}",
                      1.ToString(CultureInfo.InvariantCulture),
                      RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                    //throw new BerDecodeException(sb.ToString(), position);
                    throw new Exception(sb.ToString());
                }
                byte b = GetOctets(ref initialCount, ref octets, 1)[0];
                return b;
            }
            private static int GetLength(ref int initialCount, ref List<byte> octets)
            {
                int length = 0;
                // Checkpoint
                int position = CurrentPosition(initialCount, octets);
                try
                {
                    byte b = GetNextOctet(ref initialCount, ref octets);
                    if (b == (b & 0x7f)) { return b; }
                    int i = b & 0x7f;
                    if (i > 4)
                    {
                        StringBuilder sb = new StringBuilder("Invalid Length Encoding. ");
                        sb.AppendFormat("Length uses {0} octets",
                          i.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    while (0 != i--)
                    {
                        // shift left
                        length <<= 8;
                        length |= GetNextOctet(ref initialCount, ref octets);
                    }
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
                return length;
            }
            private static int NextSequence(ref int initialCount, ref List<byte> octets, out byte b)
            {
                int position = CurrentPosition(initialCount, octets);
                try
                {
                    b = GetNextOctet(ref initialCount, ref octets);
                    int length = 0;
                    if (0x30 == b)  // PKCS8
                    {
                        length = GetLength(ref initialCount, ref octets);
                        if (length > RemainingBytes(octets))
                        {
                            StringBuilder sb = new StringBuilder("Incorrect Sequence Size. ");
                            sb.AppendFormat("Specified: {0}, Remaining: {1}",
                              length.ToString(CultureInfo.InvariantCulture),
                              RemainingBytes(octets).ToString(CultureInfo.InvariantCulture));
                            //throw new BerDecodeException(sb.ToString(), position);
                            throw new Exception(sb.ToString());
                        }
                    }
                    if (0x02 == b)  // PKCS1
                    {
                        byte x = GetOctets(ref initialCount, ref octets, 1)[0];
                        if (x == 0x81)
                        {
                            length = GetOctets(ref initialCount, ref octets, 1)[0];
                        }
                        else if (x == 0x82)
                        {
                            byte h = GetOctets(ref initialCount, ref octets, 1)[0];
                            byte l = GetOctets(ref initialCount, ref octets, 1)[0];
                            byte[] m = { l, h, 0x00, 0x00 };
                            length = BitConverter.ToInt32(m, 0);
                            //length = h<<8|l;
                        }
                        else
                        {
                            length = x;
                        }
                        while (octets[0] == 0x00)
                        {
                            GetOctets(ref initialCount, ref octets, 1);
                            length--;
                        }
                    }
                    if (length == 0)
                    {
                        StringBuilder sb = new StringBuilder("Expected Sequence. ");
                        sb.AppendFormat("Specified Identifier: {0}",
                          b.ToString(CultureInfo.InvariantCulture));
                        //throw new BerDecodeException(sb.ToString(), position);
                        throw new Exception(sb.ToString());
                    }
                    return length;
                }
                catch (ArgumentOutOfRangeException ex)
                {
                    //throw new BerDecodeException("Error Parsing Key", position, ex);
                    throw ex;
                }
            }
        }
    }

调用方法也很简单

string base64 = FileHelper.FileToString(fi.FullName);
if (Regex.IsMatch(base64, @"^[-]+BEGIN"))
{
    base64 = Regex.Match(base64, @"(?<=KEY[-]+[\r\n]+)[\s\S]+(?=[\r\n]+[-]+END)").Value;
    base64 = Regex.Replace(base64, @"[\r\n]+", "");
}
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(8);
rsa.ImportParameters(AsnParser.ParseRSAPrivateKey(Convert.FromBase64String(base64)));

直接从密钥文件中得到的密钥数据,掐头去尾,把回车换行去掉之后转个码,然后用AsnParser解析成RSAParameters对象,直接导入

至于PKCS1和PKCS8的区别,则在AsnParser的NextSequence方法中有体现,第八个字节为48,即0x30时,为PKCS8格式,如果第八个字节为2,即0x02时,则为PKCS1,为其他值时,则为验证数据

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
ECB和PKCS7都是填充方式,而AES是加密算法,它们之间是不同的概念。在C#中,可以使用System.Security.Cryptography命名空间下的类库来进行AES加密和填充方式的转换。 以下是将ECB和PKCS7转换为AES加密算法的代码示例: ```csharp using System; using System.Security.Cryptography; using System.Text; class Program { static void Main(string[] args) { // 待加密的数据和密钥 string plainText = "Hello World!"; byte[] key = Encoding.UTF8.GetBytes("0123456789ABCDEF"); // 创建AES加密算法实例 Aes aes = Aes.Create(); aes.Mode = CipherMode.ECB; // 设置加密模式为ECB aes.KeySize = key.Length * 8; // 设置密钥长度 aes.Padding = PaddingMode.PKCS7; // 设置填充方式为PKCS7 aes.Key = key; // 创建加密器和解密器 ICryptoTransform encryptor = aes.CreateEncryptor(); ICryptoTransform decryptor = aes.CreateDecryptor(); // 加密明文数据 byte[] encryptedData = encryptor.TransformFinalBlock(Encoding.UTF8.GetBytes(plainText), 0, plainText.Length); // 解密密文数据 byte[] decryptedData = decryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length); // 输出加密和解密后的数据 Console.WriteLine("加密前:" + plainText); Console.WriteLine("加密后:" + Convert.ToBase64String(encryptedData)); Console.WriteLine("解密后:" + Encoding.UTF8.GetString(decryptedData)); } } ``` 在上面的代码中,我们使用了Aes.Create()方法来创建一个AES加密算法实例,使用CipherMode.ECB和PaddingMode.PKCS7来分别指定加密模式和填充方式,并通过CreateEncryptor()和CreateDecryptor()方法创建加密器和解密器。最后,将明文数据转换为字节数组后调用TransformFinalBlock()方法进行加密和解密,并将结果输出到控制台。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文盲老顾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值