Github open source project address

Github.com/iamlion/3To…

An overview of the

As a project-driven company, when managing APP description files, we often encounter the problem of expired description files, which causes the client application to be unavailable. At this time, users will be at a loss, which will affect the user experience and even the APP traffic. Most of the solutions, however, are to re-sign the application and distribute it using re-signing tools on the market, or to repackage the application and distribute it in Xcode, which is very unfriendly to developers. We must not fix the problem before it is too late. We must prepare for the risk before it comes, and fix the problem without the user knowing it. For this purpose, re-signing makes sense, and if you haven’t studied re-signing or are studying re-signing, this article is for you.

precondition

IOS application re-signing has certain preconditions and software dependencies, and is not cross-platform, at least this scheme cannot be used on Windows.

Depend on the conditions
  • MacOS operating system
  • Apple Developer Account
  • /usr/libexec/PlistBuddy
  • Security (come with MacOS)
  • Codesign (come with MacOS)
  • zip
  • unzip

The above dependencies are system software and can be installed via HomeBrew if zip and unZIP software does not exist.

brew install zip;
brew install unzip;
Copy the code

IPA briefly

As a mobile developer, you should know that the Android app installation package is *.apk and the iOS app installation package is *.ipa. In fact, these packages are compressed packages that can be unzip. The extracted files are resource files, application configuration files, application description files, and application binary files required by the application. The application description file is the target of this operation.

In addition to the application description file, there is another category of application within the iPA, which is appex. This kind of application is an extension of the host application. Appex also has its own description file. If the description file of the host application is updated successfully, but the appex application does not update the description file, the signature will also fail.

In conclusion, if the application needs to re-sign, we need to determine whether it existsappexApplication, if any, is required for eachappexThe directory is re-signed, and then the whole directory is re-signed. If it does not exist, only the home directory needs to be re-signed.

We can download the iPA package of the application from Ace Assistant and then unpack it with the visualization software.

Describes the capability of bundleids in files

Each BundleId has Capabilities, and the signature target must have no less Capabilities than the current new description file. If the new description file has fewer Capabilities than the target signature object, the signature will also fail.

Re-sign the core operation

The core operation of re-signing is codesign. This command is provided by MacOS and is mainly used for code signing.

Signature command:
codesign -f -s "DEVELOPER_TEAM" "PLISTFILE_PATH" "SIGN_DIRECTORY"
Copy the code

-f indicates force, and -s indicates sign.

 -f, --force
             When signing, causes codesign to replace any existing signature on the path(s) given. Without
             this option, existing signatures will not be replaced, and the signing operation fails.



-s, --sign identity
             Sign the code at the path(s) given using this identity. See SIGNING IDENTITIES below.
Copy the code

Operation is briefly

After the analysis, the design idea should be:

  1. Extract the targetipaPackage to temporary directory
  2. Will be applied underembedded.mobileprovisionReplace with the new description file
  3. Convert the new description file toinfo.plistFile to temporary directory
  4. After operation from aboveinfo.plistTo extractTeamName.Entitlementsinformation
  5. Finally, the core operation of re-signature is used to re-sign the directory
  6. The above process of the first2.3.4.5Step, ifappexIf the application exists, perform the operation again. If the application does not exist, do not perform the operation
  7. After signing, usezipCommand to repackage the application intoipafile
  8. Delete junk files generated by temporary directories

At this point, the re-signature operation is complete, which is implemented using a Shell script.

Step 1: Create a temporary directory

Create a temporary directory to store garbage generated during operations

#Creating a temporary directory
ROOT_PATH=$(pwd)
DIR_TMP_PATH="${ROOT_PATH}/temp"

#Delete the old directory and create a temporary directory
rm -rf $DIR_TMP_PATH
mkdir $DIR_TMP_PATH
Copy the code

Step 2: Decompress the target iPA

Decompress the ipA package directory that needs to be re-signed to a temporary file

#Obtains the iPA address from the parameters entered by the user
PARAM_IPA_PATH=$1

#Unzip to a temporary directory
unzip -d $DIR_TMP_PATH $PARAM_IPA_PATH
Copy the code

Step 3: Encapsulate and re-sign the signature

The resignature process is the same for both host and extended applications, and we encapsulate it as a method

#Extract the full PList file from the description file_getPlistFile(){ local _path=$1 local _name=$2 local originMobileprovisionPath="${_path}/embedded.mobileprovision" local  tempEntitle="${DIR_ENTITLEMENTS_TMP_PATH}/${_name}_temp.plist" local entitle="${DIR_ENTITLEMENTS_TMP_PATH}/${_name}.plist" security cms -D -i "$originMobileprovisionPath" > "${tempEntitle}"  #Extraction of Entitlements field
  /usr/libexec/PlistBuddy -x -c 'Print:Entitlements' $tempEntitle > $entitle
}

