tango.net.util.PKI

License:
BSD style:

author:
Jeff Davey

const int SSL_VERIFY_NONE;
PKI provides Public Key Infrastructure.

Specifically, it provides the ability to:

- Make a X509 Certificate (SSL Certificate)

- Make a Public and Private key pair

- Validate a X509 Certificate against a Certificate Authority

- Generate a SSLCtx for SSLSocket and SSLServerSocket

- Wrap a SSLVerifyCallback so that retrieving the peer cert is easier

PKI requires the OpenSSL library, and uses a dynamic binding to the library. You can find the library at http://www.openssl.org and a Win32 specific port at http://www.slproweb.com/products/Win32OpenSSL.html.





Do not verify the peer certificate. Nor fail if it's not provided (server only).

const int SSL_VERIFY_PEER;
Ask for a peer certificate, but do not fail if it is not provided.

const int SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
Ask for a peer certificate, however, fail if it is not provided

const int SSL_VERIFY_CLIENT_ONCE;
Only validate once, do not re-validate during handshake renegotiation.

alias SSLVerifyCallback = extern (C) int function(int, X509_STORE_CTX* ctx);
SSLVerifyCallback is passed into SSLCtx and is called during handshake when OpenSSL is doing certificate validation.

Wrapping the X509_STORE_CTX in the CertificateStoreCtx utility class gives the ability to access the peer certificate, and reason for error.

class SSLCtx;
SSLCtx is provided to SSLSocket and SSLServerSocket.

It contains the public/private keypair, and some additional options that control how the SSL streams work.

Example
auto cert = new Certificate(cast(char[])File("public.pem").read);
auto pkey = new PrivateKey(cast(char[])File("private.pem").read);;
auto ctx = new SSLCtx();
ctx.certificate = cert;
ctx.pkey = pkey;
ctx.checkKey();


this();
Creates a new SSLCtx supporting SSLv3 and TLSv1 methods.

@property SSL_CTX* native();
Return the native context from OpenSSL

SSLCtx certificate(Certificate cert);
Assigns a X509 Certificate to the SSLCtx.

This is required for SSL

