IOS signature mechanism is quite complex, all kinds of certificates, Provisioning Profile, entitlements, CertificateSigningRequest, p12, AppID and concept, is also very easy to get wrong, this paper starting from the principle, Step by step to explain why there are so many concepts, hope to help understand the principle and process of iOS App signature.

purpose

Let’s take a look at what Apple’s signature mechanism is designed to do. Before iOS came out, developing and running software on the mainstream operating systems (Mac/Windows/Linux) did not require a signature, and software could be downloaded from anywhere. As a result, the platform was difficult to control third-party software and piracy was prevalent. Apple hopes to solve this problem. It has absolute control over third-party apps on the iOS platform. It must ensure that every APP installed on iOS is officially approved by Apple. Through the signature mechanism.

Asymmetric encryption

Usually, the signature is a digital signature, which is based on asymmetric encryption algorithm. Symmetric encryption uses the same key to encrypt and decrypt data, while asymmetric encryption uses two keys, a public key and a private key. Data encrypted with the public key can be decrypted only with the private key, and data encrypted with the private key can be decrypted only with the public key.

The asymmetric encryption algorithm RSA is a common encryption algorithm, which is used for encryption. The asymmetric encryption algorithm is used for encryption.

  1. Take two prime numbers p and q and multiply them together to produce a large integer n, for example p = 61, q = 53, n = pq = 3233
  2. Choose any prime number e between 1 and n, for example, e = 17
  3. After a series of mathematical formulas, a number D can be worked out, which meets the following requirements: a. After performing mathematical operations on a group of data using n and E, it can be solved by using n and D, and vice versa. B. If you only know n and e, to derive D, you need to know p and q, which means you need to factor n.

(n,e) together is the public key, and (n,d) is the private key, which can be encrypted with the private key and decrypted with the public key, or vice versa, and can be decrypted with the private key. In order to derive the private key (n,d), if only the public key is exposed (only n and e are known), the factorization of the large integer n is required. At present, factorization can only rely on brute force exhaustion, and the larger the n number is, the more difficult it is to calculate the factors P and Q with exhaustion, and the safer it is. When n is large enough to 1024 or 2048 bits of binary, it is almost impossible to crack with current technology, so it is very safe.

If you are interested in how the number D is calculated, you can read these two articles: Principles of RSA Algorithm (1) (2)

A digital signature

Now that we know asymmetric encryption is a thing, what about digital signatures?

What a digital signature does is I put a mark on a piece of data that SAYS I approve it (sign my name), and THEN I send it to someone else who knows that I’ve authenticated the data and that it hasn’t been tampered with.

With the above asymmetric encryption algorithm, this requirement can be fulfilled:

  1. First, an algorithm is used to calculate a summary of the raw data. A. If there is any change in the original data, the calculated summary value will change. B. Summaries should be short. The most commonly used algorithm here is MD5.
  2. Generate an asymmetrically encrypted public and private key. I hold the private key and publish the public key.
  3. After calculating the abstract of a piece of data, encrypt the abstract with the private key and get an encrypted data, which is called the signature of the original data. Send it to the user along with the raw data.
  4. After the user receives the data and signature, the public key decrypts the abstract. At the same time, the user uses the same algorithm to calculate the summary of the original data, and compares whether the summary calculated here is equal to the summary obtained by decrypting the signature with the public key. If the summary is equal, it means that the data has not been tampered, because if it is tampered, the summary will change.

The reason for the first step calculation abstract is that the principle of asymmetric encryption restricts the encrypted content to be not too large (not larger than the above bits of N, that is, generally not larger than 1024 bits / 2048 bits), so if you want to sign any large data, you need to change the signature to its eigenvalue, the effect is the same.

Ok, so we have the basics of asymmetric encryption, what a digital signature is, and how you can ensure that a piece of data is authenticated somewhere, so let’s see how you can use digital signatures to ensure that every APP installed on iOS is authenticated by Apple.

The simplest signature

To realize this requirement, apple officially generates a pair of public and private keys and builds a public key in iOS. The private key is saved by Apple background. When we upload the App to AppStore, Apple background signs the App data with the private key. Verify the signature with the public key. If the signature is correct, the APP must have been authenticated by Apple and has not been modified, which meets Apple’s requirement: ensure that every APP installed is officially approved by Apple.

If the only way to install an APP on an iOS device was to download it from the APP Store, that would be the end of it, nothing complicated, just a digital signature, very simple to solve the problem.

But actually because there are three ways to install an App besides downloading it from the AppStore:

  1. When developing App, you can directly install the application under development into the mobile phone for debugging.
  2. In-house Is distributed within an enterprise. You can install the APP after the enterprise certificate is signed.
  3. Ad-hoc is the equivalent of a limited version of enterprise distribution that limits the number of devices installed and uses them less.

Apple has a new requirement to control apps installed using these three methods, and it’s not as simple as this.

New requirements

