6

Does anyone know how to create a self-signed SSL certificate for use with IIS (7) that has subject alternative names (SAN)s? I need the certificate to be able to validate the hostname AND the IP address like this:

  • CN=MyServerName
  • IP SAN: 192.168.2.2

Some things i've been looking at:

  • Windows SDK: makecert.exe (doesn't support SANs)

  • Windows API CertEnroll (Server 2008): using PowerShell script (I've been able to get this to work with IIS, however when I export the certificate into a Java keystore (must have) I get an error keytool error: 'java.lang.Exception: Input not an X.509 certificate’)

Here's an example of a PowerShell script using CertEnroll: http://blogs.technet.com/b/vishalagarwal/archive/2009/08/22/generating-a-certificate-self-signed-using-powershell-and-certenroll-interfaces.aspx

  • OpenSSL: I haven't looked into this yet...

It would be great if I can get my PowerShell script to create a certificate that Java recognizes using the CertEnroll API, but anything that works at this point i'll be happy hearing about.

4 Answers 4

8

I found a way to do this using OpenSSL. I was hoping to use CertEnroll but since it gave me interoperability problems with Java I'm just going to use OpenSSL.

Here is how I created a cert for IIS with subject alternative names using OpenSSL.

First create a OpenSSL config text file:

[req]
distinguished_name  = req_distinguished_name
x509_extensions     = v3_req
prompt              = no
[req_distinguished_name]
C           = US
ST          = VA
L           = SomeCity
O           = MyCompany
OU          = MyDivision
CN          = ANDY
[v3_req] 
keyUsage           = keyEncipherment, dataEncipherment
extendedKeyUsage   = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = andy
DNS.2 = 192.168.2.12
IP.1 = 192.168.2.12
IP.2 = 192.167.20.1

Then run the following OpenSSL commands:

openssl.exe req -x509 -nodes -days 730 -newkey rsa:2048 -keyout C:\cert.pem -out C:\cert.pem -config C:\PathToConfigFileAbove.txt

openssl.exe pkcs12 -export -out C:\cert.pfx -in C:\cert.pem -name "My Cert" -passout pass:mypassword

This will create you a cert in a PFX file which can be imported to IIS. I automated this with powershell like so:

    # Get the certificate from the PFX file.
$pfxcert = new-object system.security.cryptography.x509certificates.x509certificate2
$pfxcert.Import(
    "C:\cert.pfx",
    "mypassword",
    [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet -bor `
    [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
)

    # Add the certificate to the windows stores.
Get-Item -Path cert:\LocalMachine\My, cert:\LocalMachine\root | ForEach-Object {
    $store = $_
    $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
    $store.Add($pfxcert)
    $store.Close()
}

Add-PSSnapin -Name WebAdministration # IIS 7 Powershell module.
Push-Location -Path IIS:\SslBindings

    # Create new IIS SSL bindings.
Get-Item -Path "cert:\LocalMachine\My\$($pfxcert.Thumbprint)" | New-Item "0.0.0.0!443"
4
  • I misunderstood; I thought your issue was in getting the certificate to import to a java key store? That's what my answer covers. Aug 17, 2011 at 0:37
  • Yes that was part of it. I have no idea why Java didn't like the certificates created with the CertEnroll API but had no issue with the cert created with makecert.exe which uses the same API. Ultimately I needed a way to create a self-signed cert with SANs using any tool and also be able to import that certificate (with no private key) into a Java keystore (for Tomcat). Aug 17, 2011 at 4:52
  • By the way this method works if you need to create a Tomcat public/private keypair as well. The PFX created by OpenSSL can be imported into a JKS for use with Tomcat with this command: Aug 17, 2011 at 15:40
  • keytool.exe -importkeystore -srckeystore C:\cert.pfx -srcstoretype PKCS12 -destkeystore C:\andy.jks -srcstorepass mypassword -deststorepass changeit . Aug 17, 2011 at 15:58
1

The java key tool is picky about what it'll allow to import. The certificate that you've built via powershell should work, though, with a little massaging.

What format is the certificate in now? If you've done an export from a windows certificate store, it's probably .pfx; you'll want to convert to a PEM-encoded x509 certificate:

openssl pkcs12 -in /path/to/certbundle.pfx -out /public/key/path/certificate.crt -nokeys
openssl pkcs12 -in /path/to/certbundle.pfx -out /private/key/path/certificate.key -nocerts -nodes

From there, you'll want to check the actual contents of the file - these Windows certificates include a "Bag Attributes" section above the -----BEGIN CERTIFICATE----- section, which the keytool parser likes to choke on - feel free to strip that out so that the files look just like this, with no other content:

/public/key/path/certificate.crt

-----BEGIN CERTIFICATE-----
MIIAAAA........
-----END CERTIFICATE-----

/private/key/path/certificate.key

-----BEGIN RSA PRIVATE KEY-----
MIIAAAA........
-----END RSA PRIVATE KEY-----

These certificate files should be a lot more amenable to import by the java keytool.

1
  • When I export the cert create with the CertEnroll API via my script I've tried exporting both as DER and Base64. Keytool doesn't import either. When I use the export wizard in the Windows store I select not to export the private key. The base64 export has the BEGIN/END headers, the DER export is a binary file. Aug 16, 2011 at 23:26
1

I thought SAN wasn't supported using makecert either, but then I found this blog

It seems that you can get similar functionality to using SAN by using multiple common names. e.g. makecert -n "CN=CertName;CN=pseudoSAN"

or in your example "CN=Andy;CN=192.168.2.12"

0

Update for 2021.

This can now be done using a single command line, for example:

openssl req -new -x509 -nodes -sha256 -days 365 -subj "/C=GB/CN=blah" -addext  "subjectAltName = DNS:example.net,DNS:*.example.net,IP:192.168.2.12" -newkey rsa:2048 -keyout key.pem -out req.pem

Source: openssl req man page

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.