First we create a CSR
While creating CSR, the public/private key pair is generated under the hood.
The public key is attached to your CSR
The private key is kept inside your local machine.
It’s not a good idea to generating CSR from multiple macOS as they key pair generated on one mac cannot be present on other mac. Good to use one mac to generate CSR until we create the certificate in P12 format.
To generate a CSR from the command line run:
openssl genrsa -out mykey.key 2048
openssl req -new -key mykey.key -out CertificateSigningRequest.certSigningRequest -subj "/emailAddress=yourAddress@example.com, CN=Your Name Dev Key, C=GB"
This will create CertificateSigningRequest.certSigningRequest
To see some basic info of what’s in the certificate run this
openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest
or for a textual representation
openssl req -text -noout -in CertificateSigningRequest.certSigningRequest
Second we create a Certificate
Upload your CSR to Apple download the .cer file, this is your certificate
Basically, the certificate has all the data that we have provided during creating certificate signing request, Apple then adds some signer data like Authority, expiry date etc. The whole certificate has the signature attached to it.
you can see certificate details with this command:
openssl x509 -in ios_development.cer -inform DER -text -noout
we also need private key attached to the certificate to code signing the apps. This is where we need the certificate in the P12 format to back it up with the private key
PKCS#12
In Cryptography, PKCS#12 a.k.a Public Key Cryptography Standard is the standard used to store private keys with public key certificates protected with the password.
In our case in the iOS Development certificate, we can export the certificate from keychain into the Personal Information Exchange a.k.a p12 format
or from the command line using:
openssl x509 -in XXXXX.cer -inform DER -out mycert.pem -outform PEM
openssl pkcs12 -export -inkey my.key -in mycert.pem -out mycert.p12
You can find details about the p12 using
openssl pkcs12 -info -in mycert.p12
Provisioning Profiles
Provisioning profiles are a combination of multiple things:
App ID
Creation Date
Platform
Developer Certificates
Entitlements
Expiration Date
Provisioning Profile Name
Provisioned Devices
*Team Identifier *
*Team Name *
Version
Team ID
The Team ID is a unique identifier for a team. It can be found under the Apple Developer Portal under the Membership tab. It should be kept secret.
You can also find your team ID in the form of “iPhone Developer: Team Name (YOUR_TEAM_ID)” by running this:
security find-identity -v -p codesigning
Bundle Identifier
This is unique identifier for your app in reverse domain notation (EX: com.domain.appname). This needs to be set up in iTunes Connect and included in the app plist file.
App Identifier
The App ID is a combination of your Team ID and your Bundle Identifier. It identifies one or more apps.
Lets say your Team ID is *A1B2C3D4E5 *and your Bundle ID is *com.domainname.appname *then your App ID would be:
A1B2C3D4E5.com.domainname.appname
You can also use an asterisk to identify multiple apps like so:
A1B2C3D4E5.com.domainname.*
Device ID
Your Device ID is your device’s UDID, which is a 40 character combination of letters and numbers.
You can find your Device’s UDID by following this guide:
https://www.macworld.co.uk/how-to/iphone/how-find-out-your-iphone-or-ipad-udid-3530239/
or you can type this to get the UDID of all connected devices:
instruments -s devices
Entitlements and Sandbox
Entitlements specify what system resources the app can use. They can be defined in the capabilities section. The will be stored in a plist file with extension .entitlements
Check here for an in depth discussion:
You can check an apps entitlements by running this command
codesign -d --entitlements :- /Users/shashi/Library/Developer/Xcode/DerivedData/iOSCodeSigning-gakpslthucwluoakkipsycrwhnze/Build/Products/Debug-iphones/iOSCodeSigning.app
To check the entitlements of a .ipa file
* Change the extension to zip
* Expand the zip file which will produce a Payload folder with a .app file
* Use the codesign tool
codesign -d --entitlements :- "Payload/YourApp.app"
For an in depth discussion of the App Sandbox check here:
Provisioning Profiles Creation
After we create the profile on the Apple Developer Portal, download and install it. We should be able to find it here:
~/Library/MobileDevices/Provisioning Profiles
Provisioning Profiles have a .mobileprovision extension. They are stored using Cryptographic Message Syntax. To view them we can do this:
cd ~/Library/MobileDevice/Provisioning\ Profiles/
security cms -D -i xxxxxxxx_your_pp_id.mobileprovision
Code Signing
For the Apple documentation look here:
To code sign an app from the command line we can do this:
codesign -s "iPhone Developer: Shalom Friss (MY_TEAMID)" ~/Library/Developer/Xcode/DerivedData/iOSCodeSigning-gakpslthucwluoakkipsycrwhnze/Build/Products/Debug-iphonesimulator/iOSCodeSigning.app/
There are three main stages to code signing
Seal
Digital Signature
Code Requirement
Seal
Codesign generates a seal by hashing every part of the code. A verifier then goes through the code and double checks the hashes. The hashes look like this:
<key>Frameworks/libswiftos.dylib</key>
<dict>
<key>hash</key>
<data>
dyKltMCMbq+pYDVJBtY78y7BuP0=
</data>
<key>hash2</key>
<data>
6DxNIVZgqWfOeWfedGQ1+wOnIuA7vQlU+gVA0WhCiRw=
</data>
</dict>
This is great as long as the hashes aren’t altered. To make sure they are not, codesign uses a digital signature.
Digital Signature
To create the digital signature, codesign encrypts the hashes using the user’s private key, which are stored in the app along with the signer’s certificate. We can verify the signature on the command line using:
codesign -v --verbose=5 ~/Library/Developer/Xcode/DerivedData/iOSCodeSigning-gakpslthucwluoakkipsycrwhnze/Build/Products/Debug-iphonesimulator/iOSCodeSigning.app/
Any change in the code will invalidate the hash. The signature of the code is stored in the app binary, while the signatures of frameworks, bundles, tools and other code are stored in the bundle in CodeSignature/CodeResources
Code Requirements
Code requirements are rules used to ealuate the code. The complete language details can be found here.
For example, you could require that any plugins only come from Apple.
Code requirements can be specified to be part of the code signature, which are called internal requirements.
Details
To print out the details of the code signing run this:
codesign -d --verbose iOSCodeSigning.app/
NOTES
* Archives created with xcodebuild are signed with a development certificate at first
* When we specify the distribution method, the archive is re-signed with the distribution certificate
This means if you are using automatic signing on Continuous Integration servers then you must have development as well as distribution certificate on CI server.
Apple’s guide to manual signing
https://help.apple.com/xcode/mac/current/#/dev1bf96f17e****
Re-Signing an App
1.) Find the .ips file
2.) Unzip and remove the code signature:
unzip -q old.ipa
rm -rf Payload/*.app/_CodeSignature
3.) Replace the old provisioning profile with the new one
cp new_provisining_profile.mobileprovision Payload/*.app/embedded.mobileprovision
4.) Generate entitlements using the old entitlements
cd Payload/
codesign -d --entitlements - *.app > entitlements.plist
cd ..
mv Payload/entitlements.plist entitlements.plist
5.) Force sign the app with the new entitlements and certificate
/usr/bin/codesign -f -s "Your_certificate_in Keychain" '--entitlements' 'entitlements.plist' Payload/*.app
6.) Zip the .ipa
zip -qr resigned.ipa Payload
References
https://medium.com/xcblog/ios-code-signing-tutorial-series-814b22eba507