How to create an identity who can be used for signing code from custom certificate

certificatecode-signingkeychain

I want to codesign one of my applications by using my own certificate (not created with Keychain Access).

First, I create a v3.ext file:

keyUsage = digitalSignature

Then, I created my certificate with openssl:

$ openssl genrsa -des3 -out passkey.key 2048
$ openssl rsa  -in passkey.key -out mykey.key
$ openssl req -new -key mykey.key -out cert.csr
$ openssl x509 -req -sha256 -extfile v3.ext -days 3650 -in cert.csr -signkey mykey.key -out mycertificate.crt
$ openssl pkcs12 -export -in mycertificate.crt -inkey mykey.key -out certificate.p12 -name "My Company Name"

I imported certificate.p12 into Keychain Access by dragging it on the docker. Now, when I try to sign my application, I have this error:

$ security find-identity
Policy: X.509 Basic
  Matching identities
 11) 5DC3086CAD3848A22FB6E614FB8836BDDBD18938 "My Company Name" (CSSMERR_TP_NOT_TRUSTED)

$ codesign --deep -fs 5DC3086CAD3848A22FB6E614FB8836BDDBD18938 repro.app
: this identity cannot be used for signing code

However, we can see this certificate can be used to verify (CSSM_KEYUSE_VERIFY):

$ certtool y
Serial Number      : 00 F6 E2 FC FC D1 67 A6 7A 
Issuer Name        :
   Country         : FR
   State           : Some-State
   Org             : My Company Name
Subject Name       :
   Country         : FR
   State           : Some-State
   Org             : My Company Name
Cert Sig Algorithm : OID : < 06 09 2A 86 48 86 F7 0D 01 01 0B >
   alg params      : 05 00 
Not Before         : 15:09:59 May 13, 2019
Not After          : 15:09:59 May 10, 2029
Pub Key Algorithm  : OID : < 06 09 2A 86 48 86 F7 0D 01 01 01 >
   alg params      : 05 00 
Pub key Bytes      : Length 270 bytes : 30 82 01 0A 02 82 01 01 ...
CSSM Key           :
   Algorithm       : RSA
   Key Size        : 2048 bits
   Key Use         : CSSM_KEYUSE_VERIFY 
Signature          : 256 bytes : 4E F5 B9 35 9D 6A D5 2E ...
Extension struct   : OID : < 06 03 55 1D 0F >
   Critical        : FALSE
   usage           : DigitalSignature

What should I do to allow this identity to sign code?

Best Answer

Your certificate is missing specific codesign requirements. These go beyond keyUsage = digitalSignature.

Conforming Certificate

You need to create a certificate that conforms to macOS's codesigning requirements. You can find the requirements in Certification Authority Certification Practice Statement Developer ID:

4.12.2. Code Signing Certificates

A Code Signing Certificate issued by the Developer ID Sub-CA shall conform to the X.509 Certificate format and shall contain, at a minimum, the following data elements:

  • Serial Number
  • Subject Distinguished Name
  • Issuer Distinguished Name
  • Algorithm used (RSA)
  • Modulus (Size in bits)
  • Validity period
  • Certificate Policies extension listing the CP
  • Certificate qualifiers listing this CPS (URL)
  • User notice qualifier
  • Extended Key Usage extension, critical, with a purpose containing Code Signing (1.3.6.1.5.5.7.3.3)
  • Developer ID Code Signing (1.2.840.113635.100.6.1.13)
  • Certificate Authority Information Access extension, non-critical, with a method of obtaining certificate authority information via Online Certificate Status Protocol method.

For more details, see the Security StackExchange question How to create an Apple Installer Package Signing Certificate.

Trusted Certificate Authority

With a conforming certificate, you will be able to codesign your binary. For the code signature to recognised, you will need to install and trust the Certificate Authority (CA) certificate on your Mac. This needs to be done in a way that Gatekeeper trusts.

You can learn more about this step by searching for install root certificate mac.