From ce317557283fb9455fb55b9cb4fc7e4cbafb328e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20B=C3=A4chtold?= Date: Sun, 10 Jul 2016 15:21:49 +0200 Subject: [PATCH] Test signature and creation of pkpass file. These tests can only run on a developer's computer and not on the public continuous integration system (Travis CI) because they rely on personal Apple Developer certificates and private key (which must be kept secret). It would not be wise to add theses files to git. In order to run these tests you must place the required files manually. See the tests about the location and names of the files. Test coverage increases from 65% to 75% with these tests. --- passbook/test/certificates/.gitignore | 2 + passbook/test/test_passbook.py | 86 ++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 passbook/test/certificates/.gitignore diff --git a/passbook/test/certificates/.gitignore b/passbook/test/certificates/.gitignore new file mode 100644 index 0000000..b4881ee --- /dev/null +++ b/passbook/test/certificates/.gitignore @@ -0,0 +1,2 @@ +password.txt +*.pem diff --git a/passbook/test/test_passbook.py b/passbook/test/test_passbook.py index 9f1fcda..822f576 100644 --- a/passbook/test/test_passbook.py +++ b/passbook/test/test_passbook.py @@ -6,11 +6,26 @@ import json except ImportError: import simplejson as json +import pytest +from M2Crypto import BIO +from M2Crypto import SMIME +from M2Crypto import X509 +from M2Crypto import m2 +from path import Path + from passbook.models import Barcode, BarcodeFormat, Pass, StoreCard -from path import Path cwd = Path(__file__).parent +wwdr_certificate = cwd / 'certificates/wwdr_certificate.pem' +certificate = cwd / 'certificates/certificate.pem' +key = cwd / 'certificates/key.pem' +password_file = cwd / 'certificates/password.txt' + + +def _certificates_mising(): + return not wwdr_certificate.exists() or not certificate.exists() or not key.exists() + def create_shell_pass(barcodeFormat=BarcodeFormat.CODE128): cardInfo = StoreCard() @@ -125,3 +140,72 @@ def test_files(): manifest_json = passfile._createManifest(passfile._createPassJson()) manifest = json.loads(manifest_json) assert '170eed23019542b0a2890a0bf753effea0db181a' == manifest['logo.png'] + + +@pytest.mark.skipif(_certificates_mising(), reason='Certificates missing') +def test_signing(): + """ + This test can only run locally if you provide your personal Apple Wallet + certificates, private key and password. It would not be wise to add + them to git. Store them in the files indicated below, they are ignored + by git. + """ + try: + with open(password_file) as file_: + password = file_.read().strip() + except IOError: + password = '' + + passfile = create_shell_pass() + manifest_json = passfile._createManifest(passfile._createPassJson()) + signature = passfile._createSignature( + manifest_json, + certificate, + key, + wwdr_certificate, + password, + ) + + smime_obj = SMIME.SMIME() + + store = X509.X509_Store() + store.load_info(str(wwdr_certificate)) + smime_obj.set_x509_store(store) + + signature_bio = BIO.MemoryBuffer(signature) + signature_p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(signature_bio._ptr()), 1) + + stack = signature_p7.get0_signers(X509.X509_Stack()) + smime_obj.set_x509_stack(stack) + + data_bio = BIO.MemoryBuffer(manifest_json) + + # PKCS7_NOVERIFY = do not verify the signers certificate of a signed message. + assert smime_obj.verify( + signature_p7, data_bio, flags=SMIME.PKCS7_NOVERIFY + ) == manifest_json + + tampered_manifest = '{"pass.json": "foobar"}' + data_bio = BIO.MemoryBuffer(tampered_manifest) + # Verification MUST fail! + with pytest.raises(SMIME.PKCS7_Error): + smime_obj.verify(signature_p7, data_bio, flags=SMIME.PKCS7_NOVERIFY) + + +@pytest.mark.skipif(_certificates_mising(), reason='Certificates missing') +def test_passbook_creation(): + """ + This test can only run locally if you provide your personal Apple Wallet + certificates, private key and password. It would not be wise to add + them to git. Store them in the files indicated below, they are ignored + by git. + """ + try: + with open(password_file) as file_: + password = file_.read().strip() + except IOError: + password = '' + + passfile = create_shell_pass() + passfile.addFile('icon.png', open(cwd / 'static/white_square.png', 'rb')) + passfile.create(certificate, key, wwdr_certificate, password)