Let’s start with the first one, which has two requirements:

  1. The installation package does not need to be uploaded to an Apple server and can be installed directly on the phone. If you have to sign an APP on Apple’s servers before compiling it on your phone, it’s obviously not acceptable.
  2. Apple must have control over the installation here, including a. Such installation is permitted by Apple. B. Cannot be abused so that non-development apps can be installed.

To meet these requirements, the complexity of iOS signatures begins to increase.

Apple’s solution here is to use a double-layer signature, which will be more complicated. The process is roughly like this:

  1. Generate a pair of public and private keys on your Mac development machine, called public key L and private key L. L:Local
  2. Apple itself has a fixed pair of public and private keys. As in the AppStore example above, the private key is in the apple background and the public key is on each iOS device. This is called public key A and private key A. A:Apple
  3. Upload public key L to the Apple background and use the apple background private key A to sign public key L. Get a piece of data that contains the public key L and its signature, and call that data a certificate.
  4. During development, after compiling an APP, the local private key L is used to sign the APP, and the certificate obtained in the third step is packaged into the APP and installed on the mobile phone.
  5. During the installation, the iOS system obtains the certificate and uses the built-in public key A to verify the digital signature of the certificate.
  6. Verify the certificate to ensure that the public key L is authenticated by Apple, and then use the public key L to verify the signature of the APP, which indirectly verifies whether the APP installation behavior is officially approved by Apple. (This only verifies installation behavior, not whether the APP has been changed, since APP content is constantly changing during development and Apple doesn’t need to deal with it.)

Add something

The above process only addresses the first requirement, which requires Apple’s permission to install, and does not address the second problem of avoiding abuse. How do you solve it? Apple has added two more restrictions, one is to limit the installation to devices registered in the Apple background, and the other is to limit the signature to a specific APP.

How did you add it? In the third step above, when Apple uses the private key A to sign our local public key L, in fact, in addition to the signature public key L, it can also add unlimited data, which can be guaranteed to be authenticated by Apple and will not be tampered with.

It can be thought that the list of device ids allowed to install and the corresponding AppID of App and other data are combined with the public key L in step 3 to form A certificate, and then the Apple private key A is used to sign the certificate. In the verification step 5, you can get the device ID list and judge whether the current device meets the requirements. According to the principle of digital signature, as long as the digital signature is verified, the device IDs, AppID, and public key L in step 5 are authenticated by Apple and cannot be modified. Apple can restrict the devices and apps that can be installed to avoid abuse.

The final process

In fact, in addition to device ID/AppID, there are other information that also need to be signed by Apple here. Apple wants to control the permissions of iCloud/push/background running in this APP. Apple refers to these permission switches as Entitlements, which also require Entitlements by signature.

There was a standard format for a certificate, and it wasn’t appropriate for us to stuff all the extra information into the certificate, so Apple created a Provisioning Profile, A Provisioning Profile contains the certificate and all the additional information mentioned above, as well as the signing of all the information.

So the whole process changes slightly and looks like this:

Since there is a small change in the steps, here we list the whole process again without further ado:

  1. Generate a pair of public and private keys on your Mac development machine, called public key L and private key L. L:Local
  2. Apple itself has a fixed pair of public and private keys. As in the AppStore example above, the private key is in the apple background and the public key is on each iOS device. This is called public key A and private key A. A:Apple
  3. Upload public key L to the Apple background and use the apple background private key A to sign public key L. Get a piece of data that contains the public key L and its signature, and call that data a certificate.
  4. Apply for an AppID in the Apple background, configure the device ID list and the permissions available to the APP, and then add the certificate in step 3. The data is signed with the private key A. The data and signature together form A Provisioning Profile and download it to the local Mac developer.
  5. During development, you compile an APP, sign the APP with the local private key L, and pack the Provisioning Profile from Step 4 into the APP called Embedded. Mobileprovision. Install the APP on your phone.
  6. During the installation, the iOS system obtains A certificate and uses the built-in public key A to verify that the digital signature of Embedded. Mobileprovision is correct and the certificate signature in the certificate is verified again.
  7. After ensuring that the data in Embedded. Mobileprovision is authorized by Apple, you can access the data and verify all kinds of things, including the APP signature using the public key L, whether the device ID is on the ID list, and whether the AppID is valid. Permission switch Entitlements correspond to Entitlements in APP, etc.

The developer certificate process from signing to certifying eventually goes something like this, with a few details like certificate validity/certificate type left out.

Concepts and Operations

