1

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,865
Duck
  • 1,767

1 Answers1

4

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' &gt; './CA-ICA-Chain.crt.pem'
    
    # Windows:
      cmd /c type '.\ICA.crt.pem' '.\CA.crt.pem' &gt; '.\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'
    
    

    Chain of Trust: Concatenate CA or ICA and CA to Cert:

    # For ICA, change CA.crt.pem to CA-ICA-Chain.crt.pem
    
    # Linux:
      cat './CA.crt.pem' &gt;&gt; './server.crt.pem'
    
    # Windows:
      cmd /c type './CA.crt.pem' &gt;&gt; './server.crt.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/emailaddress=e@mail.com

    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:


openssl.cnf

While my GitHub will always maintain the customized openssl.cnf linked to throughout, since this answer relies on this, the Linux version is being provided for redundancy:
(Windows version couldn't be included due to the 30K character limit)

#
         ##::[[---  Linux OpenSSL Config  ---]]::##

#==================================================================== ##----- Notes -----## #====================================================================

All commands required can be found beginning on line 430

Windows users, either:

# Change file paths from &quot;/&quot; to &quot;\\&quot;
# Download the Windows openssl.cnf: https://github.com/JW0914/Wikis/blob/master/Scripts+Configs/OpenSSL/openssl.cnf



Sophos users:

# If not using SANs, prior to generating user certs, ensure 'x509_extensions = usr_cert_not_dn'
  # This results with 'RFC822 Name = user@email.com' in the SubjectAlternativeName of the certificate.
    # Without this, it will be impossible to authenticate to VPNs on Sophos.

# Intermediate CAs &amp; Intermediate CA client certs CANNOT be utilized on Sophos UTM due to how Sophos authenticates.
  # Only exception is the WebAdmin certificate, which can be signed by a Public ICA authority for a FQDN.
    # For chain of trust to be maintained, CA &amp; ICA must be installed on devices accessing the WebAdmin/User Portal.


#==================================================================== ##----- Establish Build Variables -----## #====================================================================

dir = /etc/ssl cnf = /etc/ssl/openssl.cnf CNF = $dir/openssl.cnf

#==================================================================== ##----- Establish CA Profile and Policy -----## #====================================================================

[ default ] UTM = "Sophos UTM CA" WRT = "Router 2 ICA" VPN = "Router 2 VPN ICA"

[ ca ] default_ca = CA_default

#====================================================================

[ CA_default ] certs = $dir new_certs_dir = $dir

database = $dir/index RANDFILE = $dir/rand serial = $dir/serial

crldir = $dir/crl crlnumber = $crldir/crlnumber crl = $crldir/ca.crl.pem default_crl_days = 3650

certificate = "$dir/ca/$UTM.crt.pem" private_key = "$dir/ca/$UTM.key.pem"

default_days = 3650 preserve = no default_md = sha512

x509_extensions = usr_cert_not_dn copy_extensions = copy unique_subject = yes

policy = policy_match name_opt = esc_2253,esc_ctrl,esc_msb,sep_comma_plus_space,ignore_type cert_opt = ca_default

#====================================================================

[ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = match commonName = supplied emailAddress = optional

[ policy_supply ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = match commonName = optional emailAddress = optional

#==================================================================== ##----- Establish Certificate Options -----# #--------------------------------------------------------------------

# x64 machines always process SHA512 faster than SHA256.

# 'encrypt_key = yes' is not currently commented out.
  # When creating a key for a server, add '-nodes' to the Request command.


[ req ] default_bits = 2048 default_keyfile = private.key.pem

preserve = no default_md = sha512

string_mask = utf8only utf8 = yes distinguished_name = req_distinguished_name attributes = req_attributes req_extensions = v3_req x509_extensions = v3_ca copy_extensions = copy encrypt_key = yes

[ req_attributes ] challengePassword = challengePassword_min = 12 challengePassword_max = 40

#====================================================================

[ req_distinguished_name ]

countryName = Country countryName_max = 2 stateOrProvinceName = State localityName = Locality 0.organizationName = Organization organizationalUnitName = Organizational Unit commonName = Common Name commonName_max = 64 emailAddres = Email emailAddress_max = 64

countryName_default = xx stateOrProvinceName_default = State localityName_default = Locality 0.organizationName_default = Sophos UTM organizationalUnitName_default = LAN

#==================================================================== ##----- Establish SubjectAltName (SAN) Profiles -----## #====================================================================

All server certs with WebUIs should have their loopback IP specified in their SAN profile.

# This prevents certificate errors if connecting to the device, router, or server via an SSH tunnel.
  # Certain OS CA certs must have the loopback IP specified in SAN profile (i.e. Sophos UTM's CA).

Provided SAN profiles are utilized, Common Names can be whatever one wishes (i.e. not the DNS or IP)

# SANs can be: 'email' (email address), 'URI' (Uniform Resource Indicator), 'DNS' (DNS domain name),
# 'RID' (Registered ID: OBJECT IDENTIFIER), 'IP' (IP address), 'dirName' (Distinguished Name), and 'otherName'.


#-------------------------------------------------------------------- ##----- Certificate Authorities -----## #--------------------------------------------------------------------

Main

[ alt_ca_main ] DNS.1 = Router.1 IP.1 = 127.0.0.1

Router 2

[ alt_ica_router2 ] DNS.1 = Router.2 IP.1 = 127.0.0.1

Code Signing

[ alt_signing_ica ] DNS.1 = Code-Signing

#-------------------------------------------------------------------- ##----- Certificate Authority Clients -----## #--------------------------------------------------------------------

Main

Servers

[ alt_sophos ]
IP.1                = 192.168.2.1
IP.2                = 127.0.0.1
DNS.1               = UTM.WRT
DNS.2               = your.ddns.com

[ alt_freenas ]
IP.1                = 192.168.2.13
IP.2                = 192.168.2.130
IP.3                = 127.0.0.1
DNS.1               = FreeNAS.WRT
DNS.2               = your-fqdn.com

[ alt_vpn_server1 ]
IP.1                = 10.0.0.1
DNS.1               = your.ddns.com

Clients

[ alt_vpn1_user1 ]
email.1             = user@email.com
DNS.1               = VPN1-Client1-Device1
DNS.2               = VPN1-Client1-Device2


#-------------------------------------------------------------------- ##----- Intermediate Certificate Authority Clients -----## #--------------------------------------------------------------------

Router 2

Servers

[ alt_openwrt ]
IP.1                = 192.168.2.2
IP.2                = 127.0.0.1
DNS.1               = LAN.WRT

[ alt_vpn_server2 ]
IP.1                = 10.0.1.1
DNS.1               = your.ddns.com

Clients

[ alt_vpn2_user1 ]
DNS.1               = VPN2-Client1-Device1
email.1             = user@email.com

[ alt_vpn2_user2 ]
DNS.1               = VPN2-Client2-Device1
DNS.2               = VPN2-Client2-Device2
email.1             = user@email.com


Code Signing

Cert1

[ alt_codesign ]
email.1             = user@email.com


#==================================================================== ##----- Establish Certificate Authority V3 Profiles -----## #--------------------------------------------------------------------

These V3 CA profiles must not be modified to contain any more, or any less, KUs.

These have been configured specifically for security & its imperative no other keyUsages are set

# For an ICA to be capable of signing CAs/ICAs, 'pathlen' number must mirror number of CAs/ICAs it can sign

By default, all ICAs 'pathlen' values are set to 0, meaning they can sign certs, but not other CAs/ICAs.

# If 'pathlen' is not specified, CA/ICA can sign an infinite number of other CAs/ICAs.


[ v3_ca ] basicConstraints = critical, CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = @alt_ca_main keyUsage = critical, cRLSign, digitalSignature, keyCertSign

[ v3_ica_router2 ] basicConstraints = critical, CA:TRUE, pathlen:0 subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = @alt_ica_router2 keyUsage = critical, cRLSign, digitalSignature, keyCertSign

[ v3_signing_ica ] basicConstraints = critical, CA:TRUE, pathlen:0 subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always keyUsage = critical, cRLSign, digitalSignature, keyCertSign subjectAltName = @alt_signing_ica

[ crl_ext ] issuerAltName = issuer:copy authorityKeyIdentifier = keyid:always, issuer:always

#==================================================================== ##----- Establish Generalized V3 Certificate Profiles -----## #--------------------------------------------------------------------

[ v3_req ] basicConstraints = critical, CA:FALSE subjectKeyIdentifier = hash

[ usr_cert_dn ] basicConstraints = critical, CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = critical, clientAuth, emailProtection

[ usr_cert_not_dn ] basicConstraints = critical, CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = email:copy keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = critical, clientAuth, emailProtection

#==================================================================== ##----- Establish Client Certificate V3 Profiles -----## #--------------------------------------------------------------------

These V3 profiles should not be modified to contain less than what they are currently configured with.

# These have been specifically configured with security in mind.

All servers capable of TLS should contain all keyUsages, except for 'dataEncipherment'

# VPN and file servers should not have less than: 'digitalSignature, keyEncipherment, keyAgreement'

All servers must contain EKU 'serverAuth'

# All server [VPN] clients must contain EKU 'clientAuth'


#-------------------------------------------------------------------- ##----- Certificate Authority Clients -----## #--------------------------------------------------------------------

Main

Servers

[ v3_sophos ]
basicConstraints            = critical, CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage            = critical, serverAuth
subjectAltName              = @alt_sophos

[ v3_freenas ]
basicConstraints            = critical, CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage            = critical, serverAuth
subjectAltName              = @alt_freenas

[ v3_vpn_server1 ]
basicConstraints            = critical, CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage            = critical, serverAuth
subjectAltName              = @alt_vpn_server1

Clients

[ v3_vpn1_user1 ]
basicConstraints            = critical,CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage            = critical, clientAuth
subjectAltName              = @alt_vpn1_user1


#-------------------------------------------------------------------- ##----- Intermediate Certificate Authority Clients -----## #--------------------------------------------------------------------

Router 2

Servers

[ v3_openwrt ]
basicConstraints            = critical, CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage            = critical, serverAuth
subjectAltName              = @alt_openwrt

[ v3_vpn_server2 ]
basicConstraints            = critical, CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage            = critical, serverAuth
subjectAltName              = @alt_vpn_server2

Clients

[ v3_vpn2_user1 ]
basicConstraints            = critical,CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage            = critical, clientAuth
subjectAltName              = @alt_vpn2_user1

[ v3_vpn2_user2 ]
basicConstraints            = critical,CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage            = critical, clientAuth
subjectAltName              = @alt_vpn2_user2


Code Signing

Certificates

[ v3_codesign ]
basicConstraints            = critical, CA:FALSE
subjectKeyIdentifier        = hash
authorityKeyIdentifier      = keyid:always, issuer:always
keyUsage                    = critical, nonRepudiation, digitalSignature
extendedKeyUsage            = critical, codeSigning, msCodeInd, msCodeCom, msCTLSign, timeStamping
subjectAltName              = @alt_codesign

JW0914
  • 7,865
  • 1
    “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 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
  • 1
    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
  • @DanielB is correct. It is false to say that self-signed certificates are insecure and pointless. While it is true they are vulnerable to a MITM attack, they are NOT vulnerable to passive eavesdropping. So they are strictly better than plain HTTP. For intranet webservers, self-signed certificates are always better than no certificate at all. Public CA signed certificates are completely unnecessary for intranet sites and usually impossible (unless you have public DNS entries pointing to non-public IPs). Sure, a private CA is an option, but there is a non-zero administrative overhead. – Wildcard Feb 23 '24 at 00:15
  • @Wildcard Please point to any research that deems self-signed certs as recommended, and please explain why the extra 60 - 120s should not be taken to create a self-signed CA to sign a cert. Since we're literally talking about an extra one to two minutes to properly configure Chain of Trust, which all self-signed certs lack, the resistance to this falls quite flat. It took longer to write your comment than it does to generate certs with a correct Chain of Trust. If something is worth doing, it's worth doing right the first time. – JW0914 Feb 23 '24 at 12:40
  • @JW0914 interesting point, I think I get what you're saying now. But with a self-signed CA, you still won't prevent MITM issues unless you actually distribute that CA cert to all possible clients, right? Which is the non-zero administrative overhead I referred to for the private CA option. So what is the advantage exactly over a self-signed cert? – Wildcard Feb 23 '24 at 20:56
  • @Wildcard Chain of Trust example. When using non-commercial CAs, they're distributed within the cert's .pem itself or within the PCKS12 cert's .p12. After signing the cert with the self-signed CA/ICA, afterwards you concatenate the CA, or ICA and CA, to the cert if not exporting to PKCS12, that way the entire Chain of Trust is contained within the client cert itself (see "Concatenate ICA and CA Cert" in #5, which I didn't add to #6 because of "Export"). Self-signed CAs/ICAs must be manually imported into hosts, regardless if a user or the US Dept of Defense – JW0914 Feb 24 '24 at 12:22
  • @Wildcard "So what is the advantage exactly over a self-signed cert?" It's all about Chain of Trust, not the cert in and of itself - a self-signed cert has no Chain of Trust - the cert could be replaced at any time and a user would be none the wiser. If instead you use a self-signed CA, which then signs the cert, it will be immediately obvious if the cert's been replaced or tampered with. It would be one thing if using a self-signed CA made this more complicated or more work, but it doesn't, especially when using the custom openssl.cnf I created, as the default one is complex and confusing – JW0914 Feb 24 '24 at 13:00
  • @JW0914 so you're talking about the clients actually importing the self-signed CA into their browser store so it's then trusted, rather than just clicking past the "accept the risk and continue" button like most employees do when company-internal sites use self-signed certs. In that case yes I see the advantage. But I assume that with a self-signed CA, the user could also just click past the warning, in which case there is no benefit compared to a self-signed cert—correct? It's just about the flexibility that the user can (if they choose to, by installing that CA) see if something changes. – Wildcard Feb 25 '24 at 10:02
  • @Wildcard When self-signed CAs/ICAs are used in a business, normally they're imported into the applicable certificate stores (can be automated with a script). Dept of Defense is an example of this - employees, servicemembers, contractors, etc. are provided with a root CA & ICA bundle they must import into the certificate store. It's not about convenience, but about Chain of Trust, and a self-signed cert has none, making it insecure to use. Business should be educating employees, as this is really simple, requiring no tech knowledge – JW0914 Feb 25 '24 at 12:37
  • @JW0914 thanks, I do understand the advantage of having a proper chain of trust. But it seems to me that from everything you say, you would still acknowledge that if the business isn't bothering to distribute the bundle for import into the cert store, then there is zero advantage to a self-signed CA compared to a self-signed cert. Correct? – Wildcard Feb 26 '24 at 19:56
  • @Wildcard No, that's factually inaccurate. Even if a CA/ICA isn't distributed, a cert is still signed and not self-signed - this is all about Chain of Trust and a self-signed cert has no Chain of Trust. Regardless if the CA/ICA is installed in a certificate store, a cert signed still has Chain of Trust - it simply can't be verified without the CA/ICA (I can't explain it better than the previous link). This entire topic literally ultimately comes down to pure laziness by someone not taking an extra 60 - 120s to do this correctly (it's like using UPnP, which has no secure implementation) – JW0914 Feb 27 '24 at 11:41
  • @JW0914, okay, thanks for taking the time to explain. – Wildcard Feb 28 '24 at 01:01