title: One self-signed cert to rule them all? Chrome, Android, and iOS
body: <p>Yet another self-signed cert question, but I've tried for several days to find the best/correct way to create a self-signed cert that will work in my development environment for the latest versions of Chrome, Android, and iOS.</p>
  
  <p>The instructions I've found here and elsewhere are outdated for at least one of these platforms.</p>
  
  <p>Here is the best I've found, but it only works with Chrome and Android.</p>
  
  <pre><code>openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/C=US/ST=Oklahoma/L=Stillwater/O=My Company/OU=Engineering" -keyout ca.key -out ca.crt
  openssl genrsa -out "test.key" 2048
  openssl req -new -key test.key -out test.csr -config openssl.cnf
  openssl x509 -req -days 3650 -in test.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extensions v3_req -extfile openssl.cnf -out test.crt
  openssl x509 -inform PEM -outform DER -in test.crt -out test.der.crt
  </code></pre>
  
  <p>Contents of openssl.cnf:</p>
  
  <pre><code>[req]
  default_bits = 2048
  encrypt_key  = no # Change to encrypt the private key using des3 or similar
  default_md   = sha256
  prompt       = no
  utf8         = yes
  
  # Specify the DN here so we aren't prompted (along with prompt = no above).
  
  distinguished_name = req_distinguished_name
  
  # Extensions for SAN IP and SAN DNS
  
  req_extensions = v3_req
  
  # Be sure to update the subject to match your organization.
  
  [req_distinguished_name]
  C  = US
  ST = Oklahoma
  L  = Stillwater
  O  = My Company
  OU = Engineering
  CN = test.com
  
  # Allow client and server auth. You may want to only allow server auth.
  # Link to SAN names.
  
  [v3_req]
  basicConstraints     = CA:TRUE
  subjectKeyIdentifier = hash
  keyUsage             = digitalSignature, keyEncipherment
  extendedKeyUsage     = clientAuth, serverAuth
  subjectAltName       = @alt_names
  
  # Alternative names are specified as IP.# and DNS.# for IP addresses and
  # DNS accordingly.
  
  [alt_names]
  DNS.1 = test.com
  </code></pre>
  
  <p>After installing test.crt and test.key on my development server, this method works great for Chrome: just added test.crt to my Mac's keychain and turned on "Always Trust" for it.</p>
  
  <p>It also works great for Android: emailed test.der.crt to the device and tapped it to install. Most important: it showed up in the "USER" tab under Settings / Encryption &amp; credentials / Trusted credentials. This is essential for using <a href="https://developer.android.com/training/articles/security-config" rel="noreferrer">networkSecurityConfig</a> in my Android app.</p>
  
  <p>Unfortunately it didn't work for iOS:</p>
  
  <ul>
  <li>I installed it in an Xcode simulator by dragging the certificates to it.</li>
  <li>I had to install both test.crt and ca.crt. If I just installed test.crt, it remained in "unverified" status, which makes sense since the ca.crt is the root certificate.</li>
  <li>It did not show up under Settings / About / Certificate Trust Settings which is required for me to turn it on.</li>
  <li>When my app tries to access my server with NSMutableURLRequest, it gets a  "TIC SSL Trust Error" with 10 key-value pairs, including:
  
  <ul>
  <li>NSURLErrorFailingURLPeerTrustErrorKey=</li>
  <li>_kCFStreamErrorDomainKey=3</li>
  <li>_kCFStreamErrorCodeKey=-9813</li>
  <li>NSErrorPeerCertificateChainKey=1 element, and NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “test.com” which could put your confidential information at risk.</li>
  </ul></li>
  </ul>
  
  <p>Any idea how to change what I did so I can turn it on for iOS under "Certificate Trust Settings"?</p>
  
  <p>Note 1: Since other answers to other questions about the -9813 error code suggested there may be a missing intermediate certificate, I added ca.crt to my Apache configuration for the SSLCaCertificateFile setting. It still worked fine for Chrome and Android, but had exactly the same error in iOS.</p>
  
  <p>Thanks!</p>