iOS重簽名

蘋(píng)果IPA包的重簽名可以解決跟換一個(gè)包名、logo和IP地址后進(jìn)行重新打包的工作,也避免了因?yàn)槿藶樵蛐薷拇a后忘記處理而導(dǎo)致打出的包無(wú)法使用的問(wèn)題。目前市面上有的超級(jí)app或者蒲公英上宣傳的企業(yè)簽名所用到的就是重簽名技術(shù)。

iOS簽名機(jī)制

先來(lái)看一下數(shù)字簽名的圖


數(shù)字簽名

蘋(píng)果的簽名機(jī)制如果簡(jiǎn)化,那也就是數(shù)字簽名的流程。圖的上半部分就是簽名的過(guò)程,下半部分就是用戶安裝應(yīng)用驗(yàn)證的過(guò)程。
蘋(píng)果為了控制應(yīng)用的安裝和發(fā)布,除了公私鑰對(duì),還增加了Provisioning Profile(包含了APP ID、手機(jī)UDID列表、配置的功能權(quán)限信息表Entitlements以及證書(shū)),驗(yàn)證的流程也增加了好多層級(jí):

  • 先用公鑰驗(yàn)證provisioning Profile 的簽名和證書(shū)的簽名;
  • 認(rèn)證通過(guò)后,再使用證書(shū)內(nèi)的公鑰驗(yàn)證APP的簽名,APP ID和Entitlements驗(yàn)證APP,手機(jī)UDID列表驗(yàn)證手機(jī)是否包含在列表內(nèi);
  • 所有的驗(yàn)證通過(guò)后用戶才能使用。


    蘋(píng)果簽名

IPA包的分析

IPA包解壓后是Payload文件夾,然后顯示文件夾內(nèi)的包內(nèi)容,可以發(fā)現(xiàn)(企業(yè)證書(shū)打的包)包內(nèi)有一個(gè)_CodeSignature文件夾和.mobileprovision文件還有一些已經(jīng)加密后的文件。其實(shí)_CodeSignature就是APP的簽名文件,哪些已經(jīng)加密的文件中也保存了APP的簽名文件。如果有framework,它的文件內(nèi)容和主文件下的差不多。

重簽名

需要使用到的文件:

  • 開(kāi)發(fā)者證書(shū)
  • 配置文件(entitlements)
  • Provisioning Profile文件(embedded.mobileprovision)
  • APP

步驟

  1. 找到開(kāi)發(fā)者證書(shū),可以在keychain我的證書(shū)中查找,找到證書(shū)后右鍵選擇顯示簡(jiǎn)介,拉到最底下選擇SHA-1設(shè)置為常量,在重簽名的時(shí)候可以通過(guò)這個(gè)哈希值找到對(duì)應(yīng)的證書(shū)。
CERT_FILE = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1. 使用embedded.mobileprovision文件生成entitlements.plist文件:
def gen_entitlements(out_file_name):
    os.system('security cms -D -i "%s" > entitlement_full.plist ' % (get_mobile_provision_file()))
    os.system('/usr/libexec/PlistBuddy -x -c \'Print:Entitlements\' entitlement_full.plist > "%s" ' % (out_file_name))
  1. 解壓APP的IPA包
def unzip_app(original_ipa):
    os.system('unzip -qo ./%s -d ./' % (original_ipa))
    print('unzip_app %s done!' % (original_ipa))
  1. 移除XX.app文件夾下所有_CodeSignature包括frameworks里面的
def del_code_signature():
    os.system("rm -rf ./Payload/iVMS-7880.app/_CodeSignature")
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('rm -rf ./Payload/iVMS-7880.app/"%s"/_CodeSignature' % (file))
    print('del_code_signature done!')
  1. 把準(zhǔn)備好的embedded.mobileprovision復(fù)制到XX.app文件夾下
def replace_provision_file():
    for file in os.listdir("./"):
        if os.path.splitext(file)[1] == '.mobileprovision':
            os.system('cp "%s" ./Payload/iVMS-7880.app/embedded.mobileprovision' % (file))
  1. 重簽名framework
def resign_framework():
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/frameworks/"%s"' % (file)))
            print('resign_framework "%s" done!' % (file))
  1. 重簽名app執(zhí)行文件
def resign_app():
    os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/iVMS-7880'))
    print('resign_app done!')
  1. 壓縮Payload文件,重命名壓縮文件為XX.ipa
def zip_app(f_ipa):
    os.system('zip -r %s ./Payload' % (f_ipa))
    print('zip_app done!')

到此就會(huì)有一個(gè)新的IPA包生成了,可以通過(guò)手機(jī)助手或者上傳平臺(tái)進(jìn)行手機(jī)安裝驗(yàn)證。

代碼

#!/usr/bin/python
# -*- coding: utf-8 -*- 

import os
import sys
import json

CERT_FILE = '6BF988FC0D4993B3D48810E4D67419A2B1E81DC1'

