- 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;
- 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("public.pem").read);
auto encrypted = public.encrypt(cast(ubyte[])"Hello, how are you today?");
auto pemData = public.pemFormat;
- this(char[] publicPemData);
- Generate a PublicKey object from the passed PEM formatted data
Params:
char[] publicPemData |
pem encoded data containing the public key |
- char[] pemFormat();
- Return a PublicKey in the PEM format.
- bool verify(ubyte[] data, ubyte[] signature);
- Verify the data passed was signed with the public key.
Params:
ubyte[] data |
the data to verify |
ubyte[] signature |
the digital signature |
- ubyte[] encrypt(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:
ubyte[] data |
the data to encrypt |
- ubyte[] decrypt(ubyte[] data);
- Decrypts data previously encrypted with the matching PrivateKey
Please see the encrypt notes.
Params:
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(char[] privatePemData, char[] certPass = null);
- Reads in the provided PEM data, with an optional password to decrypt
the private key.
Params:
char[] privatePemData |
the PEM encoded data of the private key |
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.
- char[] pemFormat(char[] pass = null);
- Returns the underlying public/private key pair in PEM format.
Params:
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(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:
ubyte[] data |
the data to encrypt |
- ubyte[] decrypt(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(char[] 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.
- char[] pemFormat();
- Returns the Certificate in a PEM encoded string.