2

My knowledge about SSL is very basic and I need to generate self-signed SSL certificates for a local server [server.local] so I can use it in a mobile app for SSL pinning.

How do I create a self-signed certificate, following the rules established by Apple below, via openssl x509?

  • All TLS server certificates must comply with these new security requirements in iOS 13 and macOS 10.15; connections to TLS servers violating these new requirements will fail and may cause network failures, apps to fail, and websites to not load in Safari:
    • Certificates and issuing CAs using RSA keys must use key sizes ≥2048 bits; RSA key sizes <2048 bits are no longer trusted
    • Certificates, and issuing CAs, must use a hash algorithm from the SHA2 family in the signature algorithm; SHA1 signed certificates are no longer trusted for TLS
    • Certificates must present the DNS name of the server in the SubjectAltName extension of the certificate; DNS names in the CommonName of a certificate are no longer trusted
    • Certificates issued after July 1, 2019, as indicated in the NotBefore field of the certificate, must follow these guidelines:
      • Certificates must contain an extendedKeyUsage (EKU) extension containing the id-kp-serverAuth OID
      • Certificates must have a validity period of ≤825 days, as expressed in the NotBefore and NotAfter fields of the certificate.

I created the certificate via:

openssl genrsa -des3 -out myCA.key 2048

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

After installing it on the server and device, when I try to use this inside iOS, I get error:

