예제 #1
0
def signZip(appDirectory, outputFile, issuerName, manifestHashes,
            signatureHashes, pkcs7Hashes, doSign):
    """Given a directory containing the files to package up,
    an output filename to write to, the name of the issuer of
    the signing certificate, a list of hash algorithms to use in
    the manifest file, a similar list for the signature file,
    a similar list for the pkcs#7 signature, and whether or not
    to actually sign the resulting package, packages up the
    files in the directory and creates the output as
    appropriate."""
    mfEntries = []

    with zipfile.ZipFile(outputFile, 'w') as outZip:
        for (fullPath, internalPath) in walkDirectory(appDirectory):
            with open(fullPath) as inputFile:
                contents = inputFile.read()
            outZip.writestr(internalPath, contents)

            # Add the entry to the manifest we're building
            mfEntry = 'Name: %s\n' % internalPath
            for (hashFunc, name) in manifestHashes:
                base64hash = b64encode(hashFunc(contents).digest())
                mfEntry += '%s-Digest: %s\n' % (name, base64hash)
            mfEntries.append(mfEntry)

        # Just exit early if we're not actually signing.
        if not doSign:
            return

        mfContents = 'Manifest-Version: 1.0\n\n' + '\n'.join(mfEntries)
        sfContents = 'Signature-Version: 1.0\n'
        for (hashFunc, name) in signatureHashes:
            base64hash = b64encode(hashFunc(mfContents).digest())
            sfContents += '%s-Digest-Manifest: %s\n' % (name, base64hash)

        cmsSpecification = ''
        for name in pkcs7Hashes:
            hashFunc, _ = hashNameToFunctionAndIdentifier(name)
            cmsSpecification += '%s:%s\n' % (name,
                                             hashFunc(sfContents).hexdigest())
        cmsSpecification += 'signer:\n' + \
            'issuer:%s\n' % issuerName + \
            'subject:xpcshell signed app test signer\n' + \
            'extension:keyUsage:digitalSignature'
        cmsSpecificationStream = StringIO.StringIO()
        print >> cmsSpecificationStream, cmsSpecification
        cmsSpecificationStream.seek(0)
        cms = pycms.CMS(cmsSpecificationStream)
        p7 = cms.toDER()
        outZip.writestr('META-INF/A.RSA', p7)
        outZip.writestr('META-INF/A.SF', sfContents)
        outZip.writestr('META-INF/MANIFEST.MF', mfContents)
예제 #2
0
def signZip(appDirectory, outputFile, issuerName, rootName, manifestHashes,
            signatureHashes, pkcs7Hashes, coseAlgorithms, emptySignerInfos,
            headerPaddingFactor):
    """Given a directory containing the files to package up,
    an output filename to write to, the name of the issuer of
    the signing certificate, the name of trust anchor, a list of hash algorithms
    to use in the manifest file, a similar list for the signature file,
    a similar list for the pkcs#7 signature, a list of COSE signature algorithms
    to include, whether the pkcs#7 signer info should be kept empty, and how
    many MB to pad the manifests by (to test handling large manifest files),
    packages up the files in the directory and creates the output as
    appropriate."""
    # The header of each manifest starts with the magic string
    # 'Manifest-Version: 1.0' and ends with a blank line. There can be
    # essentially anything after the first line before the blank line.
    mfEntries = ['Manifest-Version: 1.0']
    if headerPaddingFactor > 0:
        # In this format, each line can only be 72 bytes long. We make
        # our padding 50 bytes per line (49 of content and one newline)
        # so the math is easy.
        singleLinePadding = 'a' * 49
        # 1000000 / 50 = 20000
        allPadding = [singleLinePadding] * (headerPaddingFactor * 20000)
        mfEntries.extend(allPadding)
    # Append the blank line.
    mfEntries.append('')

    with zipfile.ZipFile(outputFile, 'w', zipfile.ZIP_DEFLATED) as outZip:
        for (fullPath, internalPath) in walkDirectory(appDirectory):
            with open(fullPath, 'rb') as inputFile:
                contents = inputFile.read()
            outZip.writestr(internalPath, contents)

            # Add the entry to the manifest we're building
            addManifestEntry(internalPath, manifestHashes, contents, mfEntries)

        if len(coseAlgorithms) > 0:
            coseManifest = '\n'.join(mfEntries)
            outZip.writestr('META-INF/cose.manifest', coseManifest)
            coseManifest = six.ensure_binary(coseManifest)
            addManifestEntry('META-INF/cose.manifest', manifestHashes,
                             coseManifest, mfEntries)
            intermediates = []
            coseIssuerName = issuerName
            if rootName:
                coseIssuerName = 'xpcshell signed app test issuer'
                intermediate = getCert(coseIssuerName, 'default', rootName,
                                       False)
                intermediate = intermediate.toDER()
                intermediates.append(intermediate)
            signatures = [
                coseAlgorithmToSignatureParams(coseAlgorithm, coseIssuerName)
                for coseAlgorithm in coseAlgorithms
            ]
            coseSignatureBytes = coseSig(coseManifest, intermediates,
                                         signatures)
            outZip.writestr('META-INF/cose.sig', coseSignatureBytes)
            addManifestEntry('META-INF/cose.sig', manifestHashes,
                             coseSignatureBytes, mfEntries)

        if len(pkcs7Hashes) != 0 or emptySignerInfos:
            mfContents = '\n'.join(mfEntries)
            sfContents = 'Signature-Version: 1.0\n'
            for (hashFunc, name) in signatureHashes:
                hashed = hashFunc(six.ensure_binary(mfContents)).digest()
                base64hash = b64encode(hashed).decode("ascii")
                sfContents += '%s-Digest-Manifest: %s\n' % (name, base64hash)

            cmsSpecification = ''
            for name in pkcs7Hashes:
                hashFunc, _ = hashNameToFunctionAndIdentifier(name)
                cmsSpecification += '%s:%s\n' % (
                    name, hashFunc(six.ensure_binary(sfContents)).hexdigest())
            cmsSpecification += 'signer:\n' + \
                'issuer:%s\n' % issuerName + \
                'subject:xpcshell signed app test signer\n' + \
                'extension:keyUsage:digitalSignature'
            cmsSpecificationStream = StringIO()
            print(cmsSpecification, file=cmsSpecificationStream)
            cmsSpecificationStream.seek(0)
            cms = pycms.CMS(cmsSpecificationStream)
            p7 = cms.toDER()
            outZip.writestr('META-INF/A.RSA', p7)
            outZip.writestr('META-INF/A.SF', sfContents)
            outZip.writestr('META-INF/MANIFEST.MF', mfContents)