SSLCtx privateKey(PrivateKey key);
Assigns a PrivateKey (public/private keypair to the SSLCtx.

This is required for SSL.

@property SSLCtx checkKey();
Validates that the X509 certificate was signed with the provided public/private keypair. Throws an exception if this is not the case.

SSLCtx setVerification(int flags, SSLVerifyCallback cb);
Sets a SSLVerifyCallback function using the SSL_VERIFY_(NONE|PEER|etc) flags to control how verification is handled.

SSLCtx store(CertificateStore store);
Sets a CertificateStore of certs that are valid and trust Certificate Authorities during verification.

SSLCtx caCertsPath(const(char)[] path);
Loads valid Certificate Authorities from the specified path.

From the SSL_CTX_load_verify_locations manpage:

Each file must contain only one CA certificate. Also, the files are looked up by the CA subject name hash value, which must be available. If more than one CA certificate with the same name hash value exists, the extension must be different. (ie: 9d66eef0.0, 9d66eef0.1, etc). The search is performed in the ordering of the extension, regardless of other properties of the certificates. Use the c_rehash utility to create the necessary symlinks

class CertificateStoreCtx;
The CertificateStoreCtx is a wrapper to the SSLVerifyCallback X509_STORE_CTX parameter.

It allows retrieving the peer certificate, and examining any errors during validation.



The following example will probably change sometime soon.

Example
extern (C)
{
    int myCallback(int code, X509_STORE_CTX *ctx)
    {
        auto myCtx = new CertificateStoreCtx(ctx);
        Certificate cert = myCtx.cert;
        Stdout(cert.subject).newline;
        return 0; // BAD CERT! (1 is good)
    }
}


this(X509_STORE_CTX* ctx);
This constructor takes a X509_STORE_CTX as provided by the SSLVerifyCallback function.

Certificate cert();
Returns the peer certificate.

class CertificateStore;
CertificateStore stores numerous X509 Certificates for use in CRL lists, CA lists, etc.

Example
auto store = new CertificateStore();
auto caCert = new Certificate(cast(char[])File("cacert.pem").read);
store.add(caCert);
auto untrustedCert = new Certificate(cast(char[])File("cert.pem").read);
if (untrustedCert.verify(store))
    Stdout("The untrusted cert was signed by our caCert and is valid.").newline;
else
    Stdout("The untrusted cert was expired, or not signed by the caCert").newline;


CertificateStore add(Certificate cert);
Add a Certificate to the store.

class PublicKey;
PublicKey contains the RSA public key from a private/public keypair.

It also allows extraction of the public key from a keypair.

This is useful for encryption, you can encrypt data with someone's public key and they can decrypt it with their private key.

Example
auto public = new PublicKey(cast(char[])File.get("public.pem"));
auto encrypted = public.encrypt(cast(ubyte[])"Hello, how are you today?");
auto pemData = public.pemFormat;


this(const(char)[] publicPemData);
Generate a PublicKey object from the passed PEM formatted data

Params:
const(char)[] publicPemData pem encoded data containing the public key

string pemFormat();
Return a PublicKey in the PEM format.

bool verify(const(ubyte)[] data, const(ubyte)[] signature);
Verify the data passed was signed with the public key.

Params:
const(ubyte)[] data the data to verify
const(ubyte)[] signature the digital signature

ubyte[] encrypt(const(ubyte)[] data);
Encrypt the passed data using the PublicKey

Notes:
This is size limited based off the key Not recommended for general encryption, use RSA for encrypting a random key instead and switch to a block cipher.

Params:
const(ubyte)[] data the data to encrypt

ubyte[] decrypt(const(ubyte)[] data);
Decrypts data previously encrypted with the matching PrivateKey

Please see the encrypt notes.

Params:
const(ubyte)[] data the data to encrypt

class PrivateKey;
Generates a RSA public/private key pair for use with X509 Certificates and other applications search as S/MIME, DomainKeys, etc.

Example
auto newPkey = new PrivateKey(2048); // create new keypair
Stdout(newPkey.pemFormat("password")); // dumps in pemFormat with encryption
Stdout(newPkey.pemFormat()); // dumps in pemFormat without encryption
Stdout(newPkey.publicKey.pemFormat); // dump out just the public key portion
auto data = newPkey.decrypt(someData); // decrypt data encrypted with public Key


this(const(char)[] privatePemData, const(char)[] certPass = null);
Reads in the provided PEM data, with an optional password to decrypt the private key.

Params:
const(char)[] privatePemData the PEM encoded data of the private key
const(char)[] certPass an optional password to decrypt the key.

this(int bits);
Generates a new private/public key at the specified bit leve.

Params:
int bits Number of bits to use, 2048 is a good number for this.

bool opEquals(Object obj);
Compares two PrivateKey classes to see if the internal structures are the same.

string pemFormat(const(char)[] pass = null);
Returns the underlying public/private key pair in PEM format.

Params:
const(char)[] pass If this is provided, the private key will be encrypted using AES 256bit encryption, with this as the key.

PublicKey publicKey();
Returns the underlying PublicKey

ubyte[] sign(const(ubyte)[] data, ubyte[] sigbuf);
Sign the given data with the private key

Params:
const(ubyte)[] data the data to sign
ubyte[] sigbuf the buffer to store the signature in

Returns a slice of the signature or null

ubyte[] encrypt(const(ubyte)[] data);
Encrypt the passed data using the PrivateKey

Notes:
This is size limited based off the key Not recommended for general encryption, use RSA for encrypting a random key instead and switch to a block cipher.

Params:
const(ubyte)[] data the data to encrypt

ubyte[] decrypt(const(ubyte)[] data);
Decrypts data previously encrypted with the matching PublicKey

Please see the encrypt notes.

Parmas:
data = the data to encrypt

class Certificate;
Certificate provides necessary functionality to create and read X509 Certificates.

Note, once a Certificate has been signed, it is immutable, and cannot be modified.

X509 Certificates are sometimes called SSL Certificates.

Example
auto newPkey = new PrivateKey(2048); // create new keypair
auto cert = new Certificate();
cert.privateKey = newPkey;
cert.serialNumber = 1;
cert.dateBeforeOffset = TimeSpan.zero;
cert.dateAfterOffset = TimeSpan.days(365); // cert is valid for one year
cert.setSubject("US", "State", "City", "Organization", "CN", "Organizational Unit", "Email");
cert.sign(cert, newPkey); // self signed cert
Stdout(newPkey.pemFormat).newline;
Stdout(cert.pemFormat).newline;


this(const(ubyte)[] publicPemData);
Parses a X509 Certificate from the provided PEM encoded data.

this();
Creates a new and un-signed (empty) X509 certificate. Useful for generating X509 certificates programatically.

Certificate serialNumber(uint serial);
Sets the serial number of the new unsigned certificate.

Note, this serial number should be unique for all certificates signed by the provided certificate authority. Having two Certificates with the same serial number can cause problems with web browsers and other apps because they will be different certificates.

uint serialNumber();
Returns the serial number of the Certificate

Certificate dateBeforeOffset(TimeSpan t);
If the current date is "before" the date set here, the certificate will be invalid.

Params:
TimeSpan t A TimeSpan representing the earliest time the Certificate will be valid

Example:
cert.dateBeforeOffset = TimeSpan.seconds(-86400); // Certificate is invalid before yesterday

Certificate dateAfterOffset(TimeSpan t);
If the current date is "after" the date set here, the certificate will be invalid.

Params:
TimeSpan t A TimeSpan representing the amount of time from now that the Certificate will be valid. This must be larger than dateBefore

Example:
cert.dateAfterOffset = TimeSpan.seconds(86400 * 365); // Certificate is valid up to one year from now

char[] dateAfter();
Returns the dateAfter field of the certificate in ASN1_GENERALIZEDTIME.

Note, this will eventually befome a DateTime struct.

char[] dateBefore();
Returns the dateBefore field of the certificate in ASN1_GENERALIZEDTIME.

Note, this will eventually befome a DateTime struct.

Certificate privateKey(PrivateKey key);
Sets the public/private keypair of an unsigned certificate.

Certificate setSubject(const(char)[] country, const(char)[] stateProvince, const(char)[] city, const(char)[] organization, const(char)[] cn, const(char)[] organizationalUnit = null, const(char)[] email = null);
Sets the subject (who this certificate is for) of an unsigned certificate.

The country code must be a valid two-letter country code (ie: CA, US, etc)

Params:
const(char)[] country the two letter country code of the subject
const(char)[] stateProvince the state or province of the subject
const(char)[] city the city the subject belong to
const(char)[] organization the organization the subject belongs to
const(char)[] cn the cn of the subject. For websites, this should be the website url or a wildcard version of it (ie: *.dsource.org)
organizationUnit the optional orgnizationalUnit of the subject
const(char)[] email the optional email address of the subject

char[] subject();
Returns the Certificate subject in a multi-line string.

Certificate sign(Certificate caCert, PrivateKey caKey);
Signs the unsigned Certificate with the specified CA X509 Certificate and it's corresponding public/private keypair.

Once the Certificate is signed, it can no longer be modified.

bool opEquals(Object obj);
Checks if the underlying data structur of the Certificate is equal

bool verify(CertificateStore store);
Verifies that the Certificate was signed and issues by a CACert in the passed CertificateStore.

This will also verify the dateBefore and dateAfter fields to see if the current date falls between them.

string pemFormat();
Returns the Certificate in a PEM encoded string.


Page generated by Ddoc. Copyright (c) 2008 Jeff Davey. All rights reserved