示例#1
0
        internal static RSACryptoServiceProvider DecodePublicKey(byte[] publicKeyBytes)
        {
            MemoryStream ms = new MemoryStream(publicKeyBytes);
            BinaryReader rd = new BinaryReader(ms);

            byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
            byte[] seq    = new byte[15];

            try
            {
                byte   byteValue;
                ushort shortValue;

                shortValue = rd.ReadUInt16();

                switch (shortValue)
                {
                case 0x8130:
                    rd.ReadByte(); break;

                case 0x8230:
                    rd.ReadInt16(); break;

                default:
                    return(null);
                }

                seq = rd.ReadBytes(15); if (!Helpers.CompareBytearrays(seq, SeqOID))
                {
                    return(null);
                }

                shortValue = rd.ReadUInt16();
                if (shortValue == 0x8103)
                {
                    rd.ReadByte();
                }
                else if (shortValue == 0x8203)
                {
                    rd.ReadInt16();
                }
                else
                {
                    return(null);
                }

                byteValue = rd.ReadByte();
                if (byteValue != 0x00)
                {
                    return(null);
                }

                shortValue = rd.ReadUInt16();
                if (shortValue == 0x8130)
                {
                    rd.ReadByte();
                }
                else if (shortValue == 0x8230)
                {
                    rd.ReadInt16();
                }
                else
                {
                    return(null);
                }


                CspParameters parms = new CspParameters();
                parms.Flags            = CspProviderFlags.NoFlags;
                parms.KeyContainerName = Guid.NewGuid().ToString().ToUpperInvariant();
                parms.ProviderType     = ((Environment.OSVersion.Version.Major > 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor >= 1))) ? 0x18 : 1;

                RSACryptoServiceProvider rsa       = new RSACryptoServiceProvider(parms);
                RSAParameters            rsAparams = new RSAParameters();

                rsAparams.Modulus = rd.ReadBytes(Helpers.DecodeIntegerSize(rd));

                RSAParameterTraits traits = new RSAParameterTraits(rsAparams.Modulus.Length * 8);

                rsAparams.Modulus  = Helpers.AlignBytes(rsAparams.Modulus, traits.size_Mod);
                rsAparams.Exponent = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_Exp);

                rsa.ImportParameters(rsAparams);
                return(rsa);
            }
            catch (Exception)
            {
                return(null);
            }
            finally
            {
                rd.Close();
            }
        }
示例#2
0
        /// <summary>
        /// This helper function parses an RSA private key using the ASN.1 format
        /// </summary>
        /// <param name="privateKeyBytes">Byte array containing PEM string of private key.</param>
        /// <returns>An instance of <see cref="RSACryptoServiceProvider"/> rapresenting the requested private key.
        /// Null if method fails on retriving the key.</returns>
        public static RSACryptoServiceProvider DecodeRsaPrivateKey(byte[] privateKeyBytes)
        {
            MemoryStream ms = new MemoryStream(privateKeyBytes);
            BinaryReader rd = new BinaryReader(ms);

            try
            {
                byte   byteValue;
                ushort shortValue;

                shortValue = rd.ReadUInt16();

                switch (shortValue)
                {
                case 0x8130:
                    // If true, data is little endian since the proper logical seq is 0x30 0x81
                    rd.ReadByte();     //advance 1 byte
                    break;

                case 0x8230:
                    rd.ReadInt16();      //advance 2 bytes
                    break;

                default:
                    Debug.Assert(false);         // Improper ASN.1 format
                    return(null);
                }

                shortValue = rd.ReadUInt16();
                if (shortValue != 0x0102) // (version number)
                {
                    Debug.Assert(false);  // Improper ASN.1 format, unexpected version number
                    return(null);
                }

                byteValue = rd.ReadByte();
                if (byteValue != 0x00)
                {
                    Debug.Assert(false);     // Improper ASN.1 format
                    return(null);
                }

                // The data following the version will be the ASN.1 data itself, which in our case
                // are a sequence of integers.

                // In order to solve a problem with instancing RSACryptoServiceProvider
                // via default constructor on .net 4.0 this is a hack
                CspParameters parms = new CspParameters();
                parms.Flags            = CspProviderFlags.NoFlags;
                parms.KeyContainerName = Guid.NewGuid().ToString().ToUpperInvariant();
                parms.ProviderType     = ((Environment.OSVersion.Version.Major > 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor >= 1))) ? 0x18 : 1;

                RSACryptoServiceProvider rsa       = new RSACryptoServiceProvider(parms);
                RSAParameters            rsAparams = new RSAParameters();

                rsAparams.Modulus = rd.ReadBytes(Helpers.DecodeIntegerSize(rd));

                // Argh, this is a pain.  From emperical testing it appears to be that RSAParameters doesn't like byte buffers that
                // have their leading zeros removed.  The RFC doesn't address this area that I can see, so it's hard to say that this
                // is a bug, but it sure would be helpful if it allowed that. So, there's some extra code here that knows what the
                // sizes of the various components are supposed to be.  Using these sizes we can ensure the buffer sizes are exactly
                // what the RSAParameters expect.  Thanks, Microsoft.
                RSAParameterTraits traits = new RSAParameterTraits(rsAparams.Modulus.Length * 8);

                rsAparams.Modulus  = Helpers.AlignBytes(rsAparams.Modulus, traits.size_Mod);
                rsAparams.Exponent = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_Exp);
                rsAparams.D        = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_D);
                rsAparams.P        = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_P);
                rsAparams.Q        = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_Q);
                rsAparams.DP       = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_DP);
                rsAparams.DQ       = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_DQ);
                rsAparams.InverseQ = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_InvQ);

                rsa.ImportParameters(rsAparams);
                return(rsa);
            }
            catch (Exception)
            {
                Debug.Assert(false);
                return(null);
            }
            finally
            {
                rd.Close();
            }
        }
