Coder Social home page Coder Social logo

stefh / openssl-x509certificate2-provider Goto Github PK

View Code? Open in Web Editor NEW
53.0 7.0 14.0 2.18 MB

Parses OpenSSL public and private key components and returns a X509Certificate2 with RSACryptoServiceProvider. Based on opensslkey

License: MIT License

C# 100.00%

openssl-x509certificate2-provider's Introduction

OpenSSL X509Certificate2 Provider

Parses OpenSSL public and private key components and returns a X509Certificate2 with RSA/RSACryptoServiceProvider. (Based on http://www.jensign.com/opensslkey/opensslkey.cs (Archive Link))

Project NuGet
OpenSSL.PrivateKeyDecoder NuGet Badge
OpenSSL.PublicKeyDecoder NuGet Badge
OpenSSL.X509Certificate2.Provider NuGet Badge

Support for the following frameworks:

  • .NET 2.0
  • .NET 3.5
  • .NET 4.5 and up
  • .NET Standard 1.3 (also NET Core 1.1)
  • .NET Standard 2.0 (also NET Core 2.0 and 2.1)

Support for decoding RSA Private Key, Private Key and Public Key.

Example

Generate public certificate + privatekey

Generate public certificate + privatekey using:

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt

Code example 1 - decode private key into RSAParameters

If you just want to decode the private key into RSAParameters, use the following code:

string privateKeyText = File.ReadAllText("private.key");

IOpenSSLPrivateKeyDecoder decoder = new OpenSSLPrivateKeyDecoder();
RSAParameters parameters = decoder.DecodeParameters(privateKeyText);

// do something with the parameters ...

Code example 2 - decode private key into a RSACryptoServiceProvider

If you want to decode the private key into a RSACryptoServiceProvider, use the following code:

string privateKeyText = File.ReadAllText("private.key");

IOpenSSLPrivateKeyDecoder decoder = new OpenSSLPrivateKeyDecoder();
RSACryptoServiceProvider cryptoServiceProvider = decoder.Decode(privateKeyText);

// Example: sign the data
byte[] hello = new UTF8Encoding().GetBytes("Hello World");
byte[] hashValue = cryptoServiceProvider.SignData(hello, CryptoConfig.MapNameToOID("SHA256"));

// Example: use the PrivateKey from above for signing a JWT token using Jose.Jwt:
string token = Jose.JWT.Encode(payload, cryptoServiceProvider, JwsAlgorithm.RS256);

Code example 3 - Create a X509 certificate and add private key

string certificateText = File.ReadAllText("certificate_pub.crt");
string privateKeyText = File.ReadAllText("private.key");

ICertificateProvider provider = new CertificateFromFileProvider(certificateText, privateKeyText);
X509Certificate2 certificate = provider.Certificate;

// Example: use the PrivateKey from the certificate above for signing a JWT token using Jose.Jwt:
string token = Jose.JWT.Encode(payload, certificate.PrivateKey, JwsAlgorithm.RS256);

Code example 4 - decode openssl RSA public key into RSAParameters

If you just want to decode the rsa public key into RSAParameters, use the following code:

Export the public key from the private key with openssl

openssl rsa -in private.key -out public.key -pubout
string publicKeyText = File.ReadAllText("public.key");

IOpenSSLPublicKeyDecoder decoder = new OpenSSLPublicKeyDecoder();
RSAParameters parameters = decoder.DecodeParameters(publicKeyText);

openssl-x509certificate2-provider's People

Contributors

nelsonjchen avatar stefh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

openssl-x509certificate2-provider's Issues

Sign Assembly

Hi Stef, great job on the library! worked like a charm.

I have one problem though, my project is signed, so it doesn't build after including your assembly. Could you please sign your assembly?

Thanks in advance.

Best practice for using provider to load OpenSSL PEM files for HttpWebRequest client certificate authentication?

I have to do this workaround to be able to use PEM certificates from this provider in HttpWebRequest:

{
	var cspLessPrivateKey = provider.PrivateKey;
	CspParameters cspParameters = new CspParameters {KeyContainerName = $"{{{Guid.NewGuid().ToString()}}}"};
	var cspPrivateKey = new RSACryptoServiceProvider(cspParameters);
	cspPrivateKey.ImportParameters(cspLessPrivateKey.ExportParameters(true));
	certificate.PrivateKey = cspPrivateKey;
}

The RSACryptoServiceProvider needs to be replaced with a new RSACryptoServiceProvider that has a KeyContainerName set.

Is this a good practice? I'm trying to replicate the X509Certificate2 constructor where you pass in a pfx or P12 file but with:

var certificate =
    new X509Certificate2(@"C:\Users\User\Documents\HTTPClientCertDownload\HTTPClientCertDownload\export.p12");                

From what I can see, the RSACryptoServiceProviders for the PrivateKey in that have a $"{{{Guid.NewGuid().ToString()}}}" as their key container names for that constructor.

Without the workaround, I get this error, which I assume is because the PrivateKey is not stored in some sort of accessible container to the HttpWebRequest:

Unhandled Exception: System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
   at System.Net.HttpWebRequest.GetResponse()
   at HTTPClientCertDownload.Program.Main(String[] args) in C:\Users\User\Documents\HTTPClientCertDownload\HTTPClientCertDownload\Program.cs:line 50

The PFX/PKCS12 certificate works fine though. I did do a sanity check with cURL though WSL and it loads the PEM files fine and establishes the TLS connection correctly and grabs the data from the test server.

Full code

using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using OpenSSL.X509Certificate2Provider;

namespace HTTPClientCertDownload
{
    static class Program
    {
        static void Main(string[] args)
        {
            string certificateText =
                File.ReadAllText(@"C:\Users\User\Documents\HTTPClientCertDownload\HTTPClientCertDownload\crt.pem");
            string privateKeyText =
                File.ReadAllText(@"C:\Users\User\Documents\HTTPClientCertDownload\HTTPClientCertDownload\key.pem");

            ICertificateProvider provider = new CertificateFromFileProvider(certificateText, privateKeyText);
            X509Certificate2 certificate = provider.Certificate;

            // Replace Private Key with Private Key stored in a named KeyContainer.
            // The block of code below patches up the PrivateKey to mimic enough of a PKCS12 Certificate import
            // where the PrivateKey is stored in a named CSP.
            {
                var cspLessPrivateKey = provider.PrivateKey;
                CspParameters cspParameters = new CspParameters {KeyContainerName = $"{{{Guid.NewGuid().ToString()}}}"};
                var cspPrivateKey = new RSACryptoServiceProvider(cspParameters);
                cspPrivateKey.ImportParameters(cspLessPrivateKey.ExportParameters(true));
                certificate.PrivateKey = cspPrivateKey;
            }

            HttpWebRequest req = (HttpWebRequest) WebRequest.Create(@"https://server.cryptomix.com/secure/");

            // Workaround for .NET 4.0
            ServicePointManager.Expect100Continue = true;
            ServicePointManager.SecurityProtocol = (SecurityProtocolType) 3072;
            req.PreAuthenticate = true;
            ServicePointManager.DefaultConnectionLimit = 9999;
            // Ignore Server Certificate
            ServicePointManager
                    .ServerCertificateValidationCallback +=
                (sender, cert, chain, sslPolicyErrors) => true;

            req.ClientCertificates.Add(certificate);

            HttpWebResponse response = (HttpWebResponse) req.GetResponse();

            var encoding = Encoding.ASCII;
            using (var reader = new StreamReader(response.GetResponseStream(), encoding))
            {
                string responseText = reader.ReadToEnd();
                Console.WriteLine(responseText);
            }
        }
    }
}

Cannot decrypt private key encrypted with passphrase

I am trying to generate 1 certificate with 1 public key and 1 private key with the following format

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,5E39D2DDBA544FDE

3+ptiWruvYHzhX+rpSC3852..............................
-----END RSA PRIVATE KEY-----

But when I run the following code
ICertificateProvider provider = new CertificateFromFileProvider(publicKey, privateKey, false, passpharse);
, it returns an exeption like this:
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
Looking forward to hearing from you

"BEGIN PRIVATE KEY" sometimes isn't recognized

I ran https://github.com/StefH/OpenSSL-X509Certificate2-Provider#code-example-3---create-a-x509-certificate-and-add-private-key on a key file without RSA in the header or footer and ran into an error: "The server mode SSL must use a certificate with the associated private key."

Changing the header and footer to BEGIN RSA PRIVATE KEY and END RSA PRIVATE KEY worked, but I'm not sure why considering this library appears to support both forms https://github.com/StefH/OpenSSL-X509Certificate2-Provider/search?q=begin+private+key&unscoped_q=begin+private+key

An exception about "The credentials supplied to the package were not recognized"

Dear StefH

I'm developing a tls server now. I used OpenSSL-X509Certificate2-Provider to import .crt&.key, but when run to AuthenticateAsServerAsync(), an exception occurred with error message"The credentials supplied to the package were not recognized". In the other hand, it works well by converted crt&key to pfx format through openssl tool. So what's wrong here? Is the RSA private key supported? If not, i saw it in the source code.

OpenSSLPrivateKeyDecoder.Decode fails on .Net Core on Linux

If you call OpenSSLPrivateKeyDecoder.Decode running on .Net Core on Linux (or docker for windows), this call fails with

PlatformNotSupportedException: Operation is not supported on this platform

.

The error happens on System.Security.Cryptography.RSACryptoServiceProvider..ctor() because RSACryptoServiceProvider is a windows-only concept.

I think it would be more compatible to return just the RSAParameters object instead of trying to wrap it with RSACryptoServiceProvider.

We could extend this with with a DecodeParams function that keeps all the inner logic but returns RSAParameter, and still have the existing Decode functions that just wrap that with RSACryptoServiceProvider.

Alternatively, you could just return an RSA object, that on windows I think just wraps RSACryptoServiceProvider.

I want to use this library but I'm stuck.

InvalidCastException on constructor

Hello.

I have :
System.InvalidCastException : Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.
at OpenSSL.X509Certificate2Provider.CertificateFromFileProvider..ctor(String certificateText, String privateKeyText, SecureString securePassword)

         var dataCrt = @"-----BEGIN CERTIFICATE-----
         MIIE9DCCA9ygAwIBAgIRAO/GFHEnfG7PfRsqfJE2XCMwDQYJKoZIhvcNAQELBQAw
         ...
         sbLyGg+ZHI2KE9mVzmsgITnzuaD1gXmc
         -----END CERTIFICATE-----";
         var dataKey = @"-----BEGIN PRIVATE KEY-----
         MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC8UIRu1ho6sD+6
         ...
         VCASulQriYsBYxeSBSXVEA==
         -----END PRIVATE KEY-----";
         var provider = new OpenSSL.X509Certificate2Provider.CertificateFromFileProvider(dataCrt,dataKey);
         var cert = provider.Certificate;
         Assert.True(cert.Verify());
         Assert.True(cert.HasPrivateKey);

I'm using dotnet core 2.0

Decode private key doesn't work.

Below code generates Exception thrown: 'System.Security.Cryptography.CryptographicException' in mscorlib.dll.
I am using .NET 4.6.1 with 4096 bits RSA private key

string pkey = File.ReadAllText(@"C:\Temp\private.key");
            IOpenSSLPrivateKeyDecoder privateKeyDecode = new OpenSSLPrivateKeyDecoder();
            var rsa = privateKeyDecode.DecodeParameters(pkey);
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.ImportParameters(rsa);

Private key is not added

I tried the Code example 3 - Create a X509 certificate and add private key, but the created certificate does not contain the private key. (certificate.HasPrivateKey = false, certificate.PrivateKey = null)

Specified Method is not supported.

Hi,
i'm trying to encrypt data, but i am having a Specified Method is not supported.

Target is a Windows application, .NET 4.5.2

protected RSACryptoServiceProvider CreateProvider()
        {
            var privateKeyText = GetPrivateKey();

            IOpenSSLPrivateKeyDecoder decoder = new OpenSSLPrivateKeyDecoder();
            var RSA1 = decoder.Decode(privateKeyText);

            return RSA1;

        }

        public static string Encrypt(string decryptedData)
        {
            Utils c = new Utils();
            
            var val =  c.CreateProvider().SignData(new UTF8Encoding().GetBytes(decryptedData), CryptoConfig.MapNameToOID("SHA1"));
            return Convert.ToBase64String(val);
        }

I call the function Encrypt, but when it's called the CreateProvider() function, on the " var RSA1 = decoder.Decode(privateKeyText);" it gives the exception.

Any ideas?

openssl x509 certificate

how can we implement x509 certificate using netopeer 2 ? already we have created a x509 certificate on linux platform . i have refered below README.txt file to create x509 certificate . so same thing how we can do it with the netopeer2 ?
README.txt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.