Skip to content

Instantly share code, notes, and snippets.

@ronsims2
Last active October 14, 2023 12:34
Show Gist options
  • Save ronsims2/1b7a8b9e15898f9406788988106b2f78 to your computer and use it in GitHub Desktop.
Save ronsims2/1b7a8b9e15898f9406788988106b2f78 to your computer and use it in GitHub Desktop.
A script that will confirm if a specified IPA file was signed with the specified certificate.

Verify an IPA's Signing Certificate

Example :

python ipa_cert_checker.py /Users/janedoe/Documents/Foobar.ipa /Users/janedoe/Documents/barfoo.cer

If any matching certs are found, the script will print something similar to:

Certificate (1) beginning: XCVBNM... matches the specified certificate: /Users/janedoe/Documents/barfoo.cer
import subprocess
import sys
import zipfile
import bs4
import base64
if len(sys.argv) != 3:
print('Invalid number of arguments.')
exit(1)
ipa = sys.argv[1]
app_name = ipa.split('/')[-1].split('.')[0]
cert = sys.argv[2]
workspace = '/'.join(sys.argv[1].split('/')[0:-1])
provfile = workspace + '/Payload/' + app_name + '.app/embedded.mobileprovision'
# Unzip the IPA file
with zipfile.ZipFile(ipa, 'r') as ipa_file:
ipa_file.extractall(workspace)
get_prov = subprocess.Popen(['security', 'cms', '-Di', provfile],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
provxml = ''.join(map(lambda x: str(x, 'utf-8'), get_prov.stdout.readlines()))
def base64ify(fn):
with open(fn, 'rb') as f:
return str(base64.b64encode(f.read()), 'utf-8')
# Parse doc to get cert base64 string
soup = bs4.BeautifulSoup(provxml, 'html.parser')
certs = None
exp_date = None
for k in soup('key'):
if k.string == 'DeveloperCertificates':
certs = [x.string for x in k.findNext('array').findAll('data')]
if k.string == 'ExpirationDate':
exp_date = k.findNext('date').string
# Decode cert and compare to specified cert
refcert = base64ify(cert)
for i, cer in enumerate(certs):
if cer == refcert:
print('Certificate (' + str(i + 1) + ') beginning: ' + cer[0: 9] + '... matches the specified certificate: ' + cert)
if exp_date is not None:
print('This provisioning profile expires on: ' + exp_date)
else:
print('the provisioning profiles expiration date could not be parsed.')
print('The cert checker has finished.')
beautifulsoup4==4.7.1
certifi==2019.3.9
chardet==3.0.4
soupsieve==1.8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment