openssl使用以及C#加密和数字签名


如何使用openssl生成RSA公钥和私钥对

http://blog.csdn.net/scape1989/article/details/18959657

https://www.openssl.org/docs/manmaster/apps/rsautl.html


C# RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密

http://www.2cto.com/kf/201007/52626.html

RSA Key Converter(XML to PEM,PEM to XML)
https://superdry.apphb.com/tools/online-rsa-key-converter

openssl
it defaulte generate RSA format , sometimes need convert to pkcs8 format

generate a private key pair with pkcs8 format
openssl>pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt

generate a private key pair with pem format
openssl>genrsa -out rsa_private_key.pem 1024

output the public key 

openssl>rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

use public key to encrypt data
openssl>rsautl -encrypt -in orig.txt -inkey rsa_public_key.pem -pubin -out orig.en 

use private key to decrypt data 
openssl>rsautl -decrypt -in orig.en -inkey rsa_private_key.pem -out orig.de

use private key to signature data 
rsautl  -sign -in orig.txt -inkey rsa_private_key.pem -out sig

output the data with private key from signed data
rsautl -verify -in sig -inkey rsa_private_key.pem

!!!Error:output the data with public key from signed data
rsautl -verify -in sig -inkey rsa_public_key.pem

Examine the reaw signed data
rsautl -verify -in sig -inkey rsa_private_key.pem -raw -hexdump


SSOBLL sso = newSSOBLL();

string signature = sso.SignData(string.Empty,SSOBLL.KeyType.PrivatePEM, sigData);

string signature2 = sso.SignData(string.Empty,SSOBLL.KeyType.PrivateXML, sigData);

bool valid = sso.VerifySignData(string.Empty,SSOBLL.KeyType.PublicXML,sigData,Convert.FromBase64String(signature));