The above steps correspond to our ordinary specific operations and concepts as follows:

  1. In step 1 is the corresponding keychain “from the certificate issuing authority request”, here is the local generates a pair of public and private keys, save CertificateSigningRequest is public key and private key is stored in the local computer.
  2. Step 2 Apple treatment, leave it alone.
  3. Step 3 corresponding upload CertificateSigningRequest apple background generated certificate, and downloaded to the local. The keychain will associate the two certificates because their public and private keys are the same. When XCode selects the downloaded certificate, it will actually find the corresponding private key in the keychain to sign it. The private key is only available on the Mac that generated it. What if other Macs want to compile and sign this App? The answer is to export the private key to another Mac. If you export the private key to a keychain, it will be saved as a.p12 file. Other Macs will import the private key when they open it.
  4. Step 4 is all on the Apple web site, configuring AppID/permissions/devices, etc., and finally downloading the Provisioning Profile.
  5. Step 5 XCode will use the certificate downloaded from Step 3 (with the public key), find the corresponding private key locally (generated in step 1), and use the local private key to sign App. And package the Provisioning Profile named Embedded. Mobileprovision. The signature data of App is stored in two parts. The Mach-O executable will write the signature directly to this file, and other resource files will be stored in the _CodeSignature directory.

The packaging and validation steps 6-7 are done automatically by Xcode and iOS.

To summarize these concepts:

  1. Certificate: A packet containing a public or private key that is signed by another organization.
  2. Entitlements: Contains a list of App permission switches.
  3. CertificateSigningRequest: local public key.
  4. P12: local private key that can be imported to other PCS.
  5. Provisioning Profile: A data packet containing a certificate/Entitlements, and signed by an Apple background private key.

Other distribution methods

The development kit was used as an example to describe the process of signature and verification. The other two methods of in-house enterprise signature and ad-hoc process are similar, but enterprise signature does not limit the number of devices installed. In addition, users need to manually click on the iOS system Settings to trust the enterprise to pass the verification.

However, the AppStore’s signature verification method is a little different. Previously, we talked about the simplest way to sign the App. Apple directly uses the private key in the background to sign the App. Embedded. Mobileprovision does not contain the embedded. Mobileprovision file, which means that the installation and startup process does not depend on this file, and the verification process is different from the above types.

Presumably, since apple re-encrypts the content of packages uploaded to the AppStore, the original signature of the local private key is useless and needs to be re-signed, and apple does not intend to control the expiration date of packages downloaded from the AppStore. You do not need embedded. Mobileprovision for verification. You can directly re-sign the App using the background private key in Apple and use the local public key to verify the App signature during iOS installation.

So why launch an AppStore package with all the same certificates and Provisioning profiles as development? The assumption is that because apple wants to do unified management, the Provisioning Profile includes some permissions control, the validation of AppID, etc. Apple doesn’t want to do the validation again with another protocol when uploading the AppStore package. Let’s put this in a Provisioning Profile and use the same process to validate the Provisioning Profile when uploading the AppStore.

So once your App is uploaded to the AppStore, it doesn’t matter if your certificate/Provisioning Profile is expired or not, it doesn’t affect the installation package on the AppStore.

Here the principle and main process of iOS signature mechanism is roughly said, hoping to understand apple signature and troubleshooting daily signature problems are helpful.

P.S. some questions

Finally, here are my questions about the signature process.

Enterprise certificate

Enterprise certificate signature is widely used for testing and piracy in China because of fewer restrictions. Fir. im/Dandelion and other testing platforms are distributed through enterprise certificates. Some domestic markets like PP assistant and AISi Assistant, part of the installation means are re-signed through enterprise certificates. The App installed by signing the enterprise certificate will verify the validity of the certificate when it is started and request the Apple server to check whether the certificate has been revoked from time to time. If the certificate has expired or been revoked, the App cannot be started. For this assistant pirated installation method, Apple wants to crack down on only one corporate certificate, there is no good way.

My question here is, with all the signing and verification mechanisms that Apple has put in place to limit App installs on iOS, why would apple create such a way with few restrictions to allow piracy to take advantage of it? If it is true that enterprise use is not suitable for AppStore, you can also open a small private section in AppStore, or install it through AppStore, and there will be no such problem.

AppStore encryption

Another problem is that after we upload the App to AppStore, Apple will encrypt the App, which leads to a large size of the App. This encryption is useless in fact, but the cracked person has to do an extra step, run the App to dump the executable file from the memory. No matter how encrypted, You can pull out pre-encrypted executables in this way. So why do this encryption? I can’t think of any good.

A local private key

The Provisioning Profile is available but the certificate is not available, the local public key certificate is available but the private key is not available, etc. If you don’t understand the principle, you will be confused. My question is, why can’t you simplify this? As an example, why use the private key generated by the local Mac to sign the certificate? Apple only needs a local signature, and the private key doesn’t have to be locally generated. Apple can also generate a pair of public and private keys for us, put them in a Provisioning Profile, and we can encrypt them with the private key. So there will be no CertificateSigningRequest and concept of p12, has nothing to do with local keychain, don’t need to care about the certificate, so long as has the Provisioning Profile can sign, process will reduce, ease of use will improve a lot, And apple wants no less control and no security issues, so why not?

One reason to think about it is that a Provisioning Profile is packaged in a non-Appstore installation, so a third party can take the Provisioning Profile and use it directly to sign their own App. But this kind of problem is easy to solve, just need to remove the private key in the file when packaging, so I still don’t understand why this design.