Preface
For a few years iOS app coder, for the certificate generation, the use of the process of heart, but the principle of this mechanism has been not very understanding. Recently, due to the work needs to be carefully studied, the special study of their own experience in this, for everyone to learn correct.
problem
The typical iOS app's signature process is this (just write about it, there's a lot of the process online):
- To access the keychain, use the Certificate assistant's "Request certificate from a certification authority" to generate a certificatesigningrequest.certsigningrequest file.
- Open https://developer.apple.com and use the CSR file you just generated to generate the certificate (certifcate).
- Create an App ID in the identitifiers of your website.
- Add the Udid of the device you want to test with in devices.
- To generate the. mobileprovision file in the provisioning profiles, you need to tick the ID, udids, and certificates.
- Download the. cer file and the. mobileprovision file to your Mac local, double-click, and you can choose from the Build Settings page in Xcode to package your signature.
- You can export the corresponding P12 file by keychain, double-click on another Mac computer, and they can also be packaged with this certificate.
So the problem is, the whole process is encapsulated, and we're back and forth between the keychain, the developer site, and Xcode, and we don't know exactly what's going on. So there are the following wordy.
Concept
Apple needs us to sign our app so that when users download it from the App store to our app, users can be sure that our app comes from us and has never been changed by someone else. Two of the most important concepts of digital signatures are certificates, and the other is public-key cryptography (asymmetric encryption). Apple's digital signature mechanism uses the standard, which relies on the encryption algorithm RSA.
Certificate
The whole process of digital signatures is like this: for the file to be encrypted, first generate its corresponding hash (a file corresponding to a unique hash), and then use the private key to encrypt it and record it. After the user receives the file, decrypts the hash using the public key, and then compares it with the hash of the file that he calculates. If this is the case, the file has not been modified and the file originates from the holder of the private key paired with the public key.
However, there is still a logical loophole in this operation, that is, no one can prove that the public key in the user's hands is legitimate. That is, a says B is legal, but no one can prove that a is legal, and if a is illegal, there is no guarantee that B is legal. That is, the public key proves that the private key of the signature is paired with it, but it cannot be determined that the private key really comes from the signer it says.
Therefore, the certificate protocol introduces a certificate (*. A) to solve this problem. Certificates, like our identity cards, can uniquely identify us and contain information about ourselves. The certificate is issued by the Authority (ca,certification Authority) (as if the identity card is issued by the public security organ, as long as the public key holder trusts it), and has a validity period, as shown (in the keychain), the CA is Apple worldwide Developer Relations Certification Authority, the expiration date is 2016.11.16.
On the other hand, the certificate contains the public key, which the terminal can use to verify the information. In this way, the whole chain is complete.:ca-> Proof certificate (public key) the legitimacy of the public key proves that the private key encrypts information, so that the user can confirm that the data originates from the person it identifies and has not been modified.
Rsa
In addition to certificates, another important concept is RSA. The RSA algorithm can be used for encryption (public key plus private key solution) or for digital signature (private key plus public key solution). Here we use OpenSSL as a tool for research.
First we generate a pair of key pairs as simple as possible, which is, of course, unsafe:
OpenSSL genrsa-out private.key-OpenSSL rsa-in private.key-pubout > Pubkey.pubkey
-----BEGIN RSA PRIVATE KEY-----
Mcscaqacbqctbwyxagmbaaecbdpl33ucawdepwidamdnagi/dwicct8cajmj
-----END RSA PRIVATE KEY-----
-----BEGIN Public KEY-----
mcawdqyjkozihvcnaqebbqaddwawdaifak1tzjecaweaaq==
-----END Public KEY-----
This is a pair of 32-bit-length key pairs, which is actually the binary length of the modulus (modulus), which means that the modulus is greater than 2 of the 31 is less than 2 32-square. We can see that the content is Base64 encoded, and the private key file content is longer than the public key. By command you can look at what is contained in it:
OpenSSL rsa-in Private.key-text- noout output: Private-key: (+ bit) modulus:2909627953 (0xad6d6631) publicexponent:65537 (0x10001 ) privateexponent:979754869 (0x3a65df75) prime1:56999 (0xdea7) prime2:51047 (0xc767) exponent1:16247 ( 0x3f77) exponent2:28991 (0x713f) coefficient:13091 (0x3323)-pubin-in Pubkey.pubkey- Text-noout output: modulus (+ bit): 2909627953 (0xad6d6631) exponent:65537 (0x10001)
which
- Modulus length is 32 bits and the value is 2909627953 (10101101011011010110011000110001)
- modulus = prime1 * prime2
- Publicexponent * privateexponent mod (prime1-1) * (prime2-1) =1
- (modulus, publicexponent) public key
- (modulus, privateexponent) private key
So, if someone else gets our private key file, he has everything we encrypt. Apple developers ' private keys are generally stored in keychain. The RSA encryption algorithm is the same as the decryption algorithm (the encryption is actually the same algorithm as the signature, but the role of the public private key is different), if a is clear text, B is ciphertext, then:
A=b^privateexponent mod modulus;b=a^publicexponent mod modulus
And the public private key can be used interchangeably, namely:
A=b^publicexponent mod modulus;b=a^privateexponent mod modulus
about how to use OpenSSL to sign and verify files, there is no too much to describe here, it is interesting to look at the contents of the resources.
specific to iOS
So, how does the above concept work in Apple's system? This is probably the case:
- First, a CSR (. certsigningrequest) file is generated in the Keychain assistant, and the private key and public key are already generated on your computer. The CSR file contains the public key, along with some other information.
- Sign in to the Apple Developer website, and if your account has permission, your information will be verified as valid. The CSR is then uploaded to the Apple Developer website (CA), which encrypts the file information with its own private key, which gets a certificate file that contains your public key and other information about you.
- In this way, the developer gets a pair of certified key pairs. The provision profile is then generated on the website, which is used to follow the app so that the app can only run on the specified iphone (for example, ad hoc can only run on a mobile phone that has been added udid). Provision profile contains the app's app ID and who can run the app. It also contains the application's certificate (public key), so that the user's phone can detect whether the content of the app is legitimate.
- When we pack, we need to select the code Signing Identity (chosen in Build settings) to use, which corresponds to the private key in the keychain. When the. App is generated, the code is compiled into a binary file, and the resources are copied into the. App. The system then encrypts the hash of each file using the specified private key, and the result of the resource file is saved in the coderesources under _codesignature under the. App, and the binary file is written to the file. Included together with the description file containing the public key embedded.mobileprovision.
- When the user installs the app, iOS uses its own public key, the Apple worldwide Developer relations certification Authority validates the certificate in the Embedded.mobileprovision, verifies that the public key in the certificate is used to verify the files in the app directory, and if it is legal, the app is legitimate.
Below, we will do a detailed analysis of each step to see what happened to the whole process.
Key
First of all, we want to generate the core of the entire process, the private key, the public key; Apple is using a 2048-bit key:
OpenSSL Genrsa-outprivate2048
This allows us to generate the private key, and the public key can be exported from the private key file (as the information in the private key file actually contains the public key):
OpenSSL RSA-inprivate. key-pubout > Pubkey.pubkey
Open these two files and you can see that the two files are surrounded by such strings:
-----BEGIN RSA PRIVATE KEY ——... -----END RSA PRIVATE key-------BEGIN public KEY ——... -----END Public key--
The core content in the middle is the Base64 key (and other information). This way we have a pair of key pairs that are not recognized by the CA.
CSR
Next we need to generate a CSR file that is validated to the CA:
OpenSSL req-newprivatekey-out IOS-DEV.CSR
This command will ask you to ask some of your information, the information here is no use, when the certificate is generated, Apple will use our developer account related information to fill in. And what really matters is the public key it carries, and we can look at:
OpenSSL req- in Ios-dev.csr-noout-pubkey
You can see that the public key information is the same as the previously generated public key. The CSR contains two pieces of information, the subject information, which is the information you previously asked, and the public key you created.
Certificate
Next, we need to log in to developer.apple.com to generate the certificate. The concrete steps here are not much to say, in short, the result is that we have a certificate (. cer). What we're concerned about is what happens in this step?
This step requires the CA to verify that your information is trustworthy and, if trustworthy, to sign the public key in the CSR that you provided with its private key, and to take some other information, eventually generating the certificate and returning it to you. How do you verify your information? You've already verified it before you applied for a developer account. Your personal information, bank card account information and so on, as long as it complies with Apple's rules, it thinks you are legal. So, this step, Apple just encrypts your public key with its private key.
We can export the public key from certificate (assuming that Apple is returning Ios_distribution.cer):
OpenSSL X509-inform der- in Ios_distribution.cer-pubkey-noout > Cer_pub.pubkey
The comparison shows that Cer_pub.pubkey is the same as the Pubkey.pubkey we generated earlier.
And then we can look at what's in it specifically:
OpenSSL X509-inform der- in Ios_distribution.cer-text-noout
As you can see, the CA for this certificate is Apple worldwide Developer relations Certification authority, as well as subject information and so on.
Now, we need to import the certificate into the keychain:
OpenSSL X509-inform der- in Ios_distribution.cer-out-export-inprivate . Key-out'Test sign '
Enter a password. At this point, a TEST.P12 file is generated in the current directory. Double click to import Keychain (no password will fail to import). Or, import by using the following command:
Security Import Test.p12-k ~/library/keychains/login.keychain
Open the keychain, select "Login", "certificate", will find the certificate we just generated:
As you can see, both the certificate and the private key are available, so the certificate can be used for signing.
So how does the iOS verify that the certificate is legitimate and that the public key is available? Since Apple introduced the keychain, OpenSSL should not have done it (and according to Apple, since the API between the OpenSSL versions has been changing, it has never been provided as part of iOS). Apple provides a command-line tool security in a Mac system that can be used to handle keychain-related operations. We can verify the certificate we just generated:
Security Verify-cert-c ios_distribution.pem output : ... certificate verification successful.
We can create a self-signed certificate:
365 -newkey RSA:2048 -keyout Selfsign.key- out SELFSIGN.CRT
Then verify that:
Security Verify-cert-c selfsign.crt output : Cert Verify result:cssmerr_tp_not_trusted
As you can see, this certificate is not trusted. So we can see that iOS is probably a similar way to confirm the trustworthiness of the certificate in Embedded.mobileprovision.
Sign
Everything is ready, only owed the East wind. When we have finished writing the code, we need to sign the code. Apple provides a tool codesign greatly simplifies the workflow (and of course encapsulates the specific process). As long as you know the code sign identity (that is, the certificate's CN; The certificate needs to be stored in the keychain), the app can be signed:
Codesign-s-F ' {Code sign identity} ' Test.app
Then, we can look at the signature information of the app:
CODESIGN-VV-D Test.app
Output:
executable=/users/hy/library/developer/xcode/deriveddata/test-hekagtjqikppkueajznajyogtpmc/build/products/ Debug-iphoneos/test.app/test
Identifier=com.xxx.test
Format=app Bundle with Mach-o Universal (ARMv7 arm64)
Codedirectory v=20200 size=618 flags=0x0 (none) hashes=14+3 location=embedded
Signature size=4690
Authority=iphone distribution:xxx
Authority=apple Worldwide Developer Relations Certification Authority
Authority=apple Root CA
Signed time=2016 August 8 4:19:19
Info.plist entries=27
teamidentifier=vwen6qtm5a
Sealed Resources version=2 rules=12 files=7
Internal Requirements Count=1 size=168
As you can see, the app was signed by iphone Distribution:xxx and it was signed by Apple Worldwide Developer Relations certification Authority, The certificate is also signed by Apple Root CA, and the entire chain is complete.
The specific encryption algorithms, hash algorithms are packaged in Apple, so we can not know how the signature is calculated. The signature of the resource file is stored in _codesignature/coderesources, and the signature of the binary file is written directly into the file. If you are interested, you can use different certificates to sign the name of the comparison.
Provision profile
Next, we need to install the app on the phone, when it's time to provision profile (. mobileprovision). Each iOS app carries a corresponding description file, which is named Embeded.mobileprovision in the app root directory. iOS needs to use this profile to determine whether the app has permissions to run. In a Mac system, it is stored in the ~/library/mobiledevices/provisioning profiles directory. When you package your app, Xcode simply copies the corresponding certificate from the directory to the app directory. Let's take a look at what it contains specifically.
Use the command to view its contents:
Security Cms-d-I. test.mobileprovision
This will output an XML, and we can see that this file contains the content that we are interested in:
- Developercertificates contains the previously generated certificate
- Application-identifier App ID
- Provisioneddevices the udid of all devices that this certificate can install, only appear in the Develop profile
In fact, from the site's generation process, we can also see what it contains. Because we want to create an app ID first, and then if it is a test certificate, we need to enter the Udid of the test device, then we need to choose which certificate it contains.
Let's verify if it contains the previously created certificate:
' Print $& if m{(?<=<data>). *? =</data>)}' | base64-d > Mobile.cer
The above command is to parse the description file first, the result as a regular input of the following sentence; regular gets the content between <data></data>, which is the certificate contained in Developercertificates (assuming there is only one) The contents of the extract are stored in Mobile.cer using base64 decoding.
Comparing Mobile.cer with the previously generated ios_distribution.cer, two files were found to be the same. It is also possible to know that the description file does contain a public key for validating the signature.
Summarize
These are some of the things I understand about Apple's code signing mechanism. The article ignores some of the content, some because of the time problem, some because it is not related to the topic of this article, some because of their negligence. For the lack of the text and flaws, please feel free, first thanked.
Resources
RSA algorithm
http://www.matrix67.com/blog/archives/5100
Http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
http://doctrina.org/How-RSA-Works-With-Examples.html
https://www.cs.cornell.edu/courses/cs5430/2015sp/notes/rsa_sign_vs_dec.php
Certificate
https://technet.microsoft.com/en-us/library/bb123848 (v=exchg.65). aspx
Https://www.sslshopper.com/what-is-a-csr-certificate-signing-request.html
Http://www.shellhacks.com/en/HowTo-Decode-CSR
Openssl
Http://www.cnblogs.com/interdrp/p/4881116.html
http://ngs.ac.uk/ukca/certificates/advanced
iOS Code signing
https://www.objc.io/issues/17-security/inside-code-signing/
Http://www.stencyl.com/help/view/ios-certificates-guide
iOS Code signing comprehension