public class SSOBLL
    {
        public enum KeyType
        {
            PrivatePEM,
            PublicPEM,
            PrivateXML,
            PublicXML
        }

        public string SignData(string privateKeyStr, KeyType keyType, string dataStr)
        {
            byte[] data = Encoding.UTF8.GetBytes(dataStr);
            string base64 = string.Empty;
            if (keyType == KeyType.PrivatePEM)
            {
                
                string keyStr = GetKey(privateKeyStr, KeyType.PrivatePEM);
                byte[] privateKey = Helpers.GetBytesFromPEM(keyStr, PemStringType.RsaPrivateKey);
                RSACryptoServiceProvider rsa = Crypto.DecodeRsaPrivateKey(privateKey);
                byte[] hash = rsa.SignData(data, SHA1.Create());
                base64 = Convert.ToBase64String(hash);
            }
            if (keyType == KeyType.PrivateXML)
            {
                string privatekey = GetKey(privateKeyStr, keyType);
                RSACryptoServiceProvider oRSA3 = new RSACryptoServiceProvider();
                oRSA3.FromXmlString(privatekey);
                byte[] BOutput = oRSA3.SignData(data, "SHA1");
                base64 = Convert.ToBase64String(BOutput);
            }
            return base64;
        }

        public bool VerifySignData(RSACryptoServiceProvider rsa, KeyType keyType, string dataStr, byte[] dataHash)
        {
            byte[] data = Encoding.UTF8.GetBytes(dataStr);
            bool valid = false;
            if (keyType == KeyType.PublicPEM)
            {
                RSAParameters key = rsa.ExportParameters(false); // false:公钥  true:私钥
                RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
                RSAalg.ImportParameters(key);
                valid = RSAalg.VerifyData(data, new SHA1CryptoServiceProvider(), dataHash);
            }
            else if (keyType == KeyType.PublicXML)
            {
                string publickey = rsa.ToXmlString(false);//false:公钥  true:私钥
                valid = VerifySignData(publickey, keyType, dataStr, dataHash);
            }
            return valid;
        }

        public bool VerifySignData(string keyStr, KeyType keyType, string dataStr, byte[] dataHash)
        {
            byte[] data = Encoding.UTF8.GetBytes(dataStr);
            bool valid = false;
            if (keyType == KeyType.PublicXML)
            {
                RSACryptoServiceProvider oRSA4 = new RSACryptoServiceProvider();
                string publickey = GetKey(keyStr, KeyType.PublicXML);
                oRSA4.FromXmlString(publickey);
                valid = oRSA4.VerifyData(data, "SHA1", dataHash);
            }
            return valid;
        }

        private string GetKey(string keyStr, KeyType keyType)
        {
            string key = keyStr;
            if (string.IsNullOrWhiteSpace(keyStr))
            {
                string KeyFile = AppDomain.CurrentDomain.BaseDirectory;
                switch (keyType)
                {
                    case KeyType.PrivatePEM:
                        KeyFile += @"Keysprivate.pem";
                        break;
                    case KeyType.PublicPEM:
                        KeyFile += @"Keyspublic.pem";
                        break;
                    case KeyType.PrivateXML:
                        KeyFile += @"Keysprivate.xml";
                        break;
                    case KeyType.PublicXML:
                        KeyFile += @"Keyspublic.xml";
                        break;
                    default:
                        KeyFile += @"Keysprivate.pem";
                        break;
                }
                key = File.ReadAllText(KeyFile);
            }
            return key;
        }

     
    }



   public class Crypto
    {
        /// <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();
            }
        }
    }

   public enum PemStringType
    {
        Certificate,
        RsaPrivateKey,
        RsaPublicKey
    }

    public class Helpers
    {
        /// <summary>
        /// This helper function parses an integer size from the reader using the ASN.1 format
        /// </summary>
        /// <param name="rd"></param>
        /// <returns></returns>
        public static int DecodeIntegerSize(System.IO.BinaryReader rd)
        {
            byte byteValue;
            int count;

            byteValue = rd.ReadByte();
            if (byteValue != 0x02)        // indicates an ASN.1 integer value follows
                return 0;

            byteValue = rd.ReadByte();
            if (byteValue == 0x81)
            {
                count = rd.ReadByte();    // data size is the following byte
            }
            else if (byteValue == 0x82)
            {
                byte hi = rd.ReadByte();  // data size in next 2 bytes
                byte lo = rd.ReadByte();
                count = BitConverter.ToUInt16(new[] { lo, hi }, 0);
            }
            else
            {
                count = byteValue;        // we already have the data size
            }

            //remove high order zeros in data
            while (rd.ReadByte() == 0x00)
            {
                count -= 1;
            }
            rd.BaseStream.Seek(-1, System.IO.SeekOrigin.Current);

            return count;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pemString"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static byte[] GetBytesFromPEM(string pemString, PemStringType type)
        {
            string header; string footer;

            switch (type)
            {
                case PemStringType.Certificate:
                    header = "-----BEGIN CERTIFICATE-----";
                    footer = "-----END CERTIFICATE-----";
                    break;
                case PemStringType.RsaPrivateKey:
                    header = "-----BEGIN RSA PRIVATE KEY-----";
                    footer = "-----END RSA PRIVATE KEY-----";
                    break;
                case PemStringType.RsaPublicKey:
                    header = "-----BEGIN PUBLIC KEY-----";
                    footer = "-----END PUBLIC KEY-----";
                    break;
                default:
                    return null;
            }

            int start = pemString.IndexOf(header) + header.Length;
            int end = pemString.IndexOf(footer, start) - start;
            return Convert.FromBase64String(pemString.Substring(start, end));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="inputBytes"></param>
        /// <param name="alignSize"></param>
        /// <returns></returns>
        public static byte[] AlignBytes(byte[] inputBytes, int alignSize)
        {
            int    inputBytesSize = inputBytes.Length;

            if ((alignSize != -1) && (inputBytesSize < alignSize))
            {
                byte[] buf = new byte[alignSize];
                for (int i = 0; i < inputBytesSize; ++i)
                {
                    buf[i + (alignSize - inputBytesSize)] = inputBytes[i];
                }
                return buf;
            }
            else
            {
                return inputBytes;      // Already aligned, or doesn't need alignment
            }
        }

   internal class RSAParameterTraits
    {
        public RSAParameterTraits(int modulusLengthInBits)
        {
            // The modulus length is supposed to be one of the common lengths, which is the commonly referred to strength of the key,
            // like 1024 bit, 2048 bit, etc.  It might be a few bits off though, since if the modulus has leading zeros it could show
            // up as 1016 bits or something like that.
            int assumedLength = -1;
            double logbase = Math.Log(modulusLengthInBits, 2);
            if (logbase == (int)logbase)
            {
                // It's already an even power of 2
                assumedLength = modulusLengthInBits;
            }
            else
            {
                // It's not an even power of 2, so round it up to the nearest power of 2.
                assumedLength = (int)(logbase + 1.0);
                assumedLength = (int)(Math.Pow(2, assumedLength));
                System.Diagnostics.Debug.Assert(false);  // Can this really happen in the field?  I've never seen it, so if it happens
                // you should verify that this really does the 'right' thing!
            }

            switch (assumedLength)
            {
                case 1024:
                    this.size_Mod = 0x80;
                    this.size_Exp = -1;
                    this.size_D = 0x80;
                    this.size_P = 0x40;
                    this.size_Q = 0x40;
                    this.size_DP = 0x40;
                    this.size_DQ = 0x40;
                    this.size_InvQ = 0x40;
                    break;
                case 2048:
                    this.size_Mod = 0x100;
                    this.size_Exp = -1;
                    this.size_D = 0x100;
                    this.size_P = 0x80;
                    this.size_Q = 0x80;
                    this.size_DP = 0x80;
                    this.size_DQ = 0x80;
                    this.size_InvQ = 0x80;
                    break;
                case 4096:
                    this.size_Mod = 0x200;
                    this.size_Exp = -1;
                    this.size_D = 0x200;
                    this.size_P = 0x100;
                    this.size_Q = 0x100;
                    this.size_DP = 0x100;
                    this.size_DQ = 0x100;
                    this.size_InvQ = 0x100;
                    break;
                default:
                    System.Diagnostics.Debug.Assert(false); // Unknown key size?
                    break;
            }
        }

        public int size_Mod  = -1;
        public int size_Exp  = -1;
        public int size_D    = -1;
        public int size_P    = -1;
        public int size_Q    = -1;
        public int size_DP   = -1;
        public int size_DQ   = -1;
        public int size_InvQ = -1;
    }




原文地址:https://www.cnblogs.com/sui84/p/6777024.html