Search code examples
spring-bootssl-certificatekeytool

Spring Boot SSL webapp iOS testing


I'm experimenting with Spring Boot to create a WebApp.

In order to create a SSL certificate I issue the following command:

keytool -alias devssl -keystore devssl.p12 -genkeypair -keyalg RSA -sigalg SHA256withRSA /
-keysize 2048 -storetype PKCS12 -validity 365 -dname "CN=Frankie, OU=Frankie O=Frankie, /
L=City, S=State, C=UK" -ext SAN=DNS:localhost,DNS:blueye,IP:127.0.0.1,IP:10.1.1.2"

Which from what I can understand means that such certificate will be valid for the following addresses:

  • localhost
  • blueye
  • 127.0.0.1
  • 10.1.1.2

The certificate is very easy to install on Spring:

server.ssl.key-store-type=PKCS12
server.ssl.key-store=devssl.p12
server.ssl.key-store-password=password
server.ssl.key-alias=devssl
security.require-ssl=true

After I install the certificate under Trusted Root Certification Authorities in Windows it also works great.

I just can't get it to work under iOS.

I email myself the certificate.
Install it on the iPhone.
But I always get the "this connection is not private".

enter image description here

Any idea how to make this work on iOS?


Solution

  • I was pushing on this trying to get iOS to accept a self-signed certificate as the single source of truth. I got to work around it by issuing a proper personal Certificate Authority. Making iOS trust that authority. And then signing the website with a certificate validated by that authority.

    I will describe the needed commands as they may save someone a couple of hours. The following is a "birds eye" of what we'll do.

    AUTHORITY - this will act as the source of trust for all certificates you sign. You will have to install the Authority on every single machine/phone you'll want with custom certificates

    1. Generate a private key for a Certificate Authority (CA)
    2. Generate a Certificate for the Certificate Authority (CA)
    3. Install Certificate Authority on Windows
    4. Install Certificate Authority on iOS

    CLIENT - we can issue private keys for all our projects inside our network. Those private keys will be validated by our own generated and installed authority.

    1. Generate a private key for the client
    2. Generate a Certificate Sign Request (CSR)
    3. Have CA sign the CSR thus generating the client Certificate
    4. Merge the client certificate and the CA certificate into a pkcs12 file which is read by Spring

    Now for the actual commands:

    Generate a private key, we'll also use an identical command to generate one for the client:

    openssl genrsa -des3 -out myCA.key 2048
    

    Generate a certificate for your Certificate Authority. You'll be asked several questions, none of them really matter, they will only serve to identify your certificate to yourself.

    openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem
    openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.crt
    

    You now have three files. The myCA.key (private key) and the myCA.pem and myCA.crt which are the certificate file for your certificate authority.

    Install on Windows: Click the myCA.crt file on Windows and follow screen instructions. Then click Start -> Run -> `` certmgr.msc`. It will open the Windows Certificate Manager. You will find the certificate you installed under "Intermediate Certification Authorities". You'll want to drag that file to "Trusted Root Certification Authorities".

    Install on iOS: Email the myCA.pem file to yourself. Open the email on iOS using the Apple Mail App. Follow the instructions and certificate will be installed. To uninstall you can go to Settings -> General -> Profile. After proper installation iOS requires a second step for you to trust the certificate, you must go to Settings -> General -> About -> Certificate Trust Settings and Enable Full Trust For Root Certificate.


    You now have a local CA (Certificate Authority) installed on both your Windows machine and your iOS phone. Lets create a website certificate.


    Generate a private key for the website.

    openssl genrsa -des3 -out myWebsite.key 2048
    

    Generate a CSR (Certificate Sign Request):

    openssl req -new -key myWebSite.key -out myWebsite.csr
    

    Now that we have the website key and the certificate sign request we need to create a config file that openssl will use to generate our website certificate. Create a file called myWebsite.ext with the following info. The only thing you must make sure is the alt names. You can have both IP's and DNS. Be sure to enter all the alternatives that your site will use.

    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = localhost
    DNS.2 = mywebsite
    DNS.3 = mywebsite.local
    IP.1 = 10.1.1.3
    IP.2 = 127.0.0.1
    

    Now we'll use the CA certificate and private key together with the CSR (Certificate Sign Request) and the config file to generate a proper certificate for the website. Since iOS 13 Apple only allows a max of 825 days on certificates so that's what we'll use.

    openssl x509 -req -in myWebsite.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out myWebsite.crt -days 825 -sha256 -extfile myWebsite.ext
    

    You'll now have the following files:

    myCA.key      - certificate authority private key  
    myCA.pem      - certificate authority certificate pem format
    myCA.crt      - certificate authority certificate crt format
    myWebsite.key - website private key  
    myWebsite.csr - website certificate sign request  
    myWebsite.ext - website config file for openssl sign request  
    myWebsite.crt - website certificate crt format
    

    The only thing missing is to convert the myWebsite.crt to p12 format which we can do with the following command:

    openssl pkcs12 -export -in myCA.crt -inkey myCA.key -in myWebsite.crt -inkey myWebsite.key -name myWebsite -out myWebsite.p12
    

    Now, to make Spring Boot use this certificate just open application.properties file and make sure it has these lines:

    server.ssl.key-store-type=PKCS12
    # The path to the keystore containing the certificate, place it src/main/resources
    server.ssl.key-store=classpath:myWebsite.p12
    # The password used to generate the certificate
    server.ssl.key-store-password=PASSWORD-USED
    # The alias mapped to the certificate (the -name myWebsite on the last command)
    server.ssl.key-alias=myWebsite 
    # force SSL 
    security.require-ssl=true
    

    And there you have it. A dev or internal project with proper SSL validation. Hope this saves someone some time.