示例#3
0
        // x509
        public static RSACryptoServiceProvider DecodePublicKey(byte[] publicKeyBytes)
        {
            MemoryStream ms = new MemoryStream(publicKeyBytes);
            BinaryReader rd = new BinaryReader(ms);
            byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
            byte[] seq = new byte[15];

            try
            {
                byte byteValue;
                ushort shortValue;

                shortValue = rd.ReadUInt16();

                switch (shortValue)
                {
                    case 0x8130:
                        // If true, data is little endian since the proper logical seq is 0x30 0x81
                        rd.ReadByte(); //advance 1 byte
                        break;
                    case 0x8230:
                        rd.ReadInt16();  //advance 2 bytes
                        break;
                    default:
                        Debug.Assert(false);     // Improper ASN.1 format
                        return null;
                }

                seq = rd.ReadBytes(15);		//read the Sequence OID
                if (!Helpers.CompareBytearrays(seq, SeqOID))	//make sure Sequence for OID is correct
                    return null;

                shortValue = rd.ReadUInt16();
                if (shortValue == 0x8103)	//data read as little endian order (actual data order for Bit String is 03 81)
                    rd.ReadByte();	//advance 1 byte
                else if (shortValue == 0x8203)
                    rd.ReadInt16();	//advance 2 bytes
                else
                    return null;

                byteValue = rd.ReadByte();
                if (byteValue != 0x00)
                {
                    Debug.Assert(false);     // Improper ASN.1 format
                    return null;
                }

                shortValue = rd.ReadUInt16();
                if (shortValue == 0x8130)	//data read as little endian order (actual data order for Sequence is 30 81)
                    rd.ReadByte();	//advance 1 byte
                else if (shortValue == 0x8230)
                    rd.ReadInt16();	//advance 2 bytes
                else
                    return null;

                // The data following the version will be the ASN.1 data itself, which in our case
                // are a sequence of integers.

                // In order to solve a problem with instancing RSACryptoServiceProvider
                // via default constructor on .net 4.0 this is a hack
                CspParameters parms = new CspParameters();
                parms.Flags = CspProviderFlags.NoFlags;
                parms.KeyContainerName = Guid.NewGuid().ToString().ToUpperInvariant();
                parms.ProviderType = ((Environment.OSVersion.Version.Major > 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor >= 1))) ? 0x18 : 1;

                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(parms);
                RSAParameters rsAparams = new RSAParameters();

                rsAparams.Modulus = rd.ReadBytes(Helpers.DecodeIntegerSize(rd));

                // Argh, this is a pain.  From emperical testing it appears to be that RSAParameters doesn't like byte buffers that
                // have their leading zeros removed.  The RFC doesn't address this area that I can see, so it's hard to say that this
                // is a bug, but it sure would be helpful if it allowed that. So, there's some extra code here that knows what the
                // sizes of the various components are supposed to be.  Using these sizes we can ensure the buffer sizes are exactly
                // what the RSAParameters expect.  Thanks, Microsoft.
                RSAParameterTraits traits = new RSAParameterTraits(rsAparams.Modulus.Length * 8);

                rsAparams.Modulus = Helpers.AlignBytes(rsAparams.Modulus, traits.size_Mod);
                rsAparams.Exponent = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_Exp);
                //rsAparams.D = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_D);
                //rsAparams.P = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_P);
                //rsAparams.Q = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_Q);
                //rsAparams.DP = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_DP);
                //rsAparams.DQ = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_DQ);
                //rsAparams.InverseQ = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_InvQ);

                rsa.ImportParameters(rsAparams);
                return rsa;
            }
            catch (Exception e)
            {
                Debug.Assert(false);
                return null;
            }
            finally
            {
                rd.Close();
            }
        }
		/// <summary>
		/// This helper function parses an RSA private key using the ASN.1 format
		/// </summary>
		/// <param name="PrivateKeyBytes">Byte array containing PEM string of private key.</param>
		/// <returns>An instance of <see cref="RSACryptoServiceProvider"/> rapresenting the requested private key.
		/// Null if method fails on retriving the key.</returns>
		private static RSACryptoServiceProvider DecodeRsaPrivateKey(byte[] PrivateKeyBytes)
		{
			using (MemoryStream ms = new MemoryStream(PrivateKeyBytes))
			using (BinaryReader rd = new BinaryReader(ms))
			{
				try
				{
					byte byteValue;
					ushort shortValue;

					shortValue = rd.ReadUInt16();

					switch (shortValue)
					{
						case 0x8130:
							// If true, data is little endian since the proper logical seq is 0x30 0x81
							rd.ReadByte(); //advance 1 byte
							break;
						case 0x8230:
							rd.ReadInt16();  //advance 2 bytes
							break;
						default:
							Debug.Assert(false);     // Improper ASN.1 format
							return null;
					}

					shortValue = rd.ReadUInt16();
					if (shortValue != 0x0102) // (version number)
					{
						Debug.Assert(false);     // Improper ASN.1 format, unexpected version number
						return null;
					}

					byteValue = rd.ReadByte();
					if (byteValue != 0x00)
					{
						Debug.Assert(false);     // Improper ASN.1 format
						return null;
					}

					// The data following the version will be the ASN.1 data itself, which in our case
					// are a sequence of integers.

					// In order to solve a problem with instancing RSACryptoServiceProvider
					// via default constructor on .net 4.0 this is a hack
					CspParameters parms = new CspParameters();
					parms.Flags = CspProviderFlags.NoFlags;
					parms.KeyContainerName = Guid.NewGuid().ToString().ToUpperInvariant();
					parms.ProviderType = ((Environment.OSVersion.Version.Major > 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor >= 1))) ? 0x18 : 1;

					RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(parms);
					RSAParameters rsAparams = new RSAParameters();

					rsAparams.Modulus = rd.ReadBytes(DecodeIntegerSize(rd));

					// Argh, this is a pain.  From emperical testing it appears to be that RSAParameters doesn't like byte buffers that
					// have their leading zeros removed.  The RFC doesn't address this area that I can see, so it's hard to say that this
					// is a bug, but it sure would be helpful if it allowed that. So, there's some extra code here that knows what the
					// sizes of the various components are supposed to be.  Using these sizes we can ensure the buffer sizes are exactly
					// what the RSAParameters expect.  Thanks, Microsoft.
					RSAParameterTraits traits = new RSAParameterTraits(rsAparams.Modulus.Length * 8);

					rsAparams.Modulus = AlignBytes(rsAparams.Modulus, traits.size_Mod);
					rsAparams.Exponent = AlignBytes(rd.ReadBytes(DecodeIntegerSize(rd)), traits.size_Exp);
					rsAparams.D = AlignBytes(rd.ReadBytes(DecodeIntegerSize(rd)), traits.size_D);
					rsAparams.P = AlignBytes(rd.ReadBytes(DecodeIntegerSize(rd)), traits.size_P);
					rsAparams.Q = AlignBytes(rd.ReadBytes(DecodeIntegerSize(rd)), traits.size_Q);
					rsAparams.DP = AlignBytes(rd.ReadBytes(DecodeIntegerSize(rd)), traits.size_DP);
					rsAparams.DQ = AlignBytes(rd.ReadBytes(DecodeIntegerSize(rd)), traits.size_DQ);
					rsAparams.InverseQ = AlignBytes(rd.ReadBytes(DecodeIntegerSize(rd)), traits.size_InvQ);

					rsa.ImportParameters(rsAparams);
					return rsa;
				}
				catch (Exception)
				{
					Debug.Assert(false);
					return null;
				}
			}
		}