예제 #3
0
def signZip(appDirectory, outputFile, issuerName, manifestHashes,
            signatureHashes, pkcs7Hashes, doSign, coseAlgorithms):
    """Given a directory containing the files to package up,
    an output filename to write to, the name of the issuer of
    the signing certificate, a list of hash algorithms to use in
    the manifest file, a similar list for the signature file,
    a similar list for the pkcs#7 signature, whether or not to
    actually sign the resulting package, and a list of COSE
    signature algorithms to include, packages up the files in the
    directory and creates the output as appropriate."""
    # This ensures each manifest file starts with the magic string and
    # then a blank line.
    mfEntries = ['Manifest-Version: 1.0', '']

    with zipfile.ZipFile(outputFile, 'w') as outZip:
        for (fullPath, internalPath) in walkDirectory(appDirectory):
            with open(fullPath) as inputFile:
                contents = inputFile.read()
            outZip.writestr(internalPath, contents)

            # Add the entry to the manifest we're building
            addManifestEntry(internalPath, manifestHashes, contents, mfEntries)

        # Just exit early if we're not actually signing.
        if not doSign:
            return

        if len(coseAlgorithms) > 0:
            coseManifest = '\n'.join(mfEntries)
            outZip.writestr('META-INF/cose.manifest', coseManifest)
            addManifestEntry('META-INF/cose.manifest', manifestHashes,
                             coseManifest, mfEntries)
            signatures = map(
                lambda coseAlgorithm: coseAlgorithmToSignatureParams(
                    coseAlgorithm, issuerName), coseAlgorithms)
            coseSignatureBytes = coseSig(coseManifest, [], signatures)
            outZip.writestr('META-INF/cose.sig', coseSignatureBytes)
            addManifestEntry('META-INF/cose.sig', manifestHashes,
                             coseSignatureBytes, mfEntries)

        mfContents = '\n'.join(mfEntries)
        sfContents = 'Signature-Version: 1.0\n'
        for (hashFunc, name) in signatureHashes:
            base64hash = b64encode(hashFunc(mfContents).digest())
            sfContents += '%s-Digest-Manifest: %s\n' % (name, base64hash)

        cmsSpecification = ''
        for name in pkcs7Hashes:
            hashFunc, _ = hashNameToFunctionAndIdentifier(name)
            cmsSpecification += '%s:%s\n' % (name,
                                             hashFunc(sfContents).hexdigest())
        cmsSpecification += 'signer:\n' + \
            'issuer:%s\n' % issuerName + \
            'subject:xpcshell signed app test signer\n' + \
            'extension:keyUsage:digitalSignature'
        cmsSpecificationStream = StringIO.StringIO()
        print >> cmsSpecificationStream, cmsSpecification
        cmsSpecificationStream.seek(0)
        cms = pycms.CMS(cmsSpecificationStream)
        p7 = cms.toDER()
        outZip.writestr('META-INF/A.RSA', p7)
        outZip.writestr('META-INF/A.SF', sfContents)
        outZip.writestr('META-INF/MANIFEST.MF', mfContents)