#Re-signature extension application
reSign(){
  local _path=$1
  local _appexName=$2
  local _tmpMbArray=(${_appexName/./ })
  local _tmpMbName=${_tmpMbArray[0]}

  #Replace the old description file with the new onelocal _mbPath="${_path}/embedded.mobileprovision"; rm -rf _mbPath for index in $(seq 0 ${#PARAM_APPEXMOBILEPROVISION[@]}) do local appexMb=${PARAM_APPEXMOBILEPROVISION[index]} local _tmpStrArray=(${appexMb//// }) local last=${#_tmpStrArray[@]} ((last-=1)) if [ $last -ge 0 ] then local _newAppexMb=${_tmpStrArray[last]} if [[ $_newAppexMb =~ $_tmpMbName ]]; Then # Copy new file to target directory cp $appexMb $_mbPath break fi fi done _getPlistFile $_path $_tmpMbName local _plistPath="${DIR_ENTITLEMENTS_TMP_PATH}/${_tmpMbName}.plist"; echo $PARAM_DEVELOPTEAM echo $_plistPath echo $_path codesign -f -s "${PARAM_DEVELOPTEAM}" --entitlements "${_plistPath}" "${_path}" }Copy the code

Step 4: Recursively iterate through all directories

We need to judge all the folders and re-sign them

#Iterate through the directory recursivelyrecursivePath(){ local _path=$1; for item in $(ls "$_path") do local subPath="${_path}/${item}"; if [[ ${item} =~ '.appex' ]]; Then # reSign "${subPath}" $item else if [-d "$subPath"]; then recursivePath $subPath fi fi done }
#The host application is re-signed. Procedure"Host application description file path" "Host application root"Copy the code

Step 5: Pack a new iPA package

After the re-signing is complete, our new directory is repackaged.

"Zip -r" new.ipa "./Payload mv./ new.ipa "output directory"Copy the code

Step 6: Delete junk files

When all is done, we can delete the junk file and our re-signing operation is complete.

#Remove junk files
rm -rf $DIR_TMP_PATH
Copy the code

extends

  • The reason why we need to design Shell script is that it is convenient to connect with Jenkins and other platforms. We can use script to make timing judgment on the server and inform the developer one month before the application expires. In this way, the developer only needs to upload a new description file one month in advance, and the system will automatically complete the update.

  • PlistBuddy can be used to design more personalized functions, such as the version number, APP name and so on.

Problem complement

Later in the survey, I found that there is wrong information, mainly in the signature above, TeamName parameters will be selected by default expiration time longer in the current system key string developer certificate, if the current system there are two same developer certificate, then there will be a signature failure occurs, so we need to provide the user can select operation.

Enter it on the current PCsecurity find-identity -v -p codesigningCommand to query the currently available certificates

lichXXXX:~ XXXX$ security find-identity -v -p codesigning 1) 6E8C2BD93EC549822A2E435E7ABC9D56921E950E "iPhone Developer:  XX X (XXXXXX)" 2) 4A7FCBA4774460D8A233493FB702E8F68E532C1F "iPhone Distribution: Jiangsu XXXX XXXX XXXX co., Ltd." 3) 055299883D1C6085F607E048AF95A327F41E92FA "iPhone Distribution: Jiangsu XXXX XXXX XXXX co., Ltd." 4) A2813971EAB75B20825BF69A0BA38AB132F13058 "Mac Developer: XX X (XXXXXX)" 5) C50A86CB267ACA13D874F7F8B689852D539BB2D2 "Mac Developer: [email protected] (9LM3QQV38R)" 6) A90B1137BD902385FA461408304C5FCE1FFC006B "iPhone Developer: [email protected] (9LM3QQV38R)" 7) BB273AD0F9C13E70718879656C68901C2F2C99C0 "Apple Development: XX X (XXXXXX)" 8) 5FFEAA884F4DC2DBF9B16C536FA1841F8056602B "Apple Development: [email protected] (9LM3QQV38R)" 8 valid identities foundCopy the code

If there are two identical developer certificates in the current system, you should specify identity to sign the certificate, instead of simply using TeamName to sign the certificate, otherwise the signature will fail.

Codesign -f -s "certificate of the Identify (e.g. 055299883 d1c6085f607e048af95a327f41e92fa)" - entitlements "entitlements. Plist information path" directory "signature"Copy the code

Check whether the description file matches the certificate

Print the Plist information for “new description file” and get the string under the DeveloperCertificates field

Enter the following command in control to print the description file information:

Security CMS -d -i Specifies the path to the new description fileCopy the code

2 Create a test.cer file and copy the following content to it

-----BEGIN CERTIFICATE----- copy the contents between <data></data> in the DeveloperCertificates field to -----END CERTIFICATE-----Copy the code

3 Right-click the “test.cer” file and click Quick View

Viewing serial number

4 Open the System keychain and search for duplicate certificate information

5 Click “Show Introduction” one by one to find the certificate whose serial number is consistent with the description file

6 After finding the correct certificate, slide down to find the SHA-1 fingerprint value

7 Find the certificate with the sha-1 value that matches the description file

Github open source project address

Github.com/iamlion/3To…