Skip to content

A multi-platform OpenSSL .NET wrapper containing a high-performance TLS implementation

License

Notifications You must be signed in to change notification settings

sebaFlame/NippyWard.OpenSSL

 
 

Repository files navigation

NippyWard.OpenSSL

A multi-platform OpenSSL .NET wrapper containing a high-performance TLS implementation

Rationale

I was writing some networking code, but the SSL connection would not succeed. This only occured on Windows. On Linux - mono only at the time - the SSL connection always succeeded. Hence I needed an OpenSSL wrapper and stumbled upon https://github.com/openssl-net/openssl-net. This project was already abandoned, but it still ran fine on .NET framwork/mono. After .NET Core came out I kept everything compatible and also started refactoring the code. It has now evovled into a mostly X509/TLS wrapper.

Installation

Linux

Ensure OpenSSL is installed! This should be the default for most if not all distributions. At the time of writing NippyWard.OpenSSL supports ubuntu.16.04-upwards and Debian-8-upwards.

Any other distribution can be added in

switch (RuntimeInformation.RuntimeIdentifier)
{
case "win7-x64":
case "win8-x64":
case "win81-x64":
case "win10-x64":
DLLNAME = "libcrypto-1_1-x64";
SSLDLLNAME = "libssl-1_1-x64";
break;
case "win7-x86":
case "win8-x86":
case "win81-x86":
case "win10-x86":
DLLNAME = "libcrypto-1_1";
SSLDLLNAME = "libssl-1_1";
break;
case "ubuntu.16.04-x64":
case "debian.8-x64":
case "debian.9-x64":
default:
DLLNAME = "libcrypto.so.1.1";
SSLDLLNAME = "libssl.so.1.1";
break;
}
, but most should Just Work™.

Windows

Create and install a NuGet package from runtime.win.OpenSSL.

Building this package downloads the required DLL files (x86 & x64) from http://wiki.overbyte.eu, who provide signed builds of the latest OpenSSL.

Nuget push pushes the NuGet package to your local cache. This way it can be consumed by any project.

cd deps\NippyWard.OpenSSL.Tasks
dotnet build
cd ..\runtime.win.OpenSSL
dotnet build
dotnet pack
dotnet nuget push bin\Debug\runtime.win.OpenSSL.1.1.1n.nupkg -s %USERPROFILE%\.nuget\packages

This nuget package should get auto-referenced when on Windows and referencing NippyWard.OpenSSL. You need to guarantee it's in your cache, because it is not available on NuGet.org.

MacOS

I have no mac.

Usage

See tests for usage examples.

Encryption

byte[] iv = Encoding.ASCII.GetBytes("12345678"); //initialization vector is 8 bytes
byte[] key = Encoding.ASCII.GetBytes("This is the key"); //best practice ia a key of 16 bytes or more

Span<byte> inputSpan; //data to encrypt
Span<byte> outputSpan; //data to decrypt

//initialize an encryption context
using (CipherEncryption cipherEncryption = new CipherEncryption(CipherType.AES_256_CBC, key, iv))
{
    //you can keep updating as long as there is more data to encrypt
    int encryptedLength = cipherEncryption.Update(inputSpan, ref outputSpan);

    //when all data has been encrypted, finalize to encrypt the trailing bytes
    int finalEncryptedLength = cipherEncryption.Finalize(ref outputSpan);
}

Decryption is the same. See TestCipher for further details.

Hashing

Span<byte> inputSpan; //data to hash

//create an SHA156 hash
using (Digest ctx = new Digest(DigestType.SHA256))
{
    //you can keep updating as long as there is more data to hash
    ctx.Update(inputSpan);

    //when all data has been hashed, finalize to hash trailing bytes
    //and receive the hash
    //a hash has a fixed length
    ctx.Finalize(out Span<byte> outputSpan);
}

Keys

Span<byte> unencrypted; //the data to encrypt

//create a 1024 bit RSA key
using (RSAKey key = new RSAKey(1024))
{
    //and encrypt some data using the key
    using (KeyContext keyContext = key.CreateEncryptionContext())
    {
        //get size of encrypted buffer
        encryptedLength = key.EncryptedLength(in keyContext, unencrypted);

        //create buffer to store encrypted data
        Span<byte> encrypted = new Span<byte>(new byte[encryptedLength]);

        //encrypt data
        key.Encrypt(in keyContext, unencrypted, encrypted, out encryptedLength);
    }
}

Decryption is the same. See TestKey for further details.

X509

DateTime start = DateTime.Now;
DateTime end = start + TimeSpan.FromMinutes(10);

//create a key to use in the certificate
using (RSAKey key = new RSAKey(2048))
{
    //create a new certificate
    using (X509Certificate cert = new X509Certificate(key, "localhost", "localhost", start, end))
    {
        //add some extensions concerning certificate usage
        cert.AddX509Extension(X509ExtensionType.BasicConstraints,  "CA:true");
        cert.AddX509Extension(X509ExtensionType.KeyUsage, "cRLSign,keyCertSign");

        //self-sign the certificate and generate a public key
        cert.SelfSign(key, DigestType.SHA256);

        //use the certificate
    }
}

There are also several extension and CA examples in TestX509Certificate.

TLS

The TLS implementation is to be used as an API and should not be consumed directly. See NippyWard.Networking.Tls for an asynchronous client/server implementation of the API.

Packages

No packages published

Languages

  • C# 100.0%