def get_mobile_provision_file():
    file_path = ""
    for file in os.listdir("./"):
        if os.path.splitext(file)[1] == '.mobileprovision':
            file_path = os.path.join(os.getcwd(),"%s" % (file))
    return file_path

def reset_bundle_identifier(bundle_identifier):
    os.system('/usr/libexec/PlistBuddy -c \'Set:CFBundleIdentifier "%s"\' Payload/iVMS-7880.app/Info.plist' % (bundle_identifier))

def reset_bundle_version(build):
    os.system('/usr/libexec/PlistBuddy -c \'Set:CFBundleVersion "%s"\' Payload/iVMS-7880.app/Info.plist' % (build))

def unzip_app(original_ipa):
    os.system('unzip -qo ./%s -d ./' % (original_ipa))
    print('unzip_app %s done!' % (original_ipa))

def del_code_signature():
    os.system("rm -rf ./Payload/iVMS-7880.app/_CodeSignature")
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('rm -rf ./Payload/iVMS-7880.app/"%s"/_CodeSignature' % (file))
    print('del_code_signature done!')

def resign_app():
    os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/iVMS-7880'))
    print('resign_app done!')

def resign_framework():
    for file in os.listdir("./Payload/iVMS-7880.app/Frameworks"):
        if os.path.splitext(file)[1] == '.framework':
            os.system('/usr/bin/codesign --force --sign "%s" --entitlements "%s" "%s"' % (CERT_FILE, './entitlement.plist', './Payload/iVMS-7880.app/frameworks/"%s"' % (file)))
            print('resign_framework "%s" done!' % (file))

def zip_app(f_ipa):
    os.system('zip -r %s ./Payload' % (f_ipa))
    print('zip_app done!')

def del_payload():
    os.system('rm -r ./Payload')

def gen_entitlements(out_file_name):
    os.system('security cms -D -i "%s" > entitlement_full.plist ' % (get_mobile_provision_file()))
    os.system('/usr/libexec/PlistBuddy -x -c \'Print:Entitlements\' entitlement_full.plist > "%s" ' % (out_file_name))


def rep_emb_file():
    os.system('cp "%s" ./Payload/iVMS-7880/embedded.mobileprovision' % (get_mobile_provision_file()))

def replace_provision_file():
    for file in os.listdir("./"):
        if os.path.splitext(file)[1] == '.mobileprovision':
            os.system('cp "%s" ./Payload/iVMS-7880.app/embedded.mobileprovision' % (file))


if __name__ == '__main__':
    gen_entitlements("entitlement.plist")

    original_ipa = input("original_ipa:")
    unzip_app(original_ipa)

    bundle_identifier = input("bundle_identifier:")
    reset_bundle_identifier(bundle_identifier)

    build = input("build_version:")
    reset_bundle_version(build)

    del_code_signature()
    replace_provision_file()
    resign_framework()
    resign_app()
    newName = input("newName:")
    zip_app(newName)
    del_payload()

復(fù)制代碼存儲(chǔ)為python文件,之前準(zhǔn)備的文件和該文件需要在同一個(gè)根目錄下,然后在終端中執(zhí)行該文件,輸入對(duì)應(yīng)信息后就可以得到新的IPA包。輸入的信息都為字符串需要用引號(hào),否則將會(huì)沒(méi)有效果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近有朋友需要幫忙用公司企業(yè)證書(shū)打包企業(yè)內(nèi)側(cè)應(yīng)用,經(jīng)過(guò)本人搜集、采坑,目前最簡(jiǎn)單、可靠地重簽名解決方案(企業(yè)證書(shū)可...
    歌白尼閱讀 9,336評(píng)論 17 16
  • 一.理解iOS簽名機(jī)制 網(wǎng)上有很多資料,這里不展開(kāi)細(xì)說(shuō),重點(diǎn)參考這三篇文章: https://www.objccn...
    huig游影閱讀 1,094評(píng)論 0 1
  • 一.理解iOS簽名機(jī)制 網(wǎng)上有很多資料,這里不展開(kāi)細(xì)說(shuō),重點(diǎn)參考這三篇文章: https://www.objccn...
    huig游影閱讀 1,279評(píng)論 0 0
  • 中秋之夜,望著圓圓的月亮,即使遠(yuǎn)在他鄉(xiāng)異客,也會(huì)感到節(jié)日的歡樂(lè)。 每年到了八月十五那天,皎潔的月光像在地上...
    馮瑛蕊閱讀 600評(píng)論 0 0
  • 顧客在試穿時(shí),我們要根據(jù)顧客的需求來(lái)推薦適合的款式,并為顧客做好搭配。同時(shí),在完成任務(wù)的同時(shí),我們要制定出相...
    濰坊泰華DDM店劉云閱讀 151評(píng)論 0 0

友情鏈接更多精彩內(nèi)容