SSL hostname does not match name(s) in certificate,
Extended key usage does not match certificate usage, Root is not trusted`
JW0914
  • 7,052
  • 7
  • 27
  • 48
Duck
  • 1,757
  • 2
  • 28
  • 44

1 Answers1

2

Self-signed certificates should never be used, as they have no Chain of Trust and are therefore insecure and pointless; the recommended way is to create a self-signed CA, using that CA to sign the certificate via an openssl.cnf, such as this custom one.

  • The commonName [CN] cannot be an IP or DNS name, since doing so is insecure; I always recommend using the CN to name the cert (e.g. Apache Web Server X, VPN Server 1, etc.)
  • SAN [SubjectAltName] profiles can contain:
    • email: email address
    • URI: Uniform Resource Indicator
    • DNS: DNS domain name [local or FQDN]
    • ID: Registered ID: Object Identifier [OID]
    • IP: IP address
    • dirName: Distinguished Name
    • otherName: OID;content [arbitrary data associated with an OID]
      (Content value is in standard ASN1_generate_nconf format)

Execute all commands from within the directory that will contain openssl.cnf:

  1. Download the custom openssl.cnf: (Linux/Windows)
    # Linux:
      wget https://raw.githubusercontent.com/JW0914/Wikis/master/Scripts%2BConfigs/OpenSSL/Linux/openssl.cnf
    
    # Windows:
      wget https://raw.githubusercontent.com/JW0914/Wikis/master/Scripts%2BConfigs/OpenSSL/openssl.cnf
    

  2. Edit the SAN profiles of the certs to be created: (lines 151 - 244)
    1. CA: Edit line 170 [Router.1] to name your CA
      [ alt_ca_main ]
      DNS.1                 = Router.1
      IP.1                  = 127.0.0.1
      
      • [ alt_ca_main ]
        alt_: specifies a SAN profile
        ca_main: custom name for the SAN profile
        (If renaming: update CA V3 profile line 264 [@alt_ca_main])
      • DNS.1:
        Names the CA to make it easier when managing multiple CAs/ICAs
      • IP.1:
        Some router OSes require the loopback IP to be specified in the master CA
    2. Client/Server Cert: Edit lines 189 - 193
      [ alt_sophos ]
      IP.1                = 192.168.2.1
      IP.2                = 127.0.0.1
      DNS.1               = UTM.WRT
      DNS.2               = your.ddns.com
      
      • [ alt_sophos ]:
        SAN profile name; change sophos only if wishing to rename
        (If renaming: update V3 profile lines 331 [v3_sophos] and 337 [@alt_sophos])
      • IP.1:
        Server IP (if accessible via SSH, loopback IP must be specified [IP.2])
        (list additional IPs on new lines with chronological listings; e.g. IP.3)
      • DNS.1:
        LocalHostname.LocalDomain
      • DNS.2:
        DDNS/FQDN
        (list additional names on new lines with chronological listings; e.g. DNS.3)

  3. Create prerequisite files and directories: (lines 436 - 455)
    mkdir crl; echo 01 > crl\crlnumber; echo > index; echo > rand; echo 00 > serial
    
    • crlnumber:
      serial for the next CRL [Certificate Revocation List] signed (lines 443 - 446)
    • index:
      list of all certs created (lines 448 - 451 and 642 - 686)
      • openssl ca must be used to maintain the index automatically, which I don't cover, as it overcomplicates the process (manually maintain: lines 642 - 686)
    • rand:
      random characters used for certificate/key creation (lines 453 - 455)
    • serial:
      serial [hex] of last cert signed, can be any number (lines 438 - 441 and 671 - 681)

  4. Create CA:
    # CA key should have a secure passphrase of at least 20 characters, containing:
    # 2 uppercase, 2 lowercase, 2 numbers, and 2 symbols
    
      # Request:
        openssl req -x509 -new -sha512 -days 3650 -newkey rsa:4096 -keyout 'CA.key.pem' -out 'CA.crt.pem' -config '.\openssl.cnf' -extensions v3_ca
    
      # Generate CA CRL Cert:
        openssl ca -gencrl -keyfile 'CA.key.pem' -cert 'CA.crt.pem' -out 'CA.crl.pem' -config '.\openssl.cnf'
    
      # Convert CA CRL Cert to DER CRL:
        openssl crl -inform PEM -in '.\CA.crl.pem' -outform DER -out '.\CA.crl'
    
    Most can ignore, as vast majority are fine using RSA:
    Type of key chosen determines the Key Exchange Algorithms that can be used [below]
    • It's imperative the CA V3 profile's KUs are not altered (lines 260 - 265)

  5. (Optional) Create ICA [Intermediate CA]:
    Useful if needing multiple CAs to lower risk of any one being compromised
    # ICA key should have a secure passphrase of at least 20 characters, containing:
    # 2 uppercase, 2 lowercase, 2 numbers, and 2 symbols
    
      # Request:
        openssl req -out '.\ICA.csr' -new -days 3650 -sha512 -newkey rsa:4096 -keyout 'ICA.key.pem' -config '.\openssl.cnf' -extensions v3_ica_router2
    
      # Sign ICA with CA:
        openssl x509 -req -sha512 -days 3650 -in '.\ICA.csr' -CA 'CA.crt.pem' -CAkey 'CA.key.pem' -CAserial '.\serial' -out 'ICA.crt.pem' -extfile '.\openssl.cnf' -extensions v3_ica_router2
    
      # Generate ICA CRL Cert:
        openssl ca -config '.\openssl.cnf' -gencrl -keyfile 'ICA.key.pem' -cert 'ICA.crt.pem' -out '.\ICA.crl.pem'
    
      # Convert ICA CRL Cert to DER CRL:
        openssl crl -inform PEM -in '.\ICA.crl.pem' -outform DER -out '.\ICA.crl'
    
      # Concatenate ICA and CA Cert:
        # Linux:
          cat './ICA.crt.pem' './CA.crt.pem' > './CA-ICA-Chain.crt.pem'
    
        # Windows:
          cmd /c type '.\ICA.crt.pem' '.\CA.crt.pem' > '.\CA-ICA-Chain.crt.pem'
    
    Most can ignore, as vast majority are fine using RSA:
    Type of key chosen determines the Key Exchange Algorithms that can be used [below]
    • It's imperative the ICA V3 profiles' KUs are not altered (lines 267 - 279)
    • ICA V3 profiles contian pathlen:0 (they can sign certs, but not CAs/ICAs); if pathlen is not specified/number set, it can sign an infinite/specified number of CAs/ICAs

  6. Create certificates: (if V3 profile was renamed in 2.2, update here)
    # Server certs: add -nodes to the end of the Request command; else server requires
    # manually entering encryption passphrase when starting (impractical)
    
      # Request:
        openssl req -out '.\server.csr' -new -days 825 -sha512 -newkey rsa:2048 -keyout '.\server.key.pem' -config '.\openssl.cnf' -extensions v3_sophos -nodes
    
      # Sign:
        # CA only:
          openssl x509 -req -sha512 -days 825 -in '.\server.csr' -CA '.\CA.crt.pem' -CAkey '.\CA.key.pem' -CAserial '.\serial' -out '.\server.crt.pem' -extfile '.\openssl.cnf' -extensions v3_sophos
    
        # ICA: (change to)
          -CA '.\CA-ICA-Chain.crt.pem' -CAkey '.\ICA.key.pem'
    
      # (Optional) Export:
        # CA only:
          openssl pkcs12 -export -out '.\server.p12' -inkey '.\server.key.pem' -in '.\server.crt.pem' -certfile 'CA.crt.pem'
    
        # ICA: (change to)
          -certfile 'CA-ICA-Chain.crt.pem'
          # CA - ICA chain cert must be exported to maintain the Chain of Trust of: Cert → ICA → CA
    
    Most can ignore, as vast majority are fine using RSA:
    Type of key chosen determines the Key Exchange Algorithms that can be used [below]




References:



Certificate Verification:

  • Certificate:
    openssl x509 -text -noout -in 'cert.crt.pem'
    
  • Certificate Signing Request [CSR]:
    openssl req -text -noout -verify -in 'cert.csr'
    
  • Key:
    openssl rsa -check -in 'cert.key.pem'
    
  • PKCS12 [.pfx/.p12]:
    openssl pkcs12 -info -in 'cert.p12'
    


Hex ⟷ Dec Conversion:

  • Linux:
    # hex → dec: (returns 10)
      printf '%d\n' 0x0a
    
    # dec → hex: (returns 0a)
      printf '%x\n' 10
    
  • Windows:
    Calculator has programmer mode


index:

  • # Manually maintain the index file by inputting one cert entry per line in the following format:
    
    # 1   2----------->   3->   4>  5----->   6---------------------------------------------------------------------------->
      V   261231235959Z         0a  unknown   /C=US/ST=State/L=Locality/O=Org/OU=Unit/CN=Common Name/[email protected]
    
    
      # 1 Status of Certificate:
          V                # Valid
          R                # Revoked
          E                # Expired
    
      # 2 Expiration Date:
          YYMMDDHHMMSSZ    # Date format followed by 'Z' (2026.12.31 @ 23:59:59)
    
      # 3 Revocation Date: (empty if not revoked)
          YYMMDDHHMMSSZ,reason
          # Valid reasons are:
            ## keyCompromise
            ## CACompromise
            ## affiliationChanged
            ## superseded
            ## cessationOfOperation
            ## certificateHold
            ## privilegeWithdrawn
            ## AACompromise
          # Certain distros error out without a whitespace for 3
    
      # 4 Serial number in hex format:
          0a               # hex for 10
    
      # 5 Certificate Filename or Literal String
          unknown          # Certificate filename or literal string 'unknown'
    
      # 6 Distinguished Name
    


Key Exchange Algorithms:

  • RSA:
    Encrypts a random value, chosen by the client, via the server public key
    • Required:
      Server public key must be an RSA key
      Server certificate must have KU keyAgreement

  • DH_RSA:
    Key exchange occurs via a static Diffie-Hellman key
    • Required:
      CA must be using an RSA signing key
      Server public key must be a Diffie-Hellman key
      Diffie-Hellman key must have been issued by a CA

  • DH_DSA:
    Like DH_RSA, except the CA used a DSA key in lieu of RSA

  • DHE_RSA:
    Key exchange occurs via an Ephemeral Diffie-Hellman
    • Server dynamically generates & signs a DH public key, sending it to the client
    • Required:
      Server public key must be an RSA key
      Server certificate must have KU digitalSignature

  • DHE_DSA:
    Like DHE_RSA, except the CA used a DSA key in lieu of RSA


Elliptic-Curve Key Exchange Algorithms:

  • ECDH_RSA:
    Like DH_RSA, but with elliptic-curves
    • Required:
      Server public key must be an ECDH key
      Server certificate must be issued by a CA using an RSA public key

  • ECDH_ECDSA:
    Like ECDH_RSA, except the CA used an ECDSA key

  • ECDHE_RSA: Server sends dynamically generated EC Diffie-Hellman key, signing it via it's RSA key
    • Server public key signs the Ephemeral EC Diffie-Hellman key

  • ECDHE_ECDSA:
    Like ECDHE_RSA, except server public key is an ECDSA key
    • Equivalent to DHE_DSS, but with elliptic curves for both the Diffie-Hellman & signature


KUs & EKUs:


Man Pages:

JW0914
  • 7,052
  • 7
  • 27
  • 48
  • “Self-signed certificates should never be used, as they have no Chain of Trust and are therefore insecure and pointless” – This is simply not correct. There is no difference in security or trust whatsoever. Especially considering how OP wants to use this certificate with pinning. – Daniel B Jan 16 '21 at 17:27
  • @DanielB It only leaves the user wide open to a MITM attack... _If it's worth doing, it worth doing right the first time._ I know very little about SSL Pinning, but [this](https://www.thesslstore.com/blog/an-introduction-to-pinning/) article does a decent job at detailing how a self-signed cert leaves every client at risk of a MITM attack due to the inherent lack of a Chain of Trust. Considering it takes all of ~2min to issue a self-signed CA for signing the server cert, why would anyone logically not do so? The goal is to increase security, not open ourselves up to be exploited by a MITM. – JW0914 Jan 16 '21 at 17:56
  • Except it doesn’t. Trust is all the same, whether it’s chained from a CA or directly applied to a specific certificate. A full PKI offers some benefits, especially with replacing certificates, but it doesn’t offer any improvement regarding trust or MITM. – Daniel B Jan 16 '21 at 21:31
  • @DanielB would you please provide a more in-depth explanation, or link to a reference that offers a more in-depth explanation, as I couldn't find any search result that recommended a self-signed cert for SSL pinning? Also, from the error the OP received [`Root is not trusted`], if using a self-signed cert it would need to be installed as a Root CA to comply, which isn't recommended in general and implies improper Chain of Trust. – JW0914 Jan 20 '21 at 12:35
  • A self-signed certificate does not offer advantages. It is merely equivalent. I don’t have any reference on that. OP is actually receiving three error messages, one of which is the one you quote. // Again: Using self-signed certificates or CAs does not imply a trust issue. You just need to make sure you trust the right thing. Using established trusted channels to distribute certificates is advisable. – Daniel B Jan 20 '21 at 13:44
  • @DanielB I understand the point you're making [at the certificate level, a self-signed cert and one signed by a CA are equivalent], however the Chain of Trust is _not_, which is why commercial CAs exist and why self-signed certs aren't generally recommended. By using a self-signed cert, there's no way to ensure it hasn't been maliciously replaced by a MITM if the key hasn't been encrypted. I simply don't understand why anyone would not take the few minutes extra _(literally ~2m to edit the `openssl.cnf` and paste commands)_ to create a self-signed CA and use it to sign a cert. – JW0914 Jan 21 '21 at 05:43