├── .gitignore ├── CONDUCT.md ├── INSTALL.sh ├── LICENSE.txt ├── MANIFEST.in ├── PREREQUISITES.rst ├── README.rst ├── apple ├── README.rst ├── provisions.py └── provisions.sh ├── bin ├── isign ├── isign_export_creds.sh ├── isign_guess_mobileprovision.sh ├── make_seal ├── multisign └── pprint_codesig ├── dev ├── requirements.txt └── setup.sh ├── docs ├── applecerts.rst ├── codedirectory.rst ├── credentials.rst └── speed.rst ├── isign ├── __init__.py ├── apple_credentials │ ├── README.rst │ └── applecerts.pem ├── archive.py ├── bundle.py ├── code_resources.py ├── code_resources_template.xml ├── codesig.py ├── exceptions.py ├── isign.py ├── macho.py ├── macho_cs.py ├── makesig.py ├── multisign.py ├── signable.py ├── signer.py └── utils.py ├── jenkins.sh ├── run_tests.sh ├── setup.cfg ├── setup.py ├── tests ├── NotAnApp.ipa ├── NotAnApp.txt ├── NotAnAppDir │ └── README.md ├── README.md ├── Test.app.codesig.construct.txt ├── Test.app.zip ├── Test.app │ ├── Assets.car │ ├── Base.lproj │ │ ├── LaunchScreen.storyboardc │ │ │ ├── 01J-lp-oVM-view-Ze5-6b-2t3.nib │ │ │ ├── Info.plist │ │ │ └── UIViewController-01J-lp-oVM.nib │ │ └── Main.storyboardc │ │ │ ├── 8rJ-Kc-sve-view-QS5-Rx-YEW.nib │ │ │ ├── 9pv-A4-QxB-view-tsR-hK-woN.nib │ │ │ ├── Info.plist │ │ │ └── UITabBarController-49e-Tb-3d3.nib │ ├── Frameworks │ │ ├── libswiftContacts.dylib │ │ ├── libswiftCore.dylib │ │ ├── libswiftCoreGraphics.dylib │ │ ├── libswiftCoreImage.dylib │ │ ├── libswiftDarwin.dylib │ │ ├── libswiftDispatch.dylib │ │ ├── libswiftFoundation.dylib │ │ ├── libswiftObjectiveC.dylib │ │ └── libswiftUIKit.dylib │ ├── Info.plist │ ├── PkgInfo │ ├── _CodeSignature │ │ └── CodeResources │ ├── build.sh │ ├── isignTestApp │ ├── isignTestApp.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcuserdata │ │ │ │ └── neilk.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── neilk.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── isignTestApp.xcscheme │ │ │ └── xcschememanagement.plist │ ├── isignTestAppTests │ │ ├── Info.plist │ │ └── isignTestAppTests.swift │ └── isignTestAppUITests │ │ ├── Info.plist │ │ └── isignTestAppUITests.swift ├── Test.ipa ├── TestSimulator.app.zip ├── TestWithFrameworks.ipa ├── Test_unsigned_fat.app │ ├── Assets.car │ ├── Base.lproj │ │ ├── LaunchScreen.storyboardc │ │ │ ├── 01J-lp-oVM-view-Ze5-6b-2t3.nib │ │ │ ├── Info.plist │ │ │ └── UIViewController-01J-lp-oVM.nib │ │ └── Main.storyboardc │ │ │ ├── 8rJ-Kc-sve-view-QS5-Rx-YEW.nib │ │ │ ├── 9pv-A4-QxB-view-tsR-hK-woN.nib │ │ │ ├── Info.plist │ │ │ └── UITabBarController-49e-Tb-3d3.nib │ ├── Frameworks │ │ ├── libswiftContacts.dylib │ │ ├── libswiftCore.dylib │ │ ├── libswiftCoreGraphics.dylib │ │ ├── libswiftCoreImage.dylib │ │ ├── libswiftDarwin.dylib │ │ ├── libswiftDispatch.dylib │ │ ├── libswiftFoundation.dylib │ │ ├── libswiftObjectiveC.dylib │ │ └── libswiftUIKit.dylib │ ├── Info.plist │ ├── PkgInfo │ ├── build.sh │ ├── isignTestApp │ ├── isignTestApp.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcuserdata │ │ │ │ └── neilk.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── neilk.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── isignTestApp.xcscheme │ │ │ └── xcschememanagement.plist │ ├── isignTestAppTests │ │ ├── Info.plist │ │ └── isignTestAppTests.swift │ └── isignTestAppUITests │ │ ├── Info.plist │ │ └── isignTestAppUITests.swift ├── Test_unsigned_thin.app │ ├── Assets.car │ ├── Base.lproj │ │ ├── LaunchScreen.storyboardc │ │ │ ├── 01J-lp-oVM-view-Ze5-6b-2t3.nib │ │ │ ├── Info.plist │ │ │ └── UIViewController-01J-lp-oVM.nib │ │ └── Main.storyboardc │ │ │ ├── 8rJ-Kc-sve-view-QS5-Rx-YEW.nib │ │ │ ├── 9pv-A4-QxB-view-tsR-hK-woN.nib │ │ │ ├── Info.plist │ │ │ └── UITabBarController-49e-Tb-3d3.nib │ ├── Frameworks │ │ ├── libswiftContacts.dylib │ │ ├── libswiftCore.dylib │ │ ├── libswiftCoreGraphics.dylib │ │ ├── libswiftCoreImage.dylib │ │ ├── libswiftDarwin.dylib │ │ ├── libswiftDispatch.dylib │ │ ├── libswiftFoundation.dylib │ │ ├── libswiftObjectiveC.dylib │ │ └── libswiftUIKit.dylib │ ├── Info.plist │ ├── PkgInfo │ ├── build.sh │ ├── isignTestApp │ ├── isignTestApp.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcuserdata │ │ │ │ └── neilk.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── neilk.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── isignTestApp.xcscheme │ │ │ └── xcschememanagement.plist │ ├── isignTestAppTests │ │ ├── Info.plist │ │ └── isignTestAppTests.swift │ └── isignTestAppUITests │ │ ├── Info.plist │ │ └── isignTestAppUITests.swift ├── bad_openssl ├── credentials │ ├── README.rst │ ├── makeFakePprof.sh │ ├── test.cert.pem │ ├── test.key.pem │ ├── test.mobileprovision │ └── test.mobileprovision.plist ├── credentials_std_names │ ├── README.rst │ ├── certificate.pem │ ├── isign.mobileprovision │ └── key.pem ├── credentials_std_names_2 │ ├── README.rst │ ├── certificate.pem │ ├── isign.mobileprovision │ └── key.pem ├── generate_codesig_construct_txt.py ├── isignTestApp │ ├── .gitignore │ ├── README.md │ ├── build.sh │ ├── exportOptions.plist │ ├── isignTestApp.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcuserdata │ │ │ │ └── neilk.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── neilk.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── isignTestApp.xcscheme │ │ │ └── xcschememanagement.plist │ ├── isignTestApp │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── first.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── first.pdf │ │ │ └── second.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── second.pdf │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── FirstViewController.swift │ │ ├── Info.plist │ │ └── SecondViewController.swift │ ├── isignTestAppTests │ │ ├── Info.plist │ │ └── isignTestAppTests.swift │ └── isignTestAppUITests │ │ ├── Info.plist │ │ └── isignTestAppUITests.swift ├── isignTestAppWithFrameworks │ ├── .gitignore │ ├── Podfile │ ├── Podfile.lock │ ├── README.md │ ├── build.sh │ ├── exportOptions.plist │ ├── isignTestApp.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcuserdata │ │ │ │ └── neilk.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── neilk.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── isignTestApp.xcscheme │ │ │ └── xcschememanagement.plist │ ├── isignTestApp.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── neilk.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ ├── isignTestApp │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── first.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── first.pdf │ │ │ └── second.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── second.pdf │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── FirstViewController.swift │ │ ├── Info.plist │ │ └── SecondViewController.swift │ ├── isignTestAppTests │ │ ├── Info.plist │ │ └── isignTestAppTests.swift │ └── isignTestAppUITests │ │ ├── Info.plist │ │ └── isignTestAppUITests.swift ├── isign_base_test.py ├── monitor_temp_file.py ├── sample-entitlements.plist ├── test_archive.py ├── test_creds_dir.py ├── test_entitlements.py ├── test_helpers.py ├── test_multisign.py ├── test_parsing.py ├── test_public_interface.py ├── test_sig.py ├── test_versioning.py └── test_versus_apple.py └── version.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # generic 2 | *~ 3 | *# 4 | *._* 5 | *.log 6 | *.log.* 7 | *.pid 8 | 9 | # apple 10 | .DS_Store 11 | *~.nib 12 | 13 | # Byte-compiled / optimized / DLL files 14 | __pycache__/ 15 | *.py[cod] 16 | 17 | # C extensions 18 | *.so 19 | 20 | # Distribution / packaging 21 | .Python 22 | env/ 23 | build/ 24 | develop-eggs/ 25 | dist/ 26 | downloads/ 27 | eggs/ 28 | .eggs/ 29 | lib/ 30 | lib64/ 31 | parts/ 32 | sdist/ 33 | var/ 34 | *.egg-info/ 35 | .installed.cfg 36 | *.egg 37 | 38 | # PyInstaller 39 | # Usually these files are written by a python script from a template 40 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 41 | *.manifest 42 | *.spec 43 | 44 | # Installer logs 45 | pip-log.txt 46 | pip-delete-this-directory.txt 47 | 48 | # Unit test / coverage reports 49 | htmlcov/ 50 | .tox/ 51 | .coverage 52 | .cache 53 | nosetests.xml 54 | coverage.xml 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Sphinx documentation 61 | docs/_build/ 62 | 63 | # PyBuilder 64 | target/ 65 | 66 | # Development 67 | .*.sw[po] 68 | *.sublime-project 69 | *.sublime-workspace 70 | .project 71 | .pydevproject 72 | .ropeproject 73 | *.sass-cache 74 | .aws.env 75 | .codeintel 76 | .coverage 77 | .noseids 78 | .semantic.cache 79 | .settings 80 | .idea 81 | .realsync 82 | *.tm_build_errors 83 | tmtags 84 | 85 | # iresign version 86 | isign/version.json 87 | 88 | # iresign temp files 89 | Entitlements.plist 90 | stage 91 | out.app 92 | out.ipa 93 | 94 | # all credentials 95 | *.pem 96 | *.p12 97 | *.mobileprovision 98 | # except these 99 | !apple_credentials/applecerts.pem 100 | !tests/credentials/test.key.pem 101 | !tests/credentials/test.cert.pem 102 | !tests/credentials/test.mobileprovision 103 | !tests/credentials_std_names/certificate.pem 104 | !tests/credentials_std_names/isign.mobileprovision 105 | !tests/credentials_std_names_2/key.pem 106 | !tests/credentials_std_names_2/certificate.pem 107 | !tests/credentials_std_names_2/isign.mobileprovision 108 | -------------------------------------------------------------------------------- /CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | ### What is this code of conduct for? 4 | 5 | `isign` is a piece of technology, but **the core of the `isign` community is the people in it**. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, socioeconomic status, religion (or lack thereof), or other marginalized aspect of comunity members. We expect all members of the `isign` community to abide by this Code of Conduct whenever interacting in `isign` venues (pull requests, GitHub issues, 1-1 or group chat, meetups, conferences, etc...) 6 | 7 | ### Examples of inappropriate behavior 8 | 9 | Because we come from a variety of backgrounds, we don't want to assume that everyone has the same assumptions about what is and isn't appropriate. Here are some examples of inappropriate behavior that are incompatible with our community's ethos: 10 | 11 | * Spamming, trolling, intentionally disrupting conversations, or irrelevant solicitation or advertisement 12 | * Making demeaning or discriminatory comments 13 | * Making negative assumptions about someone's background, abilities, or intentions 14 | * Harassing or stalking individuals (online or in person) 15 | * Giving someone unwelcome sexual attention or making unwelcome physical contact (in the case of an IRL event) 16 | * Sharing sexual images or using sexually explicit language 17 | 18 | In general: treat others how you would like to be treated, were you in their place. Don't be a jerk. _Do_ ask questions. _Do_ keep conflicts productively focused on technical issues. _Do_ think before you speak; remember that what is perceived as a funny witticism in your group of friends might be hurtful or reinforce hurtful stereotypes in the context of our diverse online community. _Do_ remember that we are all people, not robots, and all equally deserving of sensitivity and respect. (If and when robots join our community, let's treat them with respect too!) 19 | 20 | ### What will organizers do about inappropriate behavior? 21 | 22 | If we notice you doing or saying something inappropriate, an organizer will explain why it's inappropriate and ask you to stop. We won't demonize or vilify you. But please do stop the inappropriate behavior so we can get back to writing and discussing code in a safe environment. If you have philosophical disagreements about what's actually inappropriate, please take them to a separate public or private conversation with an `isign` maintainer so we don't turn pull requests into an ethics debate. 23 | 24 | If you keep doing unacceptable things, we'll likely ban you, report you to GitHub, or take other appropriate action. 25 | 26 | ### What if I see or am subject to what feels like inappropriate behavior? 27 | 28 | Let us know! Please notify a community organizer as soon as possible. Full contact information is listed in the [Contact Info](#contact-info) section of this document. All communications will be kept strictly confidential, unless otherwise required by law. No issue will be considered too inconsequential or unimportant for us to have a conversation about. 29 | 30 | ### Contact Info 31 | 32 | If you need to report an incident, please contact any of the following organizers directly: 33 | 34 | * Neil Kandalgaonkar [email](mailto:neilk@neilk.net) [twitter](https://twitter.com/flipzagging/) 35 | * Jonathan Lipps [email](mailto:jlipps@saucelabs.com) [twitter](https://twitter.com/jlipps) 36 | 37 | ### Credit, License, and Attribution 38 | 39 | This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). 40 | 41 | It's inspired among other things by: 42 | * [Citizen Code of Conduct](http://citizencodeofconduct.org/) 43 | * [npmjs](https://www.npmjs.com/policies/conduct) 44 | * [Geek Feminism](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy) 45 | * [Ashe Dryden](http://www.ashedryden.com/blog/codes-of-conduct-101-faq) 46 | * [Model View Culture](https://modelviewculture.com/issues/events) 47 | * [Open Source & Feelings](http://osfeels.com/conduct). 48 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2015 Sauce Labs 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include isign/version.json 2 | include isign/apple_credentials/applecerts.pem 3 | include isign/code_resources_template.xml 4 | -------------------------------------------------------------------------------- /PREREQUISITES.rst: -------------------------------------------------------------------------------- 1 | Prerequisites 2 | ============= 3 | 4 | For Linux or Mac platforms, the ``INSTALL.sh`` script should take care of 5 | everything you need. 6 | 7 | If you don't want to run that script on the machine where you want to re-sign apps, 8 | this will explain what you need. 9 | 10 | First, on the machine where you're going to re-sign apps, ensure 11 | `openssl `__ is at version 1.0.1 or better, like 12 | this: 13 | 14 | .. code:: 15 | 16 | $ openssl version 17 | OpenSSL 1.0.1 14 Mar 2012 18 | 19 | If that looks okay, you can probably install. If not: 20 | 21 | .. _Linux: 22 | 23 | Linux 24 | ~~~~~ 25 | 26 | You can probably easily update this with your package manager, such as 27 | ``apt-get upgrade openssl``. 28 | 29 | .. _Mac OS X: 30 | 31 | Mac OS X 32 | ~~~~~~~~ 33 | 34 | With OS X 10.11 "El Capitan", Apple stopped shipping some programs, libraries, and 35 | headers that we'll need. You can use `homebrew `__ to install them: 36 | 37 | .. code:: 38 | 39 | $ brew install openssl libffi 40 | 41 | You will also have to put ``brew``'s openssl into your path somehow, probably like this: 42 | 43 | .. code:: 44 | 45 | $ brew list openssl 46 | ... 47 | /usr/local/Cellar/openssl/1.0.2e/bin/openssl <-- you want this 48 | ... 49 | 50 | $ ln -s /usr/local/Cellar/openssl/1.0.2e/bin/openssl /usr/local/bin/openssl 51 | 52 | If you really don't want to alter the default ``openssl``, you can put the path to brew's 53 | ``openssl`` in an environment variable, ``$OPENSSL``, e.g. 54 | 55 | .. code:: 56 | 57 | $ export OPENSSL=/usr/local/Cellar/openssl/1.0.2e/bin/openssl 58 | 59 | If ``isign`` sees that, it will use that for its ``openssl`` instead. 60 | 61 | Anyway, no matter how you install the binary, to complete the installation of ``isign`` 62 | you need to add some library paths to your environment. The procedure will 63 | look something like this. 64 | 65 | .. code:: 66 | 67 | $ brew info openssl 68 | ... 69 | build variables: 70 | 71 | LDFLAGS: -L/usr/local/opt/openssl/lib 72 | CPPFLAGS: -I/usr/local/opt/openssl/include 73 | 74 | $ brew info libffi 75 | ... 76 | build variables: 77 | 78 | LDFLAGS: -L/usr/local/opt/libffi/lib 79 | 80 | Then, take the flags from above, and put them into appropriate environment 81 | variables: 82 | 83 | .. code:: 84 | 85 | $ export LDFLAGS="-L/usr/local/opt/openssl/lib -L/usr/local/opt/libffi/lib" 86 | $ export CPPFLAGS="-I/usr/local/opt/openssl/include" 87 | 88 | Finally, be aware that the ``python`` that ships with Mac OS X doesn't have the package 89 | manager ``pip``. You can probably use ``easy_install`` instead of ``pip``. Or, you can get a more 90 | up-to-date python with ``brew install python``. 91 | 92 | Now you're probably ready to install ``isign``. A simple ``pip install isign`` should succeed. 93 | -------------------------------------------------------------------------------- /apple/README.rst: -------------------------------------------------------------------------------- 1 | These scripts will re-provision (aka resign, code sign, etc) an app, 2 | using Apple tools. The isign tools emulate what these do, on Linux. 3 | 4 | provisions.sh is the original script that Mike Han (@mikehan) wrote. 5 | 6 | provisions.py is a python port. 7 | -------------------------------------------------------------------------------- /apple/provisions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage() { 4 | echo "./provisions -p [PATH_TO_NEW_PROVISIONING_PROFILE] -c \"CERT NAME: MUST BE IN KEYCHAIN\" ipa_file" 5 | exit 6 | } 7 | 8 | while getopts ":p:c:" opt; do 9 | case $opt in 10 | p ) PRO_PROFILE=$OPTARG ;; 11 | c ) CERT_NAME=$OPTARG ;; 12 | /? ) usage 13 | esac 14 | done 15 | 16 | shift $(($OPTIND - 1)) 17 | if [[ -z "$@" ]]; then 18 | usage 19 | else 20 | APP=$@ 21 | fi 22 | 23 | verify_args() { 24 | if [[ ! -e $APP ]]; then 25 | echo "$APP does not exist" 26 | exit 1 27 | elif [[ ! -e $PRO_PROFILE ]]; then 28 | echo "$PRO_PROFILE does not exist" 29 | exit 1 30 | elif [[ -z $CERT_NAME ]]; then 31 | echo "Must specify a certificate to use" 32 | exit 1 33 | fi 34 | } 35 | 36 | is_app() { 37 | [[ $APP =~ \.app$ ]] 38 | } 39 | 40 | is_ipa() { 41 | [[ $APP =~ \.ipa$ ]] 42 | } 43 | 44 | setup_dir() { 45 | STAGE_DIR=./stage 46 | ENTITLEMENTS_FILE=$STAGE_DIR/Entitlements.plist 47 | if [[ -e $STAGE_DIR ]]; then 48 | rm -r $STAGE_DIR 49 | fi 50 | mkdir $STAGE_DIR 51 | if is_app; then 52 | cp -r $APP $STAGE_DIR 53 | APP_NAME=$(basename $APP) 54 | PAYLOAD_DIR="" 55 | APP_DIR=$STAGE_DIR/$APP_NAME 56 | elif is_ipa; then 57 | unzip -qu $APP -d $STAGE_DIR 58 | PAYLOAD_DIR=$STAGE_DIR/Payload 59 | APP_DIR=$PAYLOAD_DIR/*.app 60 | else 61 | echo "Must provide either an .app or .ipa file" 62 | exit 1 63 | fi 64 | } 65 | 66 | copy_profile() { 67 | cp "$PRO_PROFILE" $APP_DIR/embedded.mobileprovision 68 | } 69 | 70 | create_entitlements() { 71 | /usr/libexec/PlistBuddy -x -c "print :Entitlements " /dev/stdin <<< $(security cms -D -i ${APP_DIR}/embedded.mobileprovision) > $ENTITLEMENTS_FILE 72 | } 73 | 74 | sign_app() { 75 | if [ -e $APP_DIR/Frameworks ]; then 76 | for dylib in "$APP_DIR/Frameworks/*" 77 | do 78 | echo "signing $dylib" 79 | # entitlements are irrelevant to dylibs 80 | /usr/bin/codesign -f -s "$CERT_NAME" $dylib 81 | done 82 | fi 83 | echo "signing $APP_DIR"; 84 | /usr/bin/codesign -f -s "$CERT_NAME" --entitlements $ENTITLEMENTS_FILE $APP_DIR 2>/dev/null 85 | } 86 | 87 | package_app() { 88 | if is_ipa; then 89 | (cd $STAGE_DIR; zip -qr out.ipa Payload) 90 | echo "Re-provisioned ipa at $STAGE_DIR/out.ipa" 91 | else 92 | echo "Re-provisioned app at $APP_DIR" 93 | fi 94 | } 95 | 96 | verify_args 97 | setup_dir 98 | copy_profile 99 | create_entitlements 100 | sign_app 101 | package_app 102 | -------------------------------------------------------------------------------- /bin/isign_export_creds.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Export a certificate and key from a .p12 file into PEM form, and place 4 | # them where isign expects them to be. 5 | # 6 | # The .p12 file is typically exported from Apple's Keychain Access. 7 | 8 | if [[ $# -eq 0 ]]; then 9 | echo "Usage: $0 exported.p12 [target_directory]" 10 | exit 1; 11 | fi 12 | 13 | p12_path=$1 14 | 15 | if [[ ! -e $p12_path ]]; then 16 | echo "Can't find $p12_path!"; 17 | exit 1; 18 | fi 19 | 20 | target_dir=${2-$HOME/.isign} 21 | 22 | target_cert_path=$target_dir/certificate.pem 23 | target_key_path=$target_dir/key.pem 24 | 25 | chmod 600 $p12_path 26 | 27 | mkdir -p $target_dir 28 | openssl pkcs12 -in $p12_path -out $target_cert_path -clcerts -nokeys 29 | openssl pkcs12 -in $p12_path -out $target_key_path -nocerts -nodes 30 | chmod 600 $target_key_path 31 | 32 | read -p "Done exporting $p12_path. Remove it? [Y/n]:" -n 1 -r 33 | echo 34 | if [[ $REPLY =~ ^[Yy]$ ]]; then 35 | rm $p12_path 36 | fi 37 | echo "Exported credentials from $p12_path to $target_dir" 38 | 39 | 40 | read -p "Find matching provisioning profile? [Y/n]:" -n 1 -r 41 | echo 42 | if [[ $REPLY =~ ^[Yy]$ ]]; then 43 | ./guess_mobileprovision.sh $target_cert_path 44 | fi 45 | -------------------------------------------------------------------------------- /bin/isign_guess_mobileprovision.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # given the filename certificate in PEM form, find potentially matching .mobileprovision files 4 | # in the usual directory on Mac OS X 5 | 6 | PROVISIONING_PROFILE_DIR="$HOME/Library/MobileDevice/Provisioning Profiles" 7 | 8 | cert_path=${1-$HOME/.isign/certificate.pem} 9 | 10 | echo "Looking for provisioning profiles signed with $cert_path..." 11 | 12 | get_cert() { 13 | cert_path=$1 14 | in_certificate=1 15 | certificate='' 16 | while read line; do 17 | if [[ $line =~ 'BEGIN CERTIFICATE' ]]; then 18 | in_certificate=0 19 | continue 20 | fi 21 | if [[ $line =~ 'END CERTIFICATE' ]]; then 22 | in_certificate=1 23 | continue 24 | fi 25 | if [[ $in_certificate -eq 0 ]]; then 26 | # trim leading/trailing whitespace 27 | line="$(echo -e $line | sed -e 's/^[[:space:]]*//' | sed -e 's/[[:space:]]*$//')" 28 | certificate="${certificate}${line}" 29 | fi 30 | done < $cert_path 31 | echo $certificate 32 | } 33 | 34 | target_cert=$(get_cert $cert_path) 35 | find "$PROVISIONING_PROFILE_DIR/mobdev1.mobileprovision" -type f -print0 | while IFS= read -r -d '' mobileprovision; do 36 | # extract the cert from the mobileprovision with `security` 37 | mobileprovision_data=$(security cms -D -i "$mobileprovision") 38 | # PlistBuddy doesn't give array lengths, so we don't know how many certs this mobileprovision might have. Try a few 39 | for i in `seq 0 10`; do 40 | # because Plistbuddy is dumb, we have to use a convoluted shell syntax to read from stdin 41 | # finally base64 it so we can do an easy string comparison 42 | # TODO: can't quite figure out why, but I need to pipe it to base64, can't do that encoding later. 43 | # But this means I can't figure out if the PlistBuddy succeeded or failed, by checking $? 44 | # Have to swallow the error, iterate more times than necessary :( 45 | cert=$(/usr/libexec/PlistBuddy -c "Print :DeveloperCertificates:$i" /dev/stdin <<< $(echo $mobileprovision_data) 2>/dev/null | base64) 46 | # Examine a long prefix (there are some issues with padding & zeroes at the end). 47 | # if first thousand match it is almost certainly a match 48 | if [[ ${cert:0:1000} = ${target_cert:0:1000} ]]; then 49 | echo "\"$mobileprovision\" was signed with this certificate." 50 | fi 51 | done 52 | done 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /bin/make_seal: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from optparse import OptionParser 4 | import isign.code_resources 5 | import logging 6 | 7 | FORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 8 | 9 | 10 | def log_to_stderr(level=logging.INFO): 11 | root = logging.getLogger() 12 | root.setLevel(level) 13 | handler = logging.StreamHandler() 14 | handler.setFormatter(FORMATTER) 15 | root.addHandler(handler) 16 | 17 | 18 | if __name__ == '__main__': 19 | log_to_stderr() 20 | parser = OptionParser() 21 | options, args = parser.parse_args() 22 | source_app, target_dir = args 23 | isign.code_resources.make_seal(source_app, target_dir) 24 | -------------------------------------------------------------------------------- /bin/multisign: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # From a single IPA, generate multiple re-signed IPAs simultaneously. 4 | # Why? Because you might want to distribute an app to a lot of organizations at once, 5 | # or perhaps you need to sign for an enterprise and a local debug deployment all at 6 | # the same time, and you want it to be fast. 7 | 8 | # Depends on the existence of external `zip` and `unzip` programs. 9 | 10 | import argparse 11 | from os.path import abspath, basename, dirname, expanduser, join 12 | from isign.multisign import multisign 13 | import logging 14 | 15 | FORMATTER = logging.Formatter('%(message)s') 16 | log = logging.getLogger(__name__) 17 | 18 | 19 | def log_to_stderr(level=logging.INFO): 20 | root = logging.getLogger() 21 | root.setLevel(level) 22 | handler = logging.StreamHandler() 23 | handler.setFormatter(FORMATTER) 24 | root.addHandler(handler) 25 | 26 | 27 | def absolute_path_argument(path): 28 | return abspath(expanduser(path)) 29 | 30 | 31 | def parse_args(): 32 | parser = argparse.ArgumentParser( 33 | description='From a single IPA, generate multiple re-signed IPAs simultaneously') 34 | parser.add_argument( 35 | '-a', '--app', 36 | dest='app', 37 | required=True, 38 | metavar='', 39 | type=absolute_path_argument, 40 | help='Path to input app' 41 | ) 42 | parser.add_argument( 43 | 'credential_dirs', 44 | nargs='+', 45 | metavar='', 46 | type=absolute_path_argument, 47 | help='Paths to directories containing credentials with standardized names' 48 | ) 49 | parser.add_argument( 50 | '-i', '--info', 51 | dest='info_props', 52 | required=False, 53 | metavar='', 54 | help='List of comma-delimited key=value pairs of Info.plist properties to override' 55 | ) 56 | parser.add_argument( 57 | '-v', '--verbose', 58 | dest='verbose', 59 | action='store_true', 60 | default=False, 61 | required=False, 62 | help='Set logging level to debug.' 63 | ) 64 | return parser.parse_args() 65 | 66 | def get_output_path(original_path, credential_dir): 67 | """ Create some filename based on the credential directory and original path """ 68 | original_name = basename(original_path) 69 | original_dir = dirname(original_path) 70 | resigned_name = basename(credential_dir) + '_' + original_name 71 | return join(original_dir, resigned_name) 72 | 73 | 74 | if __name__ == '__main__': 75 | args = parse_args() 76 | 77 | if args.verbose: 78 | level = logging.DEBUG 79 | else: 80 | level = logging.INFO 81 | log_to_stderr(level) 82 | 83 | # Convert the Info.plist property pairs to a dict format 84 | info_props = None 85 | if args.info_props: 86 | info_props = {} 87 | for arg in args.info_props.split(','): 88 | i = arg.find('=') 89 | if i < 0: 90 | raise Exception('Invalid Info.plist argument: ' + arg) 91 | info_props[arg[0:i]] = arg[i + 1:] 92 | 93 | log.debug('got credential paths: {}'.format(', '.join(args.credential_dirs))) 94 | log.debug('got incoming app: {}'.format(args.app)) 95 | 96 | # ensure basenames are unique 97 | unique_basenames = set([basename(p) for p in args.credential_dirs]) 98 | if len(args.credential_dirs) != len(unique_basenames): 99 | raise Exception('Credential directories do not have unique basenames. ' 100 | 'Cannot name output archives automatically. Sorry!') 101 | 102 | credential_dirs_to_output_paths = {} 103 | for d in args.credential_dirs: 104 | credential_dirs_to_output_paths[d] = get_output_path(args.app, d) 105 | 106 | results = multisign(args.app, credential_dirs_to_output_paths, info_props) 107 | for credentials_dir, resigned_app_path in results: 108 | log.info("resigned with %s to %s", credentials_dir, resigned_app_path) 109 | -------------------------------------------------------------------------------- /bin/pprint_codesig: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import isign.archive 5 | from isign.exceptions import NotSignable 6 | from isign.signable import Executable 7 | import logging 8 | from os.path import abspath, expanduser, isdir 9 | import shutil 10 | 11 | FORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 12 | log = logging.getLogger(__name__) 13 | 14 | 15 | def log_to_stderr(level=logging.INFO): 16 | root = logging.getLogger() 17 | root.setLevel(level) 18 | handler = logging.StreamHandler() 19 | handler.setFormatter(FORMATTER) 20 | root.addHandler(handler) 21 | 22 | 23 | def absolute_path_argument(path): 24 | return abspath(expanduser(path)) 25 | 26 | 27 | def print_codesig(path): 28 | temp_dir = None 29 | try: 30 | archive = isign.archive.archive_factory(path) 31 | (temp_dir, bundle) = appArchive.unarchive_to_temp() 32 | _print_codesig(bundle) 33 | except NotSignable as e: 34 | msg = "Not signable: <{0}> {1}\n".format(path, e) 35 | log.error(msg) 36 | raise 37 | finally: 38 | if temp_dir is not None and isdir(temp_dir): 39 | shutil.rmtree(temp_dir) 40 | 41 | 42 | def _print_codesig(bundle): 43 | executable = Executable(bundle.get_executable_path()) 44 | for arch in executable.arches: 45 | print arch['cmds']['LC_CODE_SIGNATURE'] 46 | 47 | 48 | def parse_args(): 49 | parser = argparse.ArgumentParser( 50 | description='Print the code signature structure of an executable or dylib') 51 | parser.add_argument( 52 | '-v', '--verbose', 53 | dest='verbose', 54 | action='store_true', 55 | default=False, 56 | required=False, 57 | help='Set logging level to debug.' 58 | ) 59 | parser.add_argument( 60 | 'app_paths', 61 | nargs=1, 62 | metavar='', 63 | type=absolute_path_argument, 64 | help='Path(s) to application, typically a ' 65 | 'directory ending in .app or file ending in .ipa.' 66 | ) 67 | return parser.parse_args() 68 | 69 | if __name__ == '__main__': 70 | args = parse_args() 71 | if args.verbose: 72 | level = logging.DEBUG 73 | else: 74 | level = logging.INFO 75 | log_to_stderr(level) 76 | 77 | print_codesig(args.app_paths[0]) 78 | -------------------------------------------------------------------------------- /dev/requirements.txt: -------------------------------------------------------------------------------- 1 | nose 2 | pytest 3 | twine 4 | -------------------------------------------------------------------------------- /dev/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # determine local paths 5 | pushd $(dirname "$0") >/dev/null 6 | DEV_DIR=$PWD 7 | cd .. 8 | SRC_DIR=$PWD 9 | popd >/dev/null 10 | 11 | pip install -U -r ${DEV_DIR}/requirements.txt 12 | ../INSTALL.sh develop 13 | -------------------------------------------------------------------------------- /docs/applecerts.rst: -------------------------------------------------------------------------------- 1 | Apple certificates 2 | ================== 3 | 4 | You probably don't need to change this file, not for a long time. 5 | 6 | The ``applecerts.pem`` file can be constructed by these steps. In theory 7 | you can export them from Keychain Access, too, but here's a procedure that 8 | doesn't involve an Apple machine. This worked for us in June 2016: 9 | 10 | .. code:: bash 11 | 12 | $ curl 'https://www.apple.com/appleca/AppleIncRootCertificate.cer' > AppleIncRootCertificate.cer 13 | $ curl 'https://developer.apple.com/certificationauthority/AppleWWDRCA.cer' > AppleWWDRCA.cer 14 | $ openssl x509 -inform der -in AppleIncRootCertificate.cer -outform pem -out AppleIncRootCertificate.pem 15 | $ openssl x509 -inform der -in AppleWWDRCA.cer -outform pem -out AppleWWDRCA.pem 16 | $ cat AppleWWDRCA.pem AppleIncRootCertificate.pem > applecerts.pem 17 | 18 | Here's a conceptual explanation of what we're doing: 19 | 20 | Download the following certs from `Apple's Certificate Authority 21 | Page `__ 22 | 23 | - Apple Inc. Root Certificate 24 | - Worldwide Developer Relations Certificate 25 | 26 | Then convert these to 27 | `PEM `__ 28 | format. 29 | 30 | Then, concatenate them together. This file can now serve as the 'Apple 31 | certificate' for code signing. 32 | 33 | -------------------------------------------------------------------------------- /docs/codedirectory.rst: -------------------------------------------------------------------------------- 1 | CodeDirectory slots 2 | =================== 3 | 4 | A signature is mostly composed of hashes of blocks of the file's 5 | contents. However, at some point, Apple added special hashes so the 6 | state of other resources in the app could be captured in the signature. 7 | For instance, the Info.plist gets its own hash, and ultimately the 8 | hashes of all the other files are also captured in the ResourceDirectory 9 | hash. Together, all these special hashes are called the CodeDirectory. 10 | 11 | Perhaps to indicate that these are special hashes, they were given 12 | negative offsets in the list of hashes. 13 | 14 | For instance, if you do ``codesign -d -r- --verbose=20 some.app`` 15 | 16 | :: 17 | 18 | Executable=... 19 | Identifier=com.somecompany.someapp 20 | Format=bundle with Mach-O universal (armv7 arm64) 21 | CodeDirectory v=20200 size=874 flags=0x0(none) hashes=35+5 location=embedded 22 | Hash type=sha1 size=20 23 | -5=0ea763a5bc4d19b0e03315a956deecd97693a661 24 | -4=0000000000000000000000000000000000000000 25 | -3=b353e6ce8464fd8ae32cfcf09e7c9015b7378054 26 | -2=32a5edb9b03a0bea2d7bc30cfdddadab7dab841c 27 | -1=46ebe92997b23b2e2187a21714c8cc32c347bf35 28 | 0=70e024fdab3426c375cf283d384de58ec6fff438 29 | 1=1ceaf73df40e531df3bfb26b4fb7cd95fb7bff1d 30 | 2=1ceaf73df40e531df3bfb26b4fb7cd95fb7bff1d 31 | ... 32 | 33 | The CodeDirectory hashes have stable negative indices - for instance, -1 34 | is always the hash of the Info.plist file. The indices for the 35 | CodeDirectory hashes are sometimes called slots. 36 | 37 | When building the CodeDirectory, We need to observe these constraints: 38 | 39 | - Executables should have all 5 slots in their codedirectory 40 | 41 | - Dylibs only need 2 slots, but sometimes have been compiled with 5 42 | 43 | - Dylibs should never include the ResourceDir slot, even if they have 5 44 | slots 45 | 46 | - We should delay calculating hashes until we know we are going to use 47 | them 48 | 49 | - Nobody uses the Application-specific slot anyway 50 | 51 | - At least so far, we don't need to change the Info.plist slot when 52 | re-signing 53 | -------------------------------------------------------------------------------- /docs/credentials.rst: -------------------------------------------------------------------------------- 1 | Apple developer credentials 2 | =========================== 3 | 4 | Mac OS X and iOS aren't like most other operating systems -- security is baked into every 5 | single program. The machine is able to check, before it even executes the program, who 6 | wrote it, whether Apple approved it, and whether it has the authority to do some things 7 | that it's asking to do. On Mac OS X, it's easy to get around those restrictions, but iOS 8 | is locked down very tight. 9 | 10 | The iOS device is able tell who wrote a program, and whether Apple approved it, without 11 | even phoning home to Apple. It does this by looking for evidence that is *was* approved 12 | at some earlier date, using cryptographic signatures embedded right into the application. 13 | 14 | Until now, few people outside Apple had a full understanding of how that worked, or how to 15 | add that magic "code signature" and other necessary proofs to the app. 16 | 17 | ``isign`` is able to create those -- with the right credentials. 18 | 19 | Definitions 20 | ----------- 21 | 22 | The **key** is the developer's private key. If you're familiar with Secure Shell keys, this is similar -- it's 23 | the private half of a public-private key pair. The private key is used to sign the application. This proves that 24 | the developer approved the entire contents of the application. 25 | 26 | Note that this key is not revealed to Apple, or anyone else. If you 27 | develop iOS apps, you, or someone in your organization, generated such a key. Hopefully they kept it 28 | secret. However, you need it to sign the app -- you probably have it in Keychain Access or something like 29 | that. 30 | 31 | The **certificate** is how Apple indicates that the developer is approved to write apps for iOS. At some 32 | point, they signed the public half of the developer's keys. Apple will also encode when your developer account 33 | is going to expire. 34 | 35 | The **organizational unit** is an identifier that Apple assigns to organizations that 36 | create apps on Apple devices. It's an eight character code of letters and numbers. You may need to know your 37 | organizational unit, so you can sign apps from your organization. ``isign`` can extract this from other files, 38 | like your certificate, so you probably don't need to worry about this. 39 | 40 | The **provisioning profile** is where it all comes together. This file is included in the app. 41 | 42 | The provisioning profile includes the contents of the certificate -- possibly many certificates. 43 | It also includes the UDIDs of the devices that you have registered with Apple. So, you can often use the same 44 | provisioning profile for all your developers and all your iOS devices. 45 | 46 | So, when a phone encounters an app, it will start by reading the provisioning profile, to learn things like: 47 | 48 | - Who wrote this app? 49 | - What organization do they belong to? 50 | - Are they still an Apple-approved developer? 51 | - And what's their public key? 52 | - Is this app approved to run on this particular device? 53 | 54 | From there it can go on to cryptographically verify each and every part of the app. This ensures that the 55 | app has not been tampered with, or that an unapproved developer hasn't snuck an app onto your phone (even if 56 | that developer is you.) 57 | 58 | 59 | How to create Apple developer credentials 60 | ----------------------------------------- 61 | 62 | For most developers, XCode takes care of most of these credentials. But with ``isign`` you have to do it more manually. 63 | 64 | Getting an account 65 | ~~~~~~~~~~~~~~~~~~ 66 | 67 | First, find an administrator for your developer organization at Apple. (If you're a solo developer, that's you.) 68 | 69 | Get them to invite you to your Apple Organizational Unit. 70 | 71 | You'll get email from Apple, which will prompt you to set up your account. Set up passwords and so on as usual. 72 | 73 | Troubleshooting: you may have to click on the mailed invite link 74 | once to set up your account, and then return to your mail to click 75 | on that invite link again to actually activate your account. Also, 76 | in general, things on the Apple site work better with Safari, so 77 | if something doesn't work, try that browser. 78 | 79 | Setting up credentials 80 | ~~~~~~~~~~~~~~~~~~~~~~ 81 | 82 | The following procedure works as of June 2015, for adding a new 83 | account from scratch. You will need a Mac OS X computer. (In theory 84 | you could do this entirely from Linux, using the Apple website, but 85 | you're on your own there.) 86 | 87 | Log into your Apple account. 88 | 89 | Go to **Certificates, Identifiers, & Profiles**. 90 | 91 | Go to **Certificates > Development** in the left-hand column. 92 | 93 | Press the plus icon to add a new certificate. 94 | 95 | It will ask what type of certificate you need. You probably want 96 | *iOS App Development*. 97 | 98 | It will then instruct you to use Keychain Access to generate a 99 | Certificate Signing Request. In effect you are going to create a 100 | private/public key pair, and then make a little file that says "Hey 101 | Apple, please sign the public half and make a certificate for it, and 102 | associate that with my Apple account!" 103 | 104 | Follow the instructions and save that CSR to disk. Press **Continue**. 105 | 106 | Then, the Apple website will ask you to upload that CSR. Do so, and 107 | it will create a certificate for your account in your organization. 108 | This certificate might need to be approved by an admin before you 109 | can download it. 110 | 111 | Once it's approved, download it! 112 | 113 | It will probably be named something generic like ``ios_development.cer``, 114 | so rename it to something more meaningful and put it somewhere safe. 115 | 116 | Import that ``.cer`` into Keychain. Keychain will detect that it 117 | has an associated private key, and in views where you see keys, the 118 | certificate will be "inside" the key, and vice versa. 119 | 120 | Provisioning profile 121 | ~~~~~~~~~~~~~~~~~~~~ 122 | 123 | Now we just need to tell Apple that your user is allowed to deploy on those devices. 124 | 125 | First, go to **Devices**, and add the UDIDs of all the devices you care about. If you installed `libimobiledevice`, an easy way to get the 126 | UDID is with ``idevice_id -l``. 127 | 128 | In the Developer portal, go to **Provisioning Profiles**, and create a new development profile. Select those devices and add them. 129 | 130 | In **Select App ID**, you probably want to just create one with a 131 | wildcard (Something using your Apple Organizational Unit plus domain plus dot-star, maybe, 132 | like ``A1B2C3D4.tld.domain.*`` ) 133 | 134 | Next, in **'Select certificates'**, select the certificates you want, which probably includes the one we just created above. 135 | 136 | Finally, download this provisioning profile, and follow the instructions in the main README. 137 | -------------------------------------------------------------------------------- /docs/speed.rst: -------------------------------------------------------------------------------- 1 | So you want to make it go faster 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | 4 | The *vast* majority of time in isign is not spent signing. It's in zipping and re-zipping. 5 | 6 | Most apps are packaged as IPAs. These are just glorified zip files with a particular directory structure. For most situations, we can't avoid the cost of unzipping and re-zipping. So if we're trying to make it faster, we've already lost, since we'll never speed it up even by a factor of 2. 7 | 8 | In theory you could: 9 | 10 | - Not use IPAs. isign can also re-sign unzipped ".app" directories. This is way faster, but then you have to use isign where you created the app, and you have to install the resigned app onto a device from there as well. 11 | 12 | - Use IPAs but re-compress them poorly. Basically, change the setting from zip quality of 6 (the default) to something else. Minor speedups can be accomplished that way, at the cost of increasing install time or time to transfer to send it the network. In my tests it wasn't an improvement when you considered typical things you would do with the app next. 13 | 14 | If neither of those approaches is acceptable to you, you can stop reading here. Because everything else that follows will speed it up, but not by much. 15 | 16 | 17 | Okay, so what *else* is taking time? 18 | 19 | 1) Copying the files. Maybe with some exotic copy-on-write filesystem we could avoid that? 20 | 21 | 2) Hashing the entire contents of the application. For data that we've never seen before, we can't do better than O(n). So we lose *again*. 22 | 23 | But we could still do better in the general case: 24 | 25 | - There are many files within the application. If we don't touch a file (it's not an executable 26 | or dylib), and we got a hash in the app's existing CodeResources seal, we could trust it, and 27 | reuse it in our CodeResources seal. 28 | 29 | I tried implementing this and it was super annoying to code, and didn't 30 | have a big impact on my test files, so I gave up. The problem is that you have to write wrappers around 31 | every method that writes to a file, and keep a tally of what files you touched. If you don't mind a less 32 | accurate method (scan directories for files changed since the start of the resigning process) that 33 | might work better. 34 | 35 | - We could recognize common libraries such as the Swift framework, and keep re-signed versions of 36 | those in some persistent storage. 37 | 38 | - Use separate processes to hash files, to exploit multiple cores. 39 | 40 | But wait! 41 | ~~~~~~~~~ 42 | 43 | Incidentally, if what you're looking for is to resign one app with multiple credentials, look into the `multisign` scripts. There can save a significant amount of time by unzipping the original app only once, and using a process pool to exploit multiple cores. 44 | -------------------------------------------------------------------------------- /isign/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import os.path 3 | import json 4 | 5 | package_dir = os.path.dirname(os.path.realpath(__file__)) 6 | with open(os.path.join(package_dir, "version.json"), 'r') as f: 7 | version = json.load(f) 8 | 9 | __version__ = version['version'] 10 | __commit__ = version['commit'] 11 | __build__ = version['build'] 12 | -------------------------------------------------------------------------------- /isign/apple_credentials/README.rst: -------------------------------------------------------------------------------- 1 | These Apple credentials are public knowledge (see the docs) so they 2 | are okay to distribute. Don't put anything else here. 3 | -------------------------------------------------------------------------------- /isign/apple_credentials/applecerts.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEIjCCAwqgAwIBAgIIAd68xDltoBAwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UE 3 | BhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRp 4 | ZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1BcHBsZSBSb290IENBMB4XDTEz 5 | MDIwNzIxNDg0N1oXDTIzMDIwNzIxNDg0N1owgZYxCzAJBgNVBAYTAlVTMRMwEQYD 6 | VQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxv 7 | cGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3Bl 8 | ciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3 9 | DQEBAQUAA4IBDwAwggEKAoIBAQDKOFSmy1aqyCQ5SOmM7uxfuH8mkbw0U3rOfGOA 10 | YXdkXqUHI7Y5/lAtFVZYcC1+xG7BSoU+L/DehBqhV8mvexj/avoVEkkVCBmsqtsq 11 | Mu2WY2hSFT2Miuy/axiV4AOsAX2XBWfODoWVN2rtCbauZ81RZJ/GXNG8V25nNYB2 12 | NqSHgW44j9grFU57Jdhav06DwY3Sk9UacbVgnJ0zTlX5ElgMhrgWDcHld0WNUEi6 13 | Ky3klIXh6MSdxmilsKP8Z35wugJZS3dCkTm59c3hTO/AO0iMpuUhXf1qarunFjVg 14 | 0uat80YpyejDi+l5wGphZxWy8P3laLxiX27Pmd3vG2P+kmWrAgMBAAGjgaYwgaMw 15 | HQYDVR0OBBYEFIgnFwmpthhgi+zruvZHWcVSVKO3MA8GA1UdEwEB/wQFMAMBAf8w 16 | HwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wLgYDVR0fBCcwJTAjoCGg 17 | H4YdaHR0cDovL2NybC5hcHBsZS5jb20vcm9vdC5jcmwwDgYDVR0PAQH/BAQDAgGG 18 | MBAGCiqGSIb3Y2QGAgEEAgUAMA0GCSqGSIb3DQEBBQUAA4IBAQBPz+9Zviz1smwv 19 | j+4ThzLoBTWobot9yWkMudkXvHcs1Gfi/ZptOllc34MBvbKuKmFysa/Nw0Uwj6OD 20 | Dc4dR7Txk4qjdJukw5hyhzs+r0ULklS5MruQGFNrCk4QttkdUGwhgAqJTleMa1s8 21 | Pab93vcNIx0LSiaHP7qRkkykGRIZbVf1eliHe2iK5IaMSuviSRSqpd1VAKmuu0sw 22 | ruGgsbwpgOYJd+W+NKIByn/c4grmO7i77LpilfMFY0GCzQ87HUyVpNur+cmV6U/k 23 | TecmmYHpvPm0KdIBembhLoz2IYrF+Hjhga6/05Cdqa3zr/04GpZnMBxRpVzscYqC 24 | tGwPDBUf 25 | -----END CERTIFICATE----- 26 | -----BEGIN CERTIFICATE----- 27 | MIIEuzCCA6OgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET 28 | MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv 29 | biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDYwNDI1MjE0 30 | MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw 31 | bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx 32 | FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 33 | ggEKAoIBAQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne+Uts9QerIjAC6Bg+ 34 | +FAJ039BqJj50cpmnCRrEdCju+QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1 35 | XQ7Vf1+b8iUDulWPTV0N8WQ1IxVLFVkds5T39pyez1C6wVhQZ48ItCD3y6wsIG9w 36 | tj8BMIy3Q88PnT3zK0koGsj+zrW5DtleHNbLPbU6rfQPDgCSC7EhFi501TwN22IW 37 | q6NxkkdTVcGvL0Gz+PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEwWOxaBDKM 38 | aLOPHd5lc/9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8E 39 | BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3 40 | R01/CF4wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wggERBgNVHSAE 41 | ggEIMIIBBDCCAQAGCSqGSIb3Y2QFATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93 42 | d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlhbmNl 43 | IG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0 44 | YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj 45 | b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZp 46 | Y2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBc 47 | NplMLXi37Yyb3PN3m/J20ncwT8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQP 48 | y3lPNNiiPvl4/2vIB+x9OYOLUyDTOMSxv5pPCmv/K/xZpwUJfBdAVhEedNO3iyM7 49 | R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx+IjXKJdXZD9Zr1KIkIxH3oayPc4Fg 50 | xhtbCS+SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL/lTaltkwGMzd/c6ByxW69oP 51 | IQ7aunMZT7XZNn/Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AX 52 | UKqK1drk/NAJBzewdXUh 53 | -----END CERTIFICATE----- 54 | -------------------------------------------------------------------------------- /isign/code_resources_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | 8 | rules 9 | 10 | ^ 11 | 12 | ^.*\.lproj/ 13 | 14 | optional 15 | 16 | weight 17 | 1000 18 | 19 | ^.*\.lproj/locversion.plist$ 20 | 21 | omit 22 | 23 | weight 24 | 1100 25 | 26 | ^version.plist$ 27 | 28 | 29 | rules2 30 | 31 | .*\.dSYM($|/) 32 | 33 | weight 34 | 11 35 | 36 | ^ 37 | 38 | weight 39 | 20 40 | 41 | ^(.*/)?\.DS_Store$ 42 | 43 | omit 44 | 45 | weight 46 | 2000 47 | 48 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ 49 | 50 | nested 51 | 52 | weight 53 | 10 54 | 55 | ^.* 56 | 57 | ^.*\.lproj/ 58 | 59 | optional 60 | 61 | weight 62 | 1000 63 | 64 | ^.*\.lproj/locversion.plist$ 65 | 66 | omit 67 | 68 | weight 69 | 1100 70 | 71 | ^Info\.plist$ 72 | 73 | omit 74 | 75 | weight 76 | 20 77 | 78 | ^PkgInfo$ 79 | 80 | omit 81 | 82 | weight 83 | 20 84 | 85 | ^[^/]+$ 86 | 87 | nested 88 | 89 | weight 90 | 10 91 | 92 | ^embedded\.provisionprofile$ 93 | 94 | weight 95 | 20 96 | 97 | ^version\.plist$ 98 | 99 | weight 100 | 20 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /isign/exceptions.py: -------------------------------------------------------------------------------- 1 | """ Some common exceptions """ 2 | 3 | 4 | class NotSignable(Exception): 5 | """ superclass for any reason why app shouldn't be 6 | signable """ 7 | pass 8 | 9 | 10 | class NotMatched(Exception): 11 | """ thrown if we can't find any app class for 12 | this file path """ 13 | pass 14 | 15 | 16 | class MissingHelpers(NotSignable): 17 | """ thrown if helper apps are missing """ 18 | pass 19 | 20 | 21 | class MissingCredentials(Exception): 22 | """ thrown if credentials are missing """ 23 | pass 24 | 25 | 26 | class ImproperCredentials(Exception): 27 | """ thrown if something looks fishy about credentials """ 28 | pass 29 | 30 | 31 | class OpenSslFailure(Exception): 32 | """ something is wrong with openssl output """ 33 | pass 34 | -------------------------------------------------------------------------------- /isign/isign.py: -------------------------------------------------------------------------------- 1 | import archive 2 | # import makesig 3 | import exceptions 4 | import os 5 | from os.path import dirname, exists, expanduser, join, realpath 6 | 7 | # this comes with the repo 8 | PACKAGE_ROOT = dirname(realpath(__file__)) 9 | DEFAULT_APPLE_CERT_PATH = join(PACKAGE_ROOT, 'apple_credentials', 'applecerts.pem') 10 | DEFAULT_CREDENTIAL_FILE_NAMES = { 11 | 'certificate': 'certificate.pem', 12 | 'key': 'key.pem', 13 | 'provisioning_profile': 'isign.mobileprovision' 14 | } 15 | 16 | 17 | class NotSignable(Exception): 18 | """ This is just so we don't expose other sorts of exceptions """ 19 | pass 20 | 21 | 22 | def get_credential_paths(directory, file_names=DEFAULT_CREDENTIAL_FILE_NAMES): 23 | """ Given a directory, return dict of paths to standard 24 | credential files """ 25 | paths = {} 26 | for (k, file_name) in file_names.iteritems(): 27 | paths[k] = join(directory, file_name) 28 | return paths 29 | 30 | 31 | # We will default to using credentials in a particular 32 | # directory with well-known names. This is complicated because 33 | # the old way at Sauce Labs (pre-2017) was: 34 | # ~/isign-credentials/mobdev.cert.pem, etc. 35 | # But the new way that everyone should now use: 36 | # ~/.isign/certificate.pem, etc. 37 | HOME_DIR = expanduser("~") 38 | if exists(join(HOME_DIR, 'isign-credentials')): 39 | DEFAULT_CREDENTIAL_PATHS = get_credential_paths( 40 | join(HOME_DIR, 'isign-credentials'), 41 | { 42 | 'certificate': 'mobdev.cert.pem', 43 | 'key': 'mobdev.key.pem', 44 | 'provisioning_profile': 'mobdev1.mobileprovision' 45 | } 46 | ) 47 | else: 48 | DEFAULT_CREDENTIAL_PATHS = get_credential_paths( 49 | join(HOME_DIR, '.isign') 50 | ) 51 | 52 | 53 | def resign_with_creds_dir(input_path, 54 | credentials_directory, 55 | **kwargs): 56 | """ Do isign.resign(), but with credential files from this directory """ 57 | kwargs.update(get_credential_paths(credentials_directory)) 58 | return resign(input_path, **kwargs) 59 | 60 | 61 | def resign(input_path, 62 | deep=True, 63 | apple_cert=DEFAULT_APPLE_CERT_PATH, 64 | certificate=DEFAULT_CREDENTIAL_PATHS['certificate'], 65 | key=DEFAULT_CREDENTIAL_PATHS['key'], 66 | provisioning_profile=DEFAULT_CREDENTIAL_PATHS['provisioning_profile'], 67 | output_path=join(os.getcwd(), "out"), 68 | info_props=None, 69 | alternate_entitlements_path=None): 70 | """ Mirrors archive.resign(), put here for convenience, to unify exceptions, 71 | and to omit default args """ 72 | try: 73 | return archive.resign(input_path, 74 | deep, 75 | certificate, 76 | key, 77 | apple_cert, 78 | provisioning_profile, 79 | output_path, 80 | info_props, 81 | alternate_entitlements_path) 82 | except exceptions.NotSignable as e: 83 | # re-raise the exception without exposing internal 84 | # details of how it happened 85 | raise NotSignable(e) 86 | 87 | 88 | def view(input_path): 89 | """ Obtain information about the app """ 90 | try: 91 | return archive.view(input_path) 92 | except exceptions.NotSignable as e: 93 | raise NotSignable(e) 94 | -------------------------------------------------------------------------------- /isign/multisign.py: -------------------------------------------------------------------------------- 1 | from os.path import isdir 2 | import isign 3 | from archive import archive_factory 4 | from signer import Signer 5 | import logging 6 | import multiprocessing 7 | 8 | log = logging.getLogger(__name__) 9 | 10 | MAX_PROCESSES = multiprocessing.cpu_count() 11 | 12 | 13 | def resign(args): 14 | """ Given a tuple consisting of a path to an uncompressed archive, 15 | credential directory, and desired output path, resign accordingly. 16 | 17 | Returns a tuple of (cred_dir, path to resigned app) """ 18 | ua, cred_dir, resigned_path = args 19 | 20 | try: 21 | log.debug('resigning with %s %s -> %s', ua.path, cred_dir, resigned_path) 22 | # get the credential files, create the 'signer' 23 | credential_paths = isign.get_credential_paths(cred_dir) 24 | signer = Signer(signer_cert_file=credential_paths['certificate'], 25 | signer_key_file=credential_paths['key'], 26 | apple_cert_file=isign.DEFAULT_APPLE_CERT_PATH) 27 | 28 | # sign it (in place) 29 | ua.bundle.resign(signer, credential_paths['provisioning_profile']) 30 | 31 | log.debug("outputing %s", resigned_path) 32 | # and archive it there 33 | ua.archive(resigned_path) 34 | 35 | finally: 36 | ua.remove() 37 | 38 | return (cred_dir, resigned_path) 39 | 40 | 41 | def clone_ua(args): 42 | original_ua, target_ua_path = args 43 | log.debug('cloning %s to %s', original_ua.path, target_ua_path) 44 | ua = original_ua.clone(target_ua_path) 45 | log.debug('done cloning to %s', original_ua.path) 46 | return ua 47 | 48 | 49 | def multisign(original_path, cred_dirs_to_output_paths, info_props=None): 50 | """ Given a path to an app, 51 | a mapping of credential directories to desired output paths, 52 | optional info.plist properties to overwrite, 53 | 54 | produce re-signed versions of the app as desired. 55 | 56 | See: multisign_archive, which this wraps. 57 | 58 | Returns an array of tuples of [(credentials_dir, resigned app path)...] 59 | """ 60 | 61 | archive = archive_factory(original_path) 62 | if archive is None: 63 | log.debug("%s didn't look like an app...", original_path) 64 | return None 65 | 66 | return multisign_archive(archive, cred_dirs_to_output_paths, info_props) 67 | 68 | 69 | def multisign_archive(archive, cred_dirs_to_output_paths, info_props=None): 70 | """ Given an isign.archive object, 71 | a mapping of credential directories to desired output paths, 72 | optional info.plist properties to overwrite, 73 | 74 | produce re-signed versions of the IPA. 75 | 76 | If info_props are provided, it will overwrite those properties in 77 | the app's Info.plist. 78 | 79 | Returns an array of tuples of [(credentials_dir, resigned app path)...] 80 | """ 81 | 82 | # get ready for multiple processes... 83 | p = multiprocessing.Pool(MAX_PROCESSES) 84 | 85 | # ua is potentially an isign.archive.UncompressedArchive 86 | ua = None 87 | 88 | results = [] 89 | 90 | try: 91 | ua = archive.unarchive_to_temp() 92 | if info_props: 93 | # Override info.plist props 94 | ua.bundle.update_info_props(info_props) 95 | 96 | # Since the signing process rewrites files, we must first create uncompressed archives 97 | # for each credentials_directory. 98 | # The first is simply the uncompressed archive we just made 99 | uas = [ua] 100 | 101 | # But the rest need to be copied. This might take a while, so let's do it in parallel 102 | # this will copy them to /path/to/uncompressedArchive_1, .._2, and so on 103 | # and make UncompressedArchive objects that can be used for resigning 104 | target_ua_paths = [] 105 | for i in range(1, len(cred_dirs_to_output_paths)): 106 | target_ua_paths.append((ua, ua.path + '_' + str(i))) 107 | uas += p.map(clone_ua, target_ua_paths) 108 | 109 | # now we should have one UncompressedArchive for every credential directory 110 | assert len(uas) == len(cred_dirs_to_output_paths) 111 | 112 | # We will now construct arguments for all the resignings 113 | resign_args = [] 114 | for i, (cred_dir, output_path) in enumerate(cred_dirs_to_output_paths.items()): 115 | resign_args.append((uas[i], cred_dir, output_path)) 116 | log.debug('resign args: %s', resign_args) 117 | 118 | # In parallel, resign each uncompressed archive with supplied credentials, 119 | # and make archives in the desired paths. 120 | results = p.map(resign, resign_args) 121 | 122 | except isign.NotSignable as e: 123 | msg = "Not signable: <{0}>: {1}\n".format(archive.path, e) 124 | log.error(msg) 125 | raise 126 | 127 | finally: 128 | if ua is not None and isdir(ua.path): 129 | ua.remove() 130 | 131 | return results 132 | -------------------------------------------------------------------------------- /isign/utils.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def print_data(data): 5 | hexstring = binascii.hexlify(data) 6 | n = 80 7 | split_string = "\n".join([hexstring[i:i+n] for i in range(0, len(hexstring), n)]) 8 | print split_string 9 | 10 | 11 | def round_up(x, k): 12 | return ((x + k - 1) & -k) 13 | 14 | 15 | def print_structure(container, struct): 16 | actual_data = struct.build(container) 17 | return "{}".format(struct.parse(actual_data)) 18 | 19 | -------------------------------------------------------------------------------- /jenkins.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # figure out our package name from the name of repo 4 | pushd $(dirname $0) >/dev/null 5 | package_name=$(basename $PWD) 6 | package=$(echo $package_name | sed 's/-/_/g') 7 | popd >/dev/null 8 | 9 | version=$(./version.sh) 10 | 11 | # this communicates to setup.py to use the version 12 | # number we just made, rather than generating another 13 | export PYTHON_PACKAGE_VERSION=${version} 14 | 15 | make_venv() { 16 | # For some reason mkvirtualenv returns with exit code 1 on success. So we 17 | # have to just continue. 18 | virtualenv $TMPDIR || true 19 | source $TMPDIR/bin/activate 20 | pip install -r dev/requirements.txt 21 | } 22 | 23 | build_release() { 24 | python setup.py sdist 25 | release=${package_name}-${version}.tar.gz 26 | } 27 | 28 | test_release() { 29 | rm -rf dist-release && mkdir -p dist-release 30 | 31 | echo "pip install dist/$release" 32 | pip install dist/$release 33 | echo -e "\nInstalled packages:" 34 | pip freeze -l 35 | echo 36 | mv $package ${package}.testing 37 | ./run_tests.sh 38 | mv dist/$release dist-release/ 39 | } 40 | 41 | # to push tags: add the repo to the "bots" team 42 | tag_release() { 43 | tag="v$version" 44 | echo "Tagging $head as $tag" 45 | git tag $tag $head 46 | git push origin $tag 47 | } 48 | 49 | update_pypi() { 50 | # always succeed with upload - transient errors with pypi 51 | # should not cause red build 52 | twine upload dist-release/$release || true 53 | } 54 | 55 | cleanup() { 56 | rm -rf $TMPDIR 57 | 58 | if [[ -d ${package}.testing ]]; then 59 | mv ${package}.testing $package 60 | fi 61 | } 62 | 63 | 64 | set -e 65 | TMPDIR=$(mktemp -d /tmp/${package_name}.XXXXXXXX) 66 | trap cleanup 0 67 | 68 | make_venv 69 | build_release 70 | test_release 71 | tag_release 72 | update_pypi 73 | cleanup 74 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | name=$(basename $PWD) 3 | package=$(echo $name | sed 's/-/_/g') 4 | 5 | # look for required apps 6 | for app in unzip zip; do 7 | if ! which $app >/dev/null; then 8 | echo "Missing application: $app" 9 | exit 1 10 | fi 11 | done 12 | 13 | # run test suite 14 | find . -name '*.pyc' -delete 15 | pushd tests >/dev/null 16 | version=$(python -c "import $package; print ${package}.__version__") 17 | echo "Testing $name v${version}" 18 | nosetests 19 | popd >/dev/null 20 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.rst 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from setuptools import setup, find_packages 3 | from codecs import open # to use a consistent encoding 4 | from subprocess import check_output 5 | from os import path, environ 6 | 7 | here = path.abspath(path.dirname(__file__)) 8 | 9 | if path.exists(path.join(here, "version.sh")): # development 10 | if 'PYTHON_PACKAGE_VERSION' in environ: 11 | version = environ['PYTHON_PACKAGE_VERSION'] 12 | else: 13 | version = check_output(path.join(here, "version.sh")).strip() 14 | package_name = path.basename(here) 15 | else: # source package 16 | with open(path.join(here, "PKG-INFO")) as f: 17 | for line in f.readlines(): 18 | if line.startswith("Version:"): 19 | version = line.split(":")[1].strip() 20 | elif line.startswith("Name:"): 21 | package_name = line.split(":")[1].strip() 22 | package = package_name.replace('-', '_') 23 | 24 | setup( 25 | name=package_name, 26 | version=version, 27 | description='Re-signing iOS apps without Apple tools', 28 | url='https://github.com/saucelabs/{}'.format(package_name), 29 | download_url='https://github.com/saucelabs/{}/tarball/v{}'.format(package_name, version), 30 | author='Sauce Labs', 31 | author_email='dev@saucelabs.com', 32 | classifiers=[ 33 | 'Development Status :: 5 - Production/Stable', 34 | 'Intended Audience :: Developers', 35 | 'Topic :: Utilities', 36 | 'License :: OSI Approved :: Apache Software License', 37 | 'Programming Language :: Python :: 2.7', 38 | ], 39 | keywords=['ios', 'app', 'signature', 'codesign', 'sign', 'resign'], 40 | packages=find_packages(), 41 | install_requires=[ 42 | 'biplist==0.9', 43 | 'construct==2.5.2', 44 | 'memoizer==0.0.1', 45 | 'pyOpenSSL==0.15.1' 46 | ], 47 | package_data={ 48 | package: ['apple_credentials/applecerts.pem', 49 | 'code_resources_template.xml', 50 | 'version.json'], 51 | }, 52 | scripts=['bin/isign', 53 | 'bin/multisign', 54 | 'bin/isign_export_creds.sh', 55 | 'bin/isign_guess_mobileprovision.sh'] 56 | ) 57 | -------------------------------------------------------------------------------- /tests/NotAnApp.ipa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/NotAnApp.ipa -------------------------------------------------------------------------------- /tests/NotAnApp.txt: -------------------------------------------------------------------------------- 1 | This file isn't actually an app. 2 | -------------------------------------------------------------------------------- /tests/NotAnAppDir/README.md: -------------------------------------------------------------------------------- 1 | This is a directory which isign shouldn't accept as being an AppArchive 2 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | To test isign, we need to actually sign some apps. This directory contains 2 | the tests and the test data AND the source files to generate that test data. 3 | 4 | This directory includes a lot of stuff. It could probably be better organized. 5 | 6 | Test data: to check that the library can detect non-apps: 7 | * NotAnApp.ipa 8 | * NotAnApp.txt 9 | 10 | Test data - compiled apps: 11 | * Test.app 12 | * Test.app.zip 13 | * Test.ipa 14 | * TestSimulator.app.zip 15 | * TestWithFrameworks.ipa 16 | 17 | Expected data from apps: 18 | * Test.app.codesig.construct.txt 19 | 20 | A short program to generate that expected data: 21 | * generate_codesig_construct_txt.py 22 | 23 | A test file, to see what happens when "helper" apps go wrong: 24 | * bad_openssl 25 | 26 | Self-signed/fake credentials, to make these tests even work 27 | * credentials 28 | 29 | Source to build the test apps: 30 | * isignTestApp 31 | * isignTestAppWithFrameworks 32 | 33 | Helper for tests: 34 | * `monitor_temp_file.py` 35 | * `helpers.py` 36 | 37 | Actual test code: 38 | * `isign_base_test.py` 39 | * `test_*.py:` 40 | -------------------------------------------------------------------------------- /tests/Test.app.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app.zip -------------------------------------------------------------------------------- /tests/Test.app/Assets.car: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Assets.car -------------------------------------------------------------------------------- /tests/Test.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib -------------------------------------------------------------------------------- /tests/Test.app/Base.lproj/LaunchScreen.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Base.lproj/LaunchScreen.storyboardc/Info.plist -------------------------------------------------------------------------------- /tests/Test.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib -------------------------------------------------------------------------------- /tests/Test.app/Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib -------------------------------------------------------------------------------- /tests/Test.app/Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib -------------------------------------------------------------------------------- /tests/Test.app/Base.lproj/Main.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Base.lproj/Main.storyboardc/Info.plist -------------------------------------------------------------------------------- /tests/Test.app/Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftContacts.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftContacts.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftCore.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftCore.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftCoreGraphics.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftCoreGraphics.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftCoreImage.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftCoreImage.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftDarwin.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftDarwin.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftDispatch.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftDispatch.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftFoundation.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftFoundation.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftObjectiveC.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftObjectiveC.dylib -------------------------------------------------------------------------------- /tests/Test.app/Frameworks/libswiftUIKit.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Frameworks/libswiftUIKit.dylib -------------------------------------------------------------------------------- /tests/Test.app/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/Info.plist -------------------------------------------------------------------------------- /tests/Test.app/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /tests/Test.app/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ./build.sh /path/to/isign 4 | 5 | # builds various archival formats of the isign test app 6 | # and puts them in the test directory of isign. You have to specify 7 | # isign's source directory on the command line 8 | 9 | 10 | project=isignTestApp 11 | isign_dir=$1 12 | isign_test_dir=$isign_dir/tests 13 | 14 | warn() { 15 | echo "$@" 1>&2; 16 | } 17 | 18 | build_app() { 19 | local platform=$1; 20 | local build_dir=build/Release-$(echo $platform | tr -d "0-9."); 21 | xcodebuild -project $project.xcodeproj -sdk $platform; 22 | } 23 | 24 | copy_app() { 25 | local platform=$1; 26 | local target=$2; 27 | local build_dir=$(build_app $platform) 28 | cp -r $build_dir/$project.app $target; 29 | } 30 | 31 | copy_app_zip() { 32 | local platform=$1; 33 | local target=$2; 34 | local build_dir=$(build_app $platform) 35 | pushd $build_dir; 36 | rm -f app.zip; 37 | zip -r app.zip $project.app; 38 | popd; 39 | mv $build_dir/app.zip $target; 40 | } 41 | 42 | 43 | build_ipa() { 44 | local platform=$1 45 | local target=$2 46 | 47 | xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform; 48 | xcodebuild archive -project $project.xcodeproj -scheme $project -archivePath $project.xcarchive 49 | xcodebuild -exportArchive \ 50 | -archivePath $projectname.xcarchive \ 51 | -exportPath $projectname \ 52 | -exportFormat ipa \ 53 | -exportProvisioningProfile "Neil Kandalgaonkar" 54 | } 55 | 56 | 57 | 58 | copy_app iphoneos9.2 $isign_test_dir/Test.app; 59 | copy_app_zip iphoneos9.2 $isign_test_dir/Test.app.zip; 60 | # build_ipa iphoneos9.2 $isign_test_dir/Test.ipa; 61 | # build_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip; 62 | 63 | -------------------------------------------------------------------------------- /tests/Test.app/isignTestApp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/isignTestApp -------------------------------------------------------------------------------- /tests/Test.app/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/Test.app/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.app/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /tests/Test.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /tests/Test.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | isignTestApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 88F49D521C21E0220007422C 16 | 17 | primary 18 | 19 | 20 | 88F49D681C21E0220007422C 21 | 22 | primary 23 | 24 | 25 | 88F49D731C21E0220007422C 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/Test.app/isignTestAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/Test.app/isignTestAppTests/isignTestAppTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppTests.swift 3 | // isignTestAppTests 4 | // 5 | // Created by Neil Kandalgaonkar on 12/16/15. 6 | // Copyright © 2015 Sauce Labs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import isignTestApp 11 | 12 | class isignTestAppTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/Test.app/isignTestAppUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/Test.app/isignTestAppUITests/isignTestAppUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppUITests.swift 3 | // isignTestAppUITests 4 | // 5 | // Created by Neil Kandalgaonkar on 12/16/15. 6 | // Copyright © 2015 Sauce Labs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class isignTestAppUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/Test.ipa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test.ipa -------------------------------------------------------------------------------- /tests/TestSimulator.app.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/TestSimulator.app.zip -------------------------------------------------------------------------------- /tests/TestWithFrameworks.ipa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/TestWithFrameworks.ipa -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Assets.car: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Assets.car -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Base.lproj/LaunchScreen.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Base.lproj/LaunchScreen.storyboardc/Info.plist -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/Info.plist -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftContacts.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftContacts.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftCore.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftCore.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftCoreGraphics.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftCoreGraphics.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftCoreImage.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftCoreImage.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftDarwin.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftDarwin.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftDispatch.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftDispatch.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftFoundation.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftFoundation.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftObjectiveC.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftObjectiveC.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Frameworks/libswiftUIKit.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Frameworks/libswiftUIKit.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/Info.plist -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ./build.sh /path/to/isign 4 | 5 | # builds various archival formats of the isign test app 6 | # and puts them in the test directory of isign. You have to specify 7 | # isign's source directory on the command line 8 | 9 | 10 | project=isignTestApp 11 | isign_dir=$1 12 | isign_test_dir=$isign_dir/tests 13 | 14 | warn() { 15 | echo "$@" 1>&2; 16 | } 17 | 18 | build_app() { 19 | local platform=$1; 20 | local build_dir=build/Release-$(echo $platform | tr -d "0-9."); 21 | xcodebuild -project $project.xcodeproj -sdk $platform; 22 | } 23 | 24 | copy_app() { 25 | local platform=$1; 26 | local target=$2; 27 | local build_dir=$(build_app $platform) 28 | cp -r $build_dir/$project.app $target; 29 | } 30 | 31 | copy_app_zip() { 32 | local platform=$1; 33 | local target=$2; 34 | local build_dir=$(build_app $platform) 35 | pushd $build_dir; 36 | rm -f app.zip; 37 | zip -r app.zip $project.app; 38 | popd; 39 | mv $build_dir/app.zip $target; 40 | } 41 | 42 | 43 | build_ipa() { 44 | local platform=$1 45 | local target=$2 46 | 47 | xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform; 48 | xcodebuild archive -project $project.xcodeproj -scheme $project -archivePath $project.xcarchive 49 | xcodebuild -exportArchive \ 50 | -archivePath $projectname.xcarchive \ 51 | -exportPath $projectname \ 52 | -exportFormat ipa \ 53 | -exportProvisioningProfile "Neil Kandalgaonkar" 54 | } 55 | 56 | 57 | 58 | copy_app iphoneos9.2 $isign_test_dir/Test.app; 59 | copy_app_zip iphoneos9.2 $isign_test_dir/Test.app.zip; 60 | # build_ipa iphoneos9.2 $isign_test_dir/Test.ipa; 61 | # build_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip; 62 | 63 | -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestApp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/isignTestApp -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | isignTestApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 88F49D521C21E0220007422C 16 | 17 | primary 18 | 19 | 20 | 88F49D681C21E0220007422C 21 | 22 | primary 23 | 24 | 25 | 88F49D731C21E0220007422C 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestAppTests/isignTestAppTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppTests.swift 3 | // isignTestAppTests 4 | // 5 | // Created by Neil Kandalgaonkar on 12/16/15. 6 | // Copyright © 2015 Sauce Labs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import isignTestApp 11 | 12 | class isignTestAppTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestAppUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/Test_unsigned_fat.app/isignTestAppUITests/isignTestAppUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppUITests.swift 3 | // isignTestAppUITests 4 | // 5 | // Created by Neil Kandalgaonkar on 12/16/15. 6 | // Copyright © 2015 Sauce Labs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class isignTestAppUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Assets.car: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Assets.car -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Base.lproj/LaunchScreen.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Base.lproj/LaunchScreen.storyboardc/Info.plist -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/Info.plist -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftContacts.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftContacts.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftCore.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftCore.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftCoreGraphics.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftCoreGraphics.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftCoreImage.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftCoreImage.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftDarwin.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftDarwin.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftDispatch.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftDispatch.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftFoundation.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftFoundation.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftObjectiveC.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftObjectiveC.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Frameworks/libswiftUIKit.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Frameworks/libswiftUIKit.dylib -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/Info.plist -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ./build.sh /path/to/isign 4 | 5 | # builds various archival formats of the isign test app 6 | # and puts them in the test directory of isign. You have to specify 7 | # isign's source directory on the command line 8 | 9 | 10 | project=isignTestApp 11 | isign_dir=$1 12 | isign_test_dir=$isign_dir/tests 13 | 14 | warn() { 15 | echo "$@" 1>&2; 16 | } 17 | 18 | build_app() { 19 | local platform=$1; 20 | local build_dir=build/Release-$(echo $platform | tr -d "0-9."); 21 | xcodebuild -project $project.xcodeproj -sdk $platform; 22 | } 23 | 24 | copy_app() { 25 | local platform=$1; 26 | local target=$2; 27 | local build_dir=$(build_app $platform) 28 | cp -r $build_dir/$project.app $target; 29 | } 30 | 31 | copy_app_zip() { 32 | local platform=$1; 33 | local target=$2; 34 | local build_dir=$(build_app $platform) 35 | pushd $build_dir; 36 | rm -f app.zip; 37 | zip -r app.zip $project.app; 38 | popd; 39 | mv $build_dir/app.zip $target; 40 | } 41 | 42 | 43 | build_ipa() { 44 | local platform=$1 45 | local target=$2 46 | 47 | xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform; 48 | xcodebuild archive -project $project.xcodeproj -scheme $project -archivePath $project.xcarchive 49 | xcodebuild -exportArchive \ 50 | -archivePath $projectname.xcarchive \ 51 | -exportPath $projectname \ 52 | -exportFormat ipa \ 53 | -exportProvisioningProfile "Neil Kandalgaonkar" 54 | } 55 | 56 | 57 | 58 | copy_app iphoneos9.2 $isign_test_dir/Test.app; 59 | copy_app_zip iphoneos9.2 $isign_test_dir/Test.app.zip; 60 | # build_ipa iphoneos9.2 $isign_test_dir/Test.ipa; 61 | # build_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip; 62 | 63 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestApp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/isignTestApp -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | isignTestApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 88F49D521C21E0220007422C 16 | 17 | primary 18 | 19 | 20 | 88F49D681C21E0220007422C 21 | 22 | primary 23 | 24 | 25 | 88F49D731C21E0220007422C 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestAppTests/isignTestAppTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppTests.swift 3 | // isignTestAppTests 4 | // 5 | // Created by Neil Kandalgaonkar on 12/16/15. 6 | // Copyright © 2015 Sauce Labs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import isignTestApp 11 | 12 | class isignTestAppTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestAppUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/Test_unsigned_thin.app/isignTestAppUITests/isignTestAppUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppUITests.swift 3 | // isignTestAppUITests 4 | // 5 | // Created by Neil Kandalgaonkar on 12/16/15. 6 | // Copyright © 2015 Sauce Labs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class isignTestAppUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/bad_openssl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # returns nothing; simulates what happens with bad versions of openssl 4 | -------------------------------------------------------------------------------- /tests/credentials/README.rst: -------------------------------------------------------------------------------- 1 | The test credentials in this directory cannot be used to sign apps for use on any iOS device. They 2 | are sufficiently similar to a real key, certificate and provisioning profile to make 3 | the tests pass. 4 | 5 | The key was generated solely for this library, and the certificate is self-signed. A working 6 | key would have to be certified by Apple. 7 | 8 | The provisioning profile was created with makeFakePprof.sh and test.mobileprovision.plist. The structure 9 | is based on a real provisioning profile, but all data has been swapped for meaningless noise. 10 | -------------------------------------------------------------------------------- /tests/credentials/makeFakePprof.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | openssl smime -sign -in test.mobileprovision.plist -outform der -out test.mobileprovision -signer test.cert.pem -inkey test.key.pem -nodetach 4 | -------------------------------------------------------------------------------- /tests/credentials/test.cert.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: isign_tests 3 | localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 4 | subject=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com 5 | issuer=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com 6 | -----BEGIN CERTIFICATE----- 7 | MIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNp 8 | Z25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRF 9 | U1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFu 10 | Y2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAy 11 | MjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3Rz 12 | MRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkG 13 | A1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAw 14 | HgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEB 15 | BQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byK 16 | pUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+ 17 | xBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBW 18 | kcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/ 19 | rUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE 20 | 2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0P 21 | AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA 22 | A4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcR 23 | BaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDla 24 | h3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzB 25 | PXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHL 26 | MaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1yw 27 | E4pd+A1hdAwzsqKr3xxZmisaV8yH 28 | -----END CERTIFICATE----- 29 | -------------------------------------------------------------------------------- /tests/credentials/test.key.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: isign_tests 3 | localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 4 | Key Attributes: 5 | -----BEGIN RSA PRIVATE KEY----- 6 | MIIEowIBAAKCAQEA8oTKqrq3FIKEiyhW/S2AAjijwEMaoBTCqNRP0drVvIqlRL9h 7 | W0d5oL2jM81Kd2UB8W9SLBX4wPSs/OdmiNCcq1jLpEIhobJKjHoV42oWYv7EFRPB 8 | BpXYipkQpQktIMtjgTE9/3wst3GuJ7JRZH6V0DRVq2d7ppPGp4qMTBQpsFaRxImt 9 | gz0jhn9noAaiamH5uVdY6DSXLlCyHEnNcOOfuLwx1bSvLdikgcsOhImJ5b+tQ1IG 10 | IblvXHLdM2pKtSPIIriqvQcmo8VoN+7MIrJQlWdhkeS3X6pnWaZfYJZq+0Tb6ztR 11 | /9PDXR8yzNeNcog/u7GVM6Nt89+ATZDdFQJKiwIDAQABAoIBAQDtyhx5qJgIqSzS 12 | 0Vvx5KImC2ksA9/gZFq1dW9KQbreokcIEGqiOIPegvK5wSmpxcVQ+Kjmhyif8YiI 13 | dU/JCFsFeww5Y4pcZFfKQ46grA2FRW33iKX0Egr/YrO6TjQMesB3FVRH5HZn7DQp 14 | wiMiWSgFvLrfVJkeLLlU33lOw1pZBbAhNaZK+DQ2nuLDg1mIbJ1B0VRvEo5zVS4r 15 | CZo8otr3MAkdTbjhqaoGDZuRnjzd72Zl/VCxlg55IJP45WV2hHWt7ofH0RjQ4KSA 16 | XIuh9KJWf9f6vVv2oZ+nY6P6EA2mzIBKzlfpcPNvUeh+gW4Ln2kbsxnIp2VxU2D+ 17 | UH+oVclpAoGBAP+Risu98rg1et1Sh5oHe2MIZ18n2M01qhqdJx5fY28+7GHVTdvn 18 | BMaooojpxYJ/aEY2M5oZfG6twCpLN5+YTFsycDsdL5ALoMqGLDdBbtNjmVzQUzuN 19 | g0oZvu6Xi9qN9GGF84falS+tchAOGQahw+mpWRtqnmNI60geo5V/Ng+lAoGBAPLt 20 | m/vwM/s09XnFozfX2tdpWUjPUnDRCFWQBSNpnqjeUi4B/evMxXhZIT+z2Vg+cRru 21 | A4xLRJ2ZQbEYsTPxejCoMJsKD48pFi1KDDAN0HQSKPwKgwHoBJjIGoxb4gV5Uz0T 22 | FiXMp8667vI2O6VlQZYfvx1K4qsbjRBLQReyE9pvAoGAMVx5BFURtkaODoVML5HW 23 | YRBUduqJU0lUK4PC9HjUCb6LhXHfceOy5nPXwL32KfhVuYnqeY8Gm5HvlbulaKvP 24 | w6WAS8qdTyMP0U4M6Dc5IpcQHf8WtF/mxb8nQ4n9tx7H3rYyjUDIo8bKSxON/dvs 25 | rQrKbSMwqFiDKRDR46QIWwkCgYBL4l1vfcE/H3Pu7gXmU89Qqt/xFpIyG5n24F46 26 | iau+JHSXWpfvKLAmv/Da7VtfbWH3f5IsKPbuJAmZQJVaHHyG5oMIa0Qg/DypORBF 27 | kosjNukGkmIKHmgRMbDZV3prK1MNKQEqHZvtwAcUMky/hbnPI2uXwuS7foe6J0fW 28 | FxKMkQKBgBzo3nCUC9nu48abop7wOBUERZAGVTdHEHA97wIgpSkAagMBrkf0f+fN 29 | hx00UefaJQLvJNPmUQ8t0rmdQX0HkGVAPA2Eek8e2fjpvzjhyUNKb47VllBBm/H/ 30 | qoQZOsKh8YWy373DPydoi9MsFal4E1Pi56co1At6hf4TICWJBedd 31 | -----END RSA PRIVATE KEY----- 32 | -------------------------------------------------------------------------------- /tests/credentials/test.mobileprovision: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/credentials/test.mobileprovision -------------------------------------------------------------------------------- /tests/credentials/test.mobileprovision.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AppIDName 6 | isign tests 7 | ApplicationIdentifierPrefix 8 | 9 | ISIGNTESTS 10 | 11 | CreationDate 12 | 2016-11-28T22:57:49Z 13 | Platform 14 | 15 | iOS 16 | 17 | DeveloperCertificates 18 | 19 | MIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNpZ25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRFU1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAyMjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3RzMRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkGA1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAwHgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byKpUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+xBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBWkcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/rUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcRBaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDlah3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzBPXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHLMaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1ywE4pd+A1hdAwzsqKr3xxZmisaV8yH 20 | 21 | Entitlements 22 | 23 | keychain-access-groups 24 | 25 | ISIGNTESTS.* 26 | 27 | get-task-allow 28 | 29 | application-identifier 30 | ISIGNTESTS.* 31 | com.apple.developer.team-identifier 32 | ISIGNTESTS 33 | 34 | ExpirationDate 35 | 2017-11-28T22:57:49Z 36 | Name 37 | RDC-Dev 38 | ProvisionedDevices 39 | 40 | e2cd3a02c1a3f69a5ff05bce3ea1b1092b30efe0 41 | 0a0fd3dcb248d3c001a586e8f638800e18c54efc 42 | 43 | TeamIdentifier 44 | 45 | ISIGNTESTS 46 | 47 | TeamName 48 | ISIGN OPEN SOURCE 49 | TimeToLive 50 | 365 51 | UUID 52 | f4d8aa37-45a7-4304-960c-1291e1a5a0f3 53 | Version 54 | 1 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /tests/credentials_std_names/README.rst: -------------------------------------------------------------------------------- 1 | These credentials exist to test the 'credentials directory' feature in isign. 2 | 3 | The credentials are copied from ../credentials and just have the correct names. 4 | -------------------------------------------------------------------------------- /tests/credentials_std_names/certificate.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: isign_tests 3 | localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 4 | subject=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com 5 | issuer=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com 6 | -----BEGIN CERTIFICATE----- 7 | MIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNp 8 | Z25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRF 9 | U1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFu 10 | Y2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAy 11 | MjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3Rz 12 | MRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkG 13 | A1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAw 14 | HgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEB 15 | BQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byK 16 | pUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+ 17 | xBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBW 18 | kcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/ 19 | rUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE 20 | 2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0P 21 | AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA 22 | A4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcR 23 | BaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDla 24 | h3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzB 25 | PXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHL 26 | MaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1yw 27 | E4pd+A1hdAwzsqKr3xxZmisaV8yH 28 | -----END CERTIFICATE----- 29 | -------------------------------------------------------------------------------- /tests/credentials_std_names/isign.mobileprovision: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/credentials_std_names/isign.mobileprovision -------------------------------------------------------------------------------- /tests/credentials_std_names/key.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: isign_tests 3 | localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 4 | Key Attributes: 5 | -----BEGIN RSA PRIVATE KEY----- 6 | MIIEowIBAAKCAQEA8oTKqrq3FIKEiyhW/S2AAjijwEMaoBTCqNRP0drVvIqlRL9h 7 | W0d5oL2jM81Kd2UB8W9SLBX4wPSs/OdmiNCcq1jLpEIhobJKjHoV42oWYv7EFRPB 8 | BpXYipkQpQktIMtjgTE9/3wst3GuJ7JRZH6V0DRVq2d7ppPGp4qMTBQpsFaRxImt 9 | gz0jhn9noAaiamH5uVdY6DSXLlCyHEnNcOOfuLwx1bSvLdikgcsOhImJ5b+tQ1IG 10 | IblvXHLdM2pKtSPIIriqvQcmo8VoN+7MIrJQlWdhkeS3X6pnWaZfYJZq+0Tb6ztR 11 | /9PDXR8yzNeNcog/u7GVM6Nt89+ATZDdFQJKiwIDAQABAoIBAQDtyhx5qJgIqSzS 12 | 0Vvx5KImC2ksA9/gZFq1dW9KQbreokcIEGqiOIPegvK5wSmpxcVQ+Kjmhyif8YiI 13 | dU/JCFsFeww5Y4pcZFfKQ46grA2FRW33iKX0Egr/YrO6TjQMesB3FVRH5HZn7DQp 14 | wiMiWSgFvLrfVJkeLLlU33lOw1pZBbAhNaZK+DQ2nuLDg1mIbJ1B0VRvEo5zVS4r 15 | CZo8otr3MAkdTbjhqaoGDZuRnjzd72Zl/VCxlg55IJP45WV2hHWt7ofH0RjQ4KSA 16 | XIuh9KJWf9f6vVv2oZ+nY6P6EA2mzIBKzlfpcPNvUeh+gW4Ln2kbsxnIp2VxU2D+ 17 | UH+oVclpAoGBAP+Risu98rg1et1Sh5oHe2MIZ18n2M01qhqdJx5fY28+7GHVTdvn 18 | BMaooojpxYJ/aEY2M5oZfG6twCpLN5+YTFsycDsdL5ALoMqGLDdBbtNjmVzQUzuN 19 | g0oZvu6Xi9qN9GGF84falS+tchAOGQahw+mpWRtqnmNI60geo5V/Ng+lAoGBAPLt 20 | m/vwM/s09XnFozfX2tdpWUjPUnDRCFWQBSNpnqjeUi4B/evMxXhZIT+z2Vg+cRru 21 | A4xLRJ2ZQbEYsTPxejCoMJsKD48pFi1KDDAN0HQSKPwKgwHoBJjIGoxb4gV5Uz0T 22 | FiXMp8667vI2O6VlQZYfvx1K4qsbjRBLQReyE9pvAoGAMVx5BFURtkaODoVML5HW 23 | YRBUduqJU0lUK4PC9HjUCb6LhXHfceOy5nPXwL32KfhVuYnqeY8Gm5HvlbulaKvP 24 | w6WAS8qdTyMP0U4M6Dc5IpcQHf8WtF/mxb8nQ4n9tx7H3rYyjUDIo8bKSxON/dvs 25 | rQrKbSMwqFiDKRDR46QIWwkCgYBL4l1vfcE/H3Pu7gXmU89Qqt/xFpIyG5n24F46 26 | iau+JHSXWpfvKLAmv/Da7VtfbWH3f5IsKPbuJAmZQJVaHHyG5oMIa0Qg/DypORBF 27 | kosjNukGkmIKHmgRMbDZV3prK1MNKQEqHZvtwAcUMky/hbnPI2uXwuS7foe6J0fW 28 | FxKMkQKBgBzo3nCUC9nu48abop7wOBUERZAGVTdHEHA97wIgpSkAagMBrkf0f+fN 29 | hx00UefaJQLvJNPmUQ8t0rmdQX0HkGVAPA2Eek8e2fjpvzjhyUNKb47VllBBm/H/ 30 | qoQZOsKh8YWy373DPydoi9MsFal4E1Pi56co1At6hf4TICWJBedd 31 | -----END RSA PRIVATE KEY----- 32 | -------------------------------------------------------------------------------- /tests/credentials_std_names_2/README.rst: -------------------------------------------------------------------------------- 1 | These credentials exist to test the 'multisign' feature in isign 2 | 3 | The credentials are copied from ../credentials_std_names, and exist solely to have 4 | a separate path to point to them. 5 | -------------------------------------------------------------------------------- /tests/credentials_std_names_2/certificate.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: isign_tests 3 | localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 4 | subject=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com 5 | issuer=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com 6 | -----BEGIN CERTIFICATE----- 7 | MIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNp 8 | Z25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRF 9 | U1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFu 10 | Y2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAy 11 | MjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3Rz 12 | MRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkG 13 | A1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAw 14 | HgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEB 15 | BQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byK 16 | pUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+ 17 | xBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBW 18 | kcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/ 19 | rUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE 20 | 2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0P 21 | AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA 22 | A4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcR 23 | BaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDla 24 | h3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzB 25 | PXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHL 26 | MaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1yw 27 | E4pd+A1hdAwzsqKr3xxZmisaV8yH 28 | -----END CERTIFICATE----- 29 | -------------------------------------------------------------------------------- /tests/credentials_std_names_2/isign.mobileprovision: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/credentials_std_names_2/isign.mobileprovision -------------------------------------------------------------------------------- /tests/credentials_std_names_2/key.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: isign_tests 3 | localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 4 | Key Attributes: 5 | -----BEGIN RSA PRIVATE KEY----- 6 | MIIEowIBAAKCAQEA8oTKqrq3FIKEiyhW/S2AAjijwEMaoBTCqNRP0drVvIqlRL9h 7 | W0d5oL2jM81Kd2UB8W9SLBX4wPSs/OdmiNCcq1jLpEIhobJKjHoV42oWYv7EFRPB 8 | BpXYipkQpQktIMtjgTE9/3wst3GuJ7JRZH6V0DRVq2d7ppPGp4qMTBQpsFaRxImt 9 | gz0jhn9noAaiamH5uVdY6DSXLlCyHEnNcOOfuLwx1bSvLdikgcsOhImJ5b+tQ1IG 10 | IblvXHLdM2pKtSPIIriqvQcmo8VoN+7MIrJQlWdhkeS3X6pnWaZfYJZq+0Tb6ztR 11 | /9PDXR8yzNeNcog/u7GVM6Nt89+ATZDdFQJKiwIDAQABAoIBAQDtyhx5qJgIqSzS 12 | 0Vvx5KImC2ksA9/gZFq1dW9KQbreokcIEGqiOIPegvK5wSmpxcVQ+Kjmhyif8YiI 13 | dU/JCFsFeww5Y4pcZFfKQ46grA2FRW33iKX0Egr/YrO6TjQMesB3FVRH5HZn7DQp 14 | wiMiWSgFvLrfVJkeLLlU33lOw1pZBbAhNaZK+DQ2nuLDg1mIbJ1B0VRvEo5zVS4r 15 | CZo8otr3MAkdTbjhqaoGDZuRnjzd72Zl/VCxlg55IJP45WV2hHWt7ofH0RjQ4KSA 16 | XIuh9KJWf9f6vVv2oZ+nY6P6EA2mzIBKzlfpcPNvUeh+gW4Ln2kbsxnIp2VxU2D+ 17 | UH+oVclpAoGBAP+Risu98rg1et1Sh5oHe2MIZ18n2M01qhqdJx5fY28+7GHVTdvn 18 | BMaooojpxYJ/aEY2M5oZfG6twCpLN5+YTFsycDsdL5ALoMqGLDdBbtNjmVzQUzuN 19 | g0oZvu6Xi9qN9GGF84falS+tchAOGQahw+mpWRtqnmNI60geo5V/Ng+lAoGBAPLt 20 | m/vwM/s09XnFozfX2tdpWUjPUnDRCFWQBSNpnqjeUi4B/evMxXhZIT+z2Vg+cRru 21 | A4xLRJ2ZQbEYsTPxejCoMJsKD48pFi1KDDAN0HQSKPwKgwHoBJjIGoxb4gV5Uz0T 22 | FiXMp8667vI2O6VlQZYfvx1K4qsbjRBLQReyE9pvAoGAMVx5BFURtkaODoVML5HW 23 | YRBUduqJU0lUK4PC9HjUCb6LhXHfceOy5nPXwL32KfhVuYnqeY8Gm5HvlbulaKvP 24 | w6WAS8qdTyMP0U4M6Dc5IpcQHf8WtF/mxb8nQ4n9tx7H3rYyjUDIo8bKSxON/dvs 25 | rQrKbSMwqFiDKRDR46QIWwkCgYBL4l1vfcE/H3Pu7gXmU89Qqt/xFpIyG5n24F46 26 | iau+JHSXWpfvKLAmv/Da7VtfbWH3f5IsKPbuJAmZQJVaHHyG5oMIa0Qg/DypORBF 27 | kosjNukGkmIKHmgRMbDZV3prK1MNKQEqHZvtwAcUMky/hbnPI2uXwuS7foe6J0fW 28 | FxKMkQKBgBzo3nCUC9nu48abop7wOBUERZAGVTdHEHA97wIgpSkAagMBrkf0f+fN 29 | hx00UefaJQLvJNPmUQ8t0rmdQX0HkGVAPA2Eek8e2fjpvzjhyUNKb47VllBBm/H/ 30 | qoQZOsKh8YWy373DPydoi9MsFal4E1Pi56co1At6hf4TICWJBedd 31 | -----END RSA PRIVATE KEY----- 32 | -------------------------------------------------------------------------------- /tests/generate_codesig_construct_txt.py: -------------------------------------------------------------------------------- 1 | # generate a string representation of a signature parse for an app - do this to generate 2 | # test files such as Test.app.codesig.construct.txt 3 | 4 | from isign_base_test import IsignBaseTest 5 | import isign.archive 6 | from isign.signable import Executable 7 | 8 | import logging 9 | 10 | FORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 11 | 12 | 13 | def log_to_stderr(level=logging.INFO): 14 | root = logging.getLogger() 15 | root.setLevel(level) 16 | handler = logging.StreamHandler() 17 | handler.setFormatter(FORMATTER) 18 | root.addHandler(handler) 19 | 20 | 21 | log_to_stderr(logging.DEBUG) 22 | log = logging.getLogger(__name__) 23 | log.debug("generating a signature parse for an app") 24 | app = isign.archive.AppArchive(IsignBaseTest.TEST_APP) 25 | executable = Executable(app.get_executable_path()) 26 | arch = executable.arches[0] 27 | codesig_str = str(arch['cmds']['LC_CODE_SIGNATURE']) 28 | print codesig_str 29 | -------------------------------------------------------------------------------- /tests/isignTestApp/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /tests/isignTestApp/README.md: -------------------------------------------------------------------------------- 1 | # isignTestApp 2 | 3 | Project to create a very simple test app for isign's test suite. 4 | 5 | Run `./build.sh` to create the necessary test app, app.zip, .ipa, and simulator app in the 6 | isign test directory (which is the containing directory). 7 | 8 | ## Caveats 9 | 10 | Currently, the TeamID specified is Neil Kandalgaonkar (neilk@neilk.net's) personal 11 | organization ID. For this to work, you would also need a provisioning profile installed 12 | in the right places on your system (the obvious thing is to use XCode). So... you pretty 13 | much need to be Neil to build this, unless you modify the `build.sh` script. 14 | 15 | For obvious reasons this is a problem going forward - we'll need to create some sort 16 | of Apple account which the community can use to sign the test apps. But on the assumption 17 | that we will only need to recreate the test apps very rarely, we're open sourcing it as it is, 18 | for now. 19 | -------------------------------------------------------------------------------- /tests/isignTestApp/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ./build.sh /path/to/isign 4 | 5 | # builds various archival formats of the isign test app 6 | # and puts them in the test directory of isign. You have to specify 7 | # isign's source directory on the command line 8 | # 9 | # Also you have to have the provisioning profile mentioned configured 10 | # in the app. 11 | # 12 | 13 | isign_test_dir=.. 14 | 15 | project=isignTestApp 16 | 17 | # this project just has one scheme configured, same name as project 18 | scheme=$project 19 | 20 | # This file must exist in this directory. 21 | export_options_plist=exportOptions.plist 22 | 23 | 24 | warn() { 25 | echo "$@" 1>&2; 26 | } 27 | 28 | platform_to_build_dir() { 29 | echo build/Release-$(echo $1 | tr -d "0-9."); 30 | } 31 | 32 | build_app() { 33 | local platform=$1; 34 | xcodebuild -project $project.xcodeproj -sdk $platform >&2; 35 | } 36 | 37 | copy_app() { 38 | local platform=$1; 39 | local target=$2; 40 | build_app $platform 41 | local build_dir=$(platform_to_build_dir $platform); 42 | rm -r $target 43 | cp -r $build_dir/$project.app $target; 44 | } 45 | 46 | copy_app_zip() { 47 | local platform=$1; 48 | local target=$2; 49 | build_app $platform 50 | local build_dir=$(platform_to_build_dir $platform); 51 | pushd $build_dir; 52 | rm -f app.zip; 53 | zip -r app.zip $project.app; 54 | popd; 55 | mv $build_dir/app.zip $target; 56 | } 57 | 58 | copy_ipa() { 59 | local platform=$1 60 | local target=$2 61 | 62 | archive_path=build/$project.xcarchive 63 | ipa_dir=build 64 | ipa_path=$ipa_dir/$project.ipa 65 | rm -f $ipa_path; 66 | 67 | xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform; 68 | xcodebuild archive -project $project.xcodeproj -scheme $scheme -archivePath $archive_path; 69 | xcodebuild -exportArchive \ 70 | -archivePath $archive_path \ 71 | -exportPath $ipa_dir \ 72 | -exportOptionsPlist $export_options_plist 73 | 74 | cp $ipa_path $target; 75 | } 76 | 77 | 78 | 79 | if [[ -n $rvm_path ]]; then 80 | warn "========"; 81 | warn "" 82 | warn "ACHTUNG!! " 83 | warn "rvm users! switch to the system version of ruby with: "; 84 | warn " $ rvm use system"; 85 | warn "otherwise your path to some ruby development tools like ipatool may be wrong"; 86 | warn "" 87 | warn "========"; 88 | fi 89 | 90 | copy_app iphoneos9.2 $isign_test_dir/Test.app; 91 | copy_app_zip iphoneos9.2 $isign_test_dir/Test.app.zip; 92 | copy_ipa iphoneos9.2 $isign_test_dir/Test.ipa; 93 | copy_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip; 94 | 95 | -------------------------------------------------------------------------------- /tests/isignTestApp/exportOptions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | teamID 6 | L37S4Z6BE9 7 | method 8 | development 9 | uploadSymbols 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/isignTestApp/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | isignTestApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 88F49D521C21E0220007422C 16 | 17 | primary 18 | 19 | 20 | 88F49D681C21E0220007422C 21 | 22 | primary 23 | 24 | 25 | 88F49D731C21E0220007422C 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // isignTestApp 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import UIKit 21 | 22 | @UIApplicationMain 23 | class AppDelegate: UIResponder, UIApplicationDelegate { 24 | 25 | var window: UIWindow? 26 | 27 | 28 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 29 | // Override point for customization after application launch. 30 | return true 31 | } 32 | 33 | func applicationWillResignActive(application: UIApplication) { 34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 36 | } 37 | 38 | func applicationDidEnterBackground(application: UIApplication) { 39 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | func applicationWillEnterForeground(application: UIApplication) { 44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | func applicationDidBecomeActive(application: UIApplication) { 48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 49 | } 50 | 51 | func applicationWillTerminate(application: UIApplication) { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/Assets.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "first.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/Assets.xcassets/first.imageset/first.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/isignTestApp/isignTestApp/Assets.xcassets/first.imageset/first.pdf -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/Assets.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "second.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/Assets.xcassets/second.imageset/second.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/isignTestApp/isignTestApp/Assets.xcassets/second.imageset/second.pdf -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/FirstViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.swift 3 | // isignTestApp 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import UIKit 21 | 22 | class FirstViewController: UIViewController { 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | // Do any additional setup after loading the view, typically from a nib. 27 | } 28 | 29 | override func didReceiveMemoryWarning() { 30 | super.didReceiveMemoryWarning() 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestApp/SecondViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.swift 3 | // isignTestApp 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import UIKit 21 | 22 | class SecondViewController: UIViewController { 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | // Do any additional setup after loading the view, typically from a nib. 27 | } 28 | 29 | override func didReceiveMemoryWarning() { 30 | super.didReceiveMemoryWarning() 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestAppTests/isignTestAppTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppTests.swift 3 | // isignTestAppTests 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import XCTest 21 | @testable import isignTestApp 22 | 23 | class isignTestAppTests: XCTestCase { 24 | 25 | override func setUp() { 26 | super.setUp() 27 | // Put setup code here. This method is called before the invocation of each test method in the class. 28 | } 29 | 30 | override func tearDown() { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | super.tearDown() 33 | } 34 | 35 | func testExample() { 36 | // This is an example of a functional test case. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | func testPerformanceExample() { 41 | // This is an example of a performance test case. 42 | self.measureBlock { 43 | // Put the code you want to measure the time of here. 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestAppUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/isignTestApp/isignTestAppUITests/isignTestAppUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppUITests.swift 3 | // isignTestAppUITests 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import XCTest 21 | 22 | class isignTestAppUITests: XCTestCase { 23 | 24 | override func setUp() { 25 | super.setUp() 26 | 27 | // Put setup code here. This method is called before the invocation of each test method in the class. 28 | 29 | // In UI tests it is usually best to stop immediately when a failure occurs. 30 | continueAfterFailure = false 31 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 32 | XCUIApplication().launch() 33 | 34 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 35 | } 36 | 37 | override func tearDown() { 38 | // Put teardown code here. This method is called after the invocation of each test method in the class. 39 | super.tearDown() 40 | } 41 | 42 | func testExample() { 43 | // Use recording to get started writing UI tests. 44 | // Use XCTAssert and related functions to verify your tests produce the correct results. 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | Pods 3 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '8.0' 3 | use_frameworks! 4 | 5 | target 'isignTestApp' do 6 | pod 'FontAwesome.swift', '~> 0.7' 7 | end 8 | 9 | target 'isignTestAppTests' do 10 | 11 | end 12 | 13 | target 'isignTestAppUITests' do 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - FontAwesome.swift (0.7.0) 3 | 4 | DEPENDENCIES: 5 | - FontAwesome.swift (~> 0.7) 6 | 7 | SPEC CHECKSUMS: 8 | FontAwesome.swift: c6e30a1a81716306ff9c81f2d38dda88ac5b8294 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/README.md: -------------------------------------------------------------------------------- 1 | # isignTestApp 2 | 3 | Project to create a very simple test app for isign's test suite. 4 | 5 | This is exactly like the isignTestApp, except that if it's working, it should 6 | also display a lightning bolt on the main screen. 7 | 8 | This app includes Github user @thii's 9 | [FontAwesome_swift Framework](https://github.com/thii/FontAwesome_swift), 10 | which crucially for our test, includes both a small resource (a font file) and 11 | a small amount of code. 12 | 13 | # Prerequisites 14 | 15 | This project uses frameworks from the [CocoaPods](http://cocoapods.org) system. 16 | To obtain the frameworks, install Cocoapods, then run `pod install` in this directory. 17 | 18 | # Building 19 | 20 | Run `./build.sh` to create the necessary test .ipa in the 21 | isign test directory (which is the containing directory). 22 | 23 | ## Caveats 24 | 25 | Currently, the TeamID specified is Neil Kandalgaonkar (neilk@neilk.net)'s' personal 26 | organization ID. For this to work, you would also need a provisioning profile installed 27 | in the right places on your system (the obvious thing is to use XCode). 28 | 29 | So... you pretty much need to be Neil to build this, unless you modify the `build.sh` 30 | script and the `exportOptions.plist` in this directory. 31 | 32 | For obvious reasons this is a problem going forward. Perhaps we'll need to create some sort 33 | of Apple account which the community can use to sign the test apps. But on the assumption 34 | that we will only need to recreate the test apps very rarely, we're open sourcing it as it is, 35 | for now. 36 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ./build.sh /path/to/isign 4 | 5 | # builds various archival formats of the isign test app 6 | # and puts them in the test directory of isign. You have to specify 7 | # isign's source directory on the command line 8 | # 9 | # Also you have to have the provisioning profile mentioned configured 10 | # in the app. 11 | # 12 | 13 | isign_test_dir=.. 14 | 15 | projectName=isignTestApp 16 | 17 | # workspace 18 | workspace=$projectName.xcworkspace 19 | 20 | # this projectName just has one scheme configured, same name as projectName 21 | scheme=$projectName 22 | 23 | # This file must exist in this directory. 24 | export_options_plist=exportOptions.plist 25 | 26 | warn() { 27 | echo "$@" 1>&2; 28 | } 29 | 30 | copy_ipa() { 31 | local platform=$1 32 | local target=$2 33 | 34 | archive_path=build/$projectName.xcarchive 35 | ipa_dir=build 36 | ipa_path=$ipa_dir/$projectName.ipa 37 | rm -f $ipa_path; 38 | 39 | xcodebuild clean -workspace $workspace \ 40 | -scheme $scheme \ 41 | -configuration Release \ 42 | -sdk $platform; 43 | xcodebuild archive -workspace $workspace \ 44 | -scheme $scheme \ 45 | -archivePath $archive_path; 46 | xcodebuild -exportArchive \ 47 | -archivePath $archive_path \ 48 | -exportPath $ipa_dir \ 49 | -exportOptionsPlist $export_options_plist; 50 | 51 | cp $ipa_path $target; 52 | } 53 | 54 | 55 | 56 | if [[ -n $rvm_path ]]; then 57 | warn "========"; 58 | warn "" 59 | warn "ACHTUNG!! " 60 | warn "rvm users! switch to the system version of ruby with: "; 61 | warn " $ rvm use system"; 62 | warn "otherwise your path to some ruby development tools like ipatool may be wrong"; 63 | warn "" 64 | warn "========"; 65 | fi 66 | 67 | copy_ipa iphoneos9.2 $isign_test_dir/TestWithFrameworks.ipa; 68 | 69 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/exportOptions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | teamID 6 | L37S4Z6BE9 7 | method 8 | development 9 | compileBitcode 10 | 11 | uploadSymbols 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/project.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | isignTestApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 88F49D521C21E0220007422C 16 | 17 | primary 18 | 19 | 20 | 88F49D681C21E0220007422C 21 | 22 | primary 23 | 24 | 25 | 88F49D731C21E0220007422C 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/isignTestAppWithFrameworks/isignTestApp.xcworkspace/xcuserdata/neilk.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // isignTestApp 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import UIKit 21 | 22 | @UIApplicationMain 23 | class AppDelegate: UIResponder, UIApplicationDelegate { 24 | 25 | var window: UIWindow? 26 | 27 | 28 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 29 | // Override point for customization after application launch. 30 | return true 31 | } 32 | 33 | func applicationWillResignActive(application: UIApplication) { 34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 36 | } 37 | 38 | func applicationDidEnterBackground(application: UIApplication) { 39 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | func applicationWillEnterForeground(application: UIApplication) { 44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | func applicationDidBecomeActive(application: UIApplication) { 48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 49 | } 50 | 51 | func applicationWillTerminate(application: UIApplication) { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "first.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/first.imageset/first.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/first.imageset/first.pdf -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "second.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/second.imageset/second.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryu2/isign/495e3145335aba4bb9241aef5baa0baaae7794d8/tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/second.imageset/second.pdf -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/FirstViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.swift 3 | // isignTestApp 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import UIKit 21 | import FontAwesome_swift 22 | 23 | class FirstViewController: UIViewController { 24 | 25 | @IBOutlet weak var boltLabel: UILabel! 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | boltLabel.font = UIFont.fontAwesomeOfSize(100); 30 | boltLabel.text = String.fontAwesomeIconWithName(FontAwesome.Bolt); 31 | boltLabel.textAlignment = NSTextAlignment.Center; 32 | } 33 | 34 | override func didReceiveMemoryWarning() { 35 | super.didReceiveMemoryWarning() 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestApp/SecondViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.swift 3 | // isignTestApp 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import UIKit 21 | 22 | class SecondViewController: UIViewController { 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | // Do any additional setup after loading the view, typically from a nib. 27 | } 28 | 29 | override func didReceiveMemoryWarning() { 30 | super.didReceiveMemoryWarning() 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestAppTests/isignTestAppTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppTests.swift 3 | // isignTestAppTests 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import XCTest 21 | @testable import isignTestApp 22 | 23 | class isignTestAppTests: XCTestCase { 24 | 25 | override func setUp() { 26 | super.setUp() 27 | // Put setup code here. This method is called before the invocation of each test method in the class. 28 | } 29 | 30 | override func tearDown() { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | super.tearDown() 33 | } 34 | 35 | func testExample() { 36 | // This is an example of a functional test case. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | func testPerformanceExample() { 41 | // This is an example of a performance test case. 42 | self.measureBlock { 43 | // Put the code you want to measure the time of here. 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestAppUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/isignTestAppWithFrameworks/isignTestAppUITests/isignTestAppUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // isignTestAppUITests.swift 3 | // isignTestAppUITests 4 | // 5 | // Copyright © 2015 Sauce Labs. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import XCTest 21 | 22 | class isignTestAppUITests: XCTestCase { 23 | 24 | override func setUp() { 25 | super.setUp() 26 | 27 | // Put setup code here. This method is called before the invocation of each test method in the class. 28 | 29 | // In UI tests it is usually best to stop immediately when a failure occurs. 30 | continueAfterFailure = false 31 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 32 | XCUIApplication().launch() 33 | 34 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 35 | } 36 | 37 | override func tearDown() { 38 | // Put teardown code here. This method is called after the invocation of each test method in the class. 39 | super.tearDown() 40 | } 41 | 42 | func testExample() { 43 | // Use recording to get started writing UI tests. 44 | // Use XCTAssert and related functions to verify your tests produce the correct results. 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tests/isign_base_test.py: -------------------------------------------------------------------------------- 1 | from os.path import dirname, exists, join, isdir 2 | from isign import isign 3 | import logging 4 | from monitor_temp_file import MonitorTempFile 5 | import os 6 | import shutil 7 | import tempfile 8 | import unittest 9 | 10 | log = logging.getLogger(__name__) 11 | 12 | 13 | class IsignBaseTest(unittest.TestCase): 14 | TEST_DIR = dirname(__file__) 15 | TEST_APP = join(TEST_DIR, 'Test.app') 16 | TEST_APP_CODESIG_STR = join(TEST_DIR, 17 | 'Test.app.codesig.construct.txt') 18 | TEST_APPZIP = TEST_APP + '.zip' 19 | TEST_IPA = join(TEST_DIR, 'Test.ipa') 20 | TEST_WITH_FRAMEWORKS_IPA = join(TEST_DIR, 'TestWithFrameworks.ipa') 21 | TEST_NONAPP_DIR = join(TEST_DIR, 'NotAnAppDir') 22 | TEST_NONAPP_TXT = join(TEST_DIR, 'NotAnApp.txt') 23 | TEST_NONAPP_IPA = join(TEST_DIR, 'NotAnApp.ipa') 24 | TEST_SIMULATOR_APP = join(TEST_DIR, 'TestSimulator.app.zip') 25 | KEY = join(TEST_DIR, 'credentials', 'test.key.pem') 26 | CERTIFICATE = join(TEST_DIR, 'credentials', 'test.cert.pem') 27 | PROVISIONING_PROFILE = join(TEST_DIR, 'credentials', 'test.mobileprovision') 28 | ERROR_KEY = '_errors' 29 | CREDENTIALS_DIR = join(TEST_DIR, 'credentials_std_names') 30 | CREDENTIALS_DIR_2 = join(TEST_DIR, 'credentials_std_names_2') 31 | 32 | TEST_UNSIGNED_THIN_APP = join(TEST_DIR, 'Test_unsigned_thin.app') 33 | TEST_UNSIGNED_FAT_APP = join(TEST_DIR, 'Test_unsigned_fat.app') 34 | 35 | 36 | # Fake Apple organizational unit 37 | OU = 'ISIGNTESTS' 38 | 39 | def setUp(self): 40 | """ this helps us monitor if we're not cleaning up temp files """ 41 | MonitorTempFile.start() 42 | 43 | def tearDown(self): 44 | """ remove monitor on tempfile creation """ 45 | remaining_temp_files = MonitorTempFile.get_temp_files() 46 | MonitorTempFile.stop() 47 | if len(remaining_temp_files) != 0: 48 | log.error("remaining temp files: %s", 49 | ', '.join(remaining_temp_files)) 50 | # assert len(remaining_temp_files) == 0 51 | 52 | def resign(self, filename, **args): 53 | """ resign with test credentials """ 54 | args.update({ 55 | "key": self.KEY, 56 | "certificate": self.CERTIFICATE, 57 | "provisioning_profile": self.PROVISIONING_PROFILE 58 | }) 59 | return isign.resign(filename, **args) 60 | 61 | def unlink(self, path): 62 | if exists(path): 63 | if isdir(path): 64 | shutil.rmtree(path) 65 | else: 66 | os.unlink(path) 67 | 68 | def get_temp_file(self, prefix='isign-test-'): 69 | """ just getting a file path that probably isn't in use """ 70 | (fd, path) = tempfile.mkstemp(prefix=prefix) 71 | os.close(fd) 72 | os.unlink(path) 73 | return path 74 | 75 | def get_temp_dir(self, prefix='isign-test-'): 76 | return tempfile.mkdtemp(prefix=prefix) 77 | -------------------------------------------------------------------------------- /tests/monitor_temp_file.py: -------------------------------------------------------------------------------- 1 | """" 2 | isign creates big temporary files, using the standard tempfile library. 3 | If they are not cleaned up, they can fill up the disk. This has 4 | already happened in production. :( 5 | 6 | This library monkey-patches tempfile to use our own temporary 7 | directory, so it's easy to test that we aren't leaving any temp files behind. 8 | """ 9 | import os 10 | import shutil 11 | import tempfile 12 | 13 | 14 | class MonitorTempFile(object): 15 | TEMP_DIR = None 16 | 17 | @classmethod 18 | def mkdtemp(cls, *args, **kwargs): 19 | """ ensure temp directories are subdirs of TEMP_DIR """ 20 | kwargs['dir'] = MonitorTempFile.TEMP_DIR 21 | return tempfile._original_mkdtemp(*args, **kwargs) 22 | 23 | @classmethod 24 | def mkstemp(cls, *args, **kwargs): 25 | """ ensure temp files are within TEMP_DIR """ 26 | kwargs['dir'] = MonitorTempFile.TEMP_DIR 27 | return tempfile._original_mkstemp(*args, **kwargs) 28 | 29 | @classmethod 30 | def NamedTemporaryFile(cls, *args, **kwargs): 31 | """ ensure named temp files are within TEMP_DIR """ 32 | kwargs['dir'] = MonitorTempFile.TEMP_DIR 33 | return tempfile._original_NamedTemporaryFile(*args, **kwargs) 34 | 35 | @classmethod 36 | def start(cls): 37 | """ swap a few methods in tempfile with our versions that limit them 38 | to a particular directory """ 39 | 40 | if hasattr(tempfile, '_is_patched') and tempfile._is_patched: 41 | raise Exception("need tempfile to be in unpatched state!") 42 | 43 | cls.TEMP_DIR = tempfile.mkdtemp(prefix='isign-test-run-') 44 | 45 | tempfile._original_mkdtemp = tempfile.mkdtemp 46 | tempfile.mkdtemp = MonitorTempFile.mkdtemp 47 | 48 | tempfile._original_mkstemp = tempfile.mkstemp 49 | tempfile.mkstemp = MonitorTempFile.mkstemp 50 | 51 | tempfile._original_NamedTemporaryFile = tempfile.NamedTemporaryFile 52 | tempfile.NamedTemporaryFile = MonitorTempFile.NamedTemporaryFile 53 | 54 | tempfile._is_patched = True 55 | 56 | @classmethod 57 | def stop(cls): 58 | """ restore a few methods in tempfile. opposite of _tempfile_patch """ 59 | tempfile.mkdtemp = tempfile._original_mkdtemp 60 | tempfile.mkstemp = tempfile._original_mkstemp 61 | tempfile.NamedTemporaryFile = tempfile._original_NamedTemporaryFile 62 | 63 | tempfile._is_patched = False 64 | 65 | shutil.rmtree(cls.TEMP_DIR) 66 | 67 | cls.TEMP_DIR = None 68 | 69 | @classmethod 70 | def get_temp_files(cls): 71 | return os.listdir(cls.TEMP_DIR) 72 | 73 | @classmethod 74 | def has_no_temp_files(cls): 75 | """ check if this test has created any temp files which 76 | aren't cleaned up """ 77 | if cls.TEMP_DIR is None: 78 | raise Exception("temp dir is None. Maybe call patch() first?") 79 | return len(cls.get_temp_files()) == 0 80 | -------------------------------------------------------------------------------- /tests/sample-entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | application-identifier 6 | ISIGNTEST.com.example.isigntest 7 | com.apple.developer.team-identifier 8 | ISIGNTEST 9 | get-task-allow 10 | 11 | keychain-access-groups 12 | 13 | ISIGNTEST.com.example.isigntest 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/test_archive.py: -------------------------------------------------------------------------------- 1 | from isign_base_test import IsignBaseTest 2 | from isign.archive import archive_factory, Archive, AppArchive, AppZipArchive, IpaArchive 3 | import logging 4 | 5 | log = logging.getLogger(__name__) 6 | 7 | 8 | class TestArchive(IsignBaseTest): 9 | 10 | def _test_good(self, filename, klass): 11 | archive = archive_factory(filename) 12 | assert archive is not None 13 | assert archive.__class__ is klass 14 | assert isinstance(archive, Archive) 15 | 16 | def test_archive_factory_app(self): 17 | self._test_good(self.TEST_APP, AppArchive) 18 | 19 | def test_archive_factory_appzip(self): 20 | self._test_good(self.TEST_APPZIP, AppZipArchive) 21 | 22 | def test_archive_factory_ipa(self): 23 | self._test_good(self.TEST_IPA, IpaArchive) 24 | 25 | def test_archive_factory_nonapp_dir(self): 26 | archive = archive_factory(self.TEST_NONAPP_DIR) 27 | assert archive is None 28 | 29 | def test_archive_factory_nonapp_ipa(self): 30 | archive = archive_factory(self.TEST_NONAPP_IPA) 31 | assert archive is None 32 | 33 | def test_archive_factory_nonapp_txt(self): 34 | archive = archive_factory(self.TEST_NONAPP_TXT) 35 | assert archive is None 36 | 37 | def test_archive_factory_nonapp_simulator_app(self): 38 | archive = archive_factory(self.TEST_SIMULATOR_APP) 39 | assert archive is None 40 | 41 | 42 | class TestBundleInfo(IsignBaseTest): 43 | 44 | def _test_bundle_info(self, filename): 45 | archive = archive_factory(filename) 46 | assert archive is not None 47 | assert archive.bundle_info is not None 48 | assert archive.bundle_info['CFBundleName'] == 'isignTestApp' 49 | 50 | def test_app_archive_info(self): 51 | self._test_bundle_info(self.TEST_APP) 52 | 53 | def test_appzip_archive_info(self): 54 | self._test_bundle_info(self.TEST_APPZIP) 55 | 56 | def test_ipa_archive_info(self): 57 | self._test_bundle_info(self.TEST_IPA) 58 | 59 | 60 | class TestArchivePrecheck(IsignBaseTest): 61 | 62 | def test_precheck_app(self): 63 | assert AppArchive.precheck(self.TEST_APP) 64 | 65 | def test_precheck_appzip(self): 66 | assert AppZipArchive.precheck(self.TEST_APPZIP) 67 | 68 | def test_precheck_ipa(self): 69 | assert IpaArchive.precheck(self.TEST_IPA) 70 | 71 | def test_bad_precheck_app(self): 72 | assert AppArchive.precheck(self.TEST_NONAPP_DIR) is False 73 | assert AppArchive.precheck(self.TEST_APPZIP) is False 74 | assert AppArchive.precheck(self.TEST_IPA) is False 75 | 76 | def test_bad_precheck_appzip(self): 77 | assert AppZipArchive.precheck(self.TEST_APP) is False 78 | assert AppZipArchive.precheck(self.TEST_IPA) is False 79 | 80 | def test_bad_precheck_ipa(self): 81 | assert IpaArchive.precheck(self.TEST_APP) is False 82 | assert IpaArchive.precheck(self.TEST_APPZIP) is False 83 | assert IpaArchive.precheck(self.TEST_NONAPP_IPA) is False 84 | -------------------------------------------------------------------------------- /tests/test_creds_dir.py: -------------------------------------------------------------------------------- 1 | from isign.exceptions import MissingCredentials 2 | from isign_base_test import IsignBaseTest 3 | from isign import isign 4 | import os 5 | from os.path import exists, join 6 | import logging 7 | 8 | log = logging.getLogger(__name__) 9 | 10 | 11 | class TestCredentialsDir(IsignBaseTest): 12 | 13 | def test_creds_dir(self): 14 | # this directory contains credentials with the standard names 15 | # key.pem, certificate.pem, isign.mobileprovision 16 | output_path = self.get_temp_file() 17 | isign.resign_with_creds_dir(self.TEST_IPA, 18 | self.CREDENTIALS_DIR, 19 | output_path=output_path) 20 | assert exists(output_path) 21 | assert os.path.getsize(output_path) > 0 22 | self.unlink(output_path) 23 | 24 | def test_bad_creds_dir(self): 25 | # while this contains credentials, they don't have standard names 26 | credentials_dir = join(self.TEST_DIR, 'credentials') 27 | output_path = self.get_temp_file() 28 | with self.assertRaises(MissingCredentials): 29 | isign.resign_with_creds_dir(self.TEST_IPA, credentials_dir, output_path=output_path) 30 | self.unlink(output_path) 31 | -------------------------------------------------------------------------------- /tests/test_entitlements.py: -------------------------------------------------------------------------------- 1 | from isign_base_test import IsignBaseTest 2 | from isign.bundle import App 3 | import logging 4 | 5 | log = logging.getLogger(__name__) 6 | 7 | 8 | class TestEntitlements(IsignBaseTest): 9 | def test_entitlements_extraction(self): 10 | entitlements = App.extract_entitlements(self.PROVISIONING_PROFILE) 11 | log.debug(entitlements) 12 | assert entitlements['application-identifier'] == 'ISIGNTESTS.*' 13 | assert entitlements['get-task-allow'] == True 14 | -------------------------------------------------------------------------------- /tests/test_helpers.py: -------------------------------------------------------------------------------- 1 | import isign.archive 2 | from isign.archive import AppZipArchive 3 | from isign.exceptions import MissingHelpers 4 | from isign_base_test import IsignBaseTest 5 | from distutils import spawn 6 | import logging 7 | 8 | 9 | log = logging.getLogger(__name__) 10 | 11 | 12 | class MissingHelpersArchive(AppZipArchive): 13 | """ An App whose helpers are not present """ 14 | helpers = ['a_file_that_should_never_be_present'] 15 | 16 | 17 | def dummy_find_executable(name): 18 | return '/dummy/path/to/name' 19 | 20 | 21 | class TestHelpers(IsignBaseTest): 22 | def test_helpers_is_present(self): 23 | """ test that missing helpers raises exception """ 24 | with self.assertRaises(MissingHelpers): 25 | MissingHelpersArchive.precheck(self.TEST_APPZIP) 26 | 27 | def test_helpers_become_present(self): 28 | """ test that we can install helpers without restart """ 29 | with self.assertRaises(MissingHelpers): 30 | MissingHelpersArchive.precheck(self.TEST_APPZIP) 31 | spawn._original_find_executable = spawn.find_executable 32 | spawn.find_executable = dummy_find_executable 33 | MissingHelpersArchive.precheck(self.TEST_APPZIP) 34 | if hasattr(spawn, '_original_find_executable'): 35 | spawn.find_executable = spawn._original_find_executable 36 | isign.archive.helper_paths = {} 37 | -------------------------------------------------------------------------------- /tests/test_multisign.py: -------------------------------------------------------------------------------- 1 | from isign_base_test import IsignBaseTest 2 | import os 3 | from os.path import exists 4 | from isign.multisign import multisign 5 | import logging 6 | 7 | log = logging.getLogger(__name__) 8 | 9 | 10 | class TestMultisign(IsignBaseTest): 11 | 12 | def test_multisign(self): 13 | output_path1 = self.get_temp_file() 14 | output_path2 = self.get_temp_file() 15 | creds_dir_to_output_paths = { 16 | self.CREDENTIALS_DIR: output_path1, 17 | self.CREDENTIALS_DIR_2: output_path2 18 | } 19 | results = multisign(self.TEST_IPA, creds_dir_to_output_paths) 20 | log.debug("results: %s", results) 21 | for output_path in [output_path1, output_path2]: 22 | assert exists(output_path) 23 | assert os.path.getsize(output_path) > 0 24 | self.unlink(output_path) 25 | -------------------------------------------------------------------------------- /tests/test_parsing.py: -------------------------------------------------------------------------------- 1 | from isign_base_test import IsignBaseTest 2 | import isign.bundle 3 | from isign.signable import Executable 4 | import logging 5 | 6 | log = logging.getLogger(__name__) 7 | 8 | 9 | class TestParsing(IsignBaseTest): 10 | """ This tests whether code signatures are parsed, by comparing 11 | stringified parses.""" 12 | # Tests the parse-before-resign functionality used in 13 | # bin/pprint_codesig, which isn't exposed nicely as such. 14 | # Also see generate_codesig_construct_txt.py, to generate 15 | # the string this tests for 16 | def test_app(self): 17 | with open(self.TEST_APP_CODESIG_STR, 'r') as f: 18 | expected_codesig_str = f.read().strip() 19 | bundle = isign.bundle.App(self.TEST_APP) 20 | executable = Executable(bundle, bundle.get_executable_path(), None) 21 | arch = executable.arches[0] 22 | codesig_str = str(arch['cmds']['LC_CODE_SIGNATURE']) 23 | self.assertEquals(expected_codesig_str, codesig_str) 24 | -------------------------------------------------------------------------------- /tests/test_public_interface.py: -------------------------------------------------------------------------------- 1 | from isign_base_test import IsignBaseTest 2 | import os 3 | from os.path import exists 4 | from isign import isign 5 | import logging 6 | 7 | log = logging.getLogger(__name__) 8 | 9 | 10 | class TestPublicInterface(IsignBaseTest): 11 | 12 | def _test_signable(self, filename, output_path): 13 | self.resign(filename, output_path=output_path) 14 | assert exists(output_path) 15 | assert os.path.getsize(output_path) > 0 16 | self.unlink(output_path) 17 | 18 | def _test_unsignable(self, filename, output_path): 19 | with self.assertRaises(isign.NotSignable): 20 | self.resign(filename, output_path=output_path) 21 | self.unlink(output_path) 22 | 23 | def test_app(self): 24 | self._test_signable(self.TEST_APP, self.get_temp_dir()) 25 | 26 | def test_app_ipa(self): 27 | self._test_signable(self.TEST_IPA, self.get_temp_file()) 28 | 29 | def test_app_with_frameworks_ipa(self): 30 | self._test_signable(self.TEST_WITH_FRAMEWORKS_IPA, self.get_temp_file()) 31 | 32 | def test_appzip(self): 33 | self._test_signable(self.TEST_APPZIP, self.get_temp_file()) 34 | 35 | def test_non_app_txt(self): 36 | self._test_unsignable(self.TEST_NONAPP_TXT, self.get_temp_file()) 37 | 38 | def test_non_app_ipa(self): 39 | self._test_unsignable(self.TEST_NONAPP_IPA, self.get_temp_file()) 40 | 41 | def test_simulator_app(self): 42 | self._test_unsignable(self.TEST_SIMULATOR_APP, self.get_temp_file()) 43 | -------------------------------------------------------------------------------- /tests/test_sig.py: -------------------------------------------------------------------------------- 1 | import isign 2 | from isign_base_test import IsignBaseTest 3 | from os.path import join 4 | 5 | 6 | class TestSigner(IsignBaseTest): 7 | 8 | def test_bad_signature(self): 9 | """ make openssl appear to return a bad signature """ 10 | old_openssl = isign.signer.OPENSSL 11 | try: 12 | signer = isign.signer.Signer( 13 | signer_key_file=self.KEY, 14 | signer_cert_file=self.CERTIFICATE, 15 | apple_cert_file=isign.isign.DEFAULT_APPLE_CERT_PATH) 16 | isign.signer.OPENSSL = join(self.TEST_DIR, "bad_openssl") 17 | with self.assertRaises(Exception): 18 | signer.sign("some data") 19 | finally: 20 | isign.signer.OPENSSL = old_openssl 21 | -------------------------------------------------------------------------------- /tests/test_versioning.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os.path 3 | import importlib 4 | import unittest 5 | 6 | tests_dir = os.path.abspath(os.path.dirname(__file__)) 7 | package_name = tests_dir.split(os.path.sep)[-2].replace('-', '_') 8 | package = importlib.import_module(package_name) 9 | 10 | 11 | class VersioningTestCase(unittest.TestCase): 12 | 13 | def assert_proper_attribute(self, attribute): 14 | try: 15 | assert getattr(package, attribute), ( 16 | "{} improperly set".format(attribute)) 17 | except AttributeError: 18 | assert False, "missing {}".format(attribute) 19 | 20 | def test_version_attribute(self): 21 | self.assert_proper_attribute("__version__") 22 | 23 | # test major, minor, and patch are numbers 24 | version_split = package.__version__.split(".")[:3] 25 | assert version_split, "__version__ is not set" 26 | for n in version_split: 27 | try: 28 | int(n) 29 | except ValueError: 30 | assert False, "'{}' is not an integer".format(n) 31 | 32 | def test_commit_attribute(self): 33 | self.assert_proper_attribute("__commit__") 34 | 35 | def test_build_attribute(self): 36 | self.assert_proper_attribute("__build__") 37 | 38 | 39 | if __name__ == '__main__': 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Figures out what the current version is, echoes that back, 4 | # and also writes a `version.json` file into the package. 5 | 6 | set -e 7 | MAJMIN_VERSION="1.6" 8 | 9 | pushd $(dirname $0) >/dev/null 10 | working_dir=$PWD 11 | name=$(basename $PWD) 12 | popd >/dev/null 13 | package=$(echo $name | sed 's/-/_/g') 14 | version_json="${working_dir}/${package}/version.json" 15 | 16 | version_suffix="" 17 | # official version 18 | if [[ "$JOB_NAME" = "${name}" ]] && [[ -n "$BUILD_TAG" ]]; then 19 | patch_version=0 20 | if [[ -n "$(git tag --list v$MAJMIN_VERSION.0)" ]]; then 21 | # number of commits since vMAJOR.MINOR.0 22 | patch_version=$(git rev-list --count $(git describe --tags --match "v${MAJMIN_VERSION}.0" | cut -f 1 -d -)...HEAD) 23 | fi 24 | # add post version if built before (i.e., already tagged) 25 | post_version=$(git tag --contain | wc -l | awk '{print $1}') 26 | test "$post_version" -gt 0 && version_suffix=".post${post_version}" 27 | # development version 28 | else 29 | if [[ -n "$(git tag --list 'v[0-9]*')" ]]; then 30 | recent_tag=$(git describe --tags --match 'v[0-9]*' | cut -f 1 -d -) 31 | majmin_version=$(echo $recent_tag | tr "v.-" " " | awk '{print $1"."$2}') 32 | patch_version=$(echo $recent_tag | tr "v.-" " " | awk '{print $3}') 33 | dev_version=$(git rev-list --count ${recent_tag}...HEAD) 34 | else # start of dev, nothing tagged 35 | majmin_version="0.0" 36 | patch_version="0" 37 | dev_version=$(git rev-list --count HEAD) 38 | fi 39 | version_suffix=".$(date '+%s').dev${dev_version}+${USER}" 40 | fi 41 | 42 | version="${majmin_version:-$MAJMIN_VERSION}.${patch_version}${version_suffix}" 43 | json='"version": "'$version'", "commit": "'$(git rev-parse HEAD)'", "build": "'${BUILD_TAG:-"dev"}'"' 44 | # write-out version.json 45 | echo "{${json}}" > $version_json 46 | 47 | style="$1" 48 | if [[ "$style" = "json" ]]; then 49 | cat $version_json 50 | else 51 | echo $version 52 | fi 53 | --------------------------------------------------------------------------------