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 existsappex
Application, if any, is required for eachappex
The 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:
- Extract the target
ipa
Package to temporary directory - Will be applied under
embedded.mobileprovision
Replace with the new description file - Convert the new description file to
info.plist
File to temporary directory - After operation from above
info.plist
To extractTeamName
.Entitlements
information - Finally, the core operation of re-signature is used to re-sign the directory
- The above process of the first
2
.3
.4
.5
Step, ifappex
If the application exists, perform the operation again. If the application does not exist, do not perform the operation - After signing, use
zip
Command to repackage the application intoipa
file - 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 codesigning
Command 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…