Example #1
0
def test_timestamp_old(test_file, digest_algo, tmp_path, signing_keys,
                       httpserver):
    """Verify that we can sign with old style timestamps."""
    signed_exe = tmp_path / "signed.exe"

    priv_key = load_private_key(open(signing_keys[0], "rb").read())
    certs = load_pem_certs(signing_keys[1].read_bytes())

    def signer(digest, digest_algo):
        return sign_signer_digest(priv_key, digest_algo, digest)

    httpserver.serve_content(
        (DATA_DIR / f"unsigned-{digest_algo}-ts-old.dat").read_bytes())
    assert sign_file(
        test_file,
        signed_exe,
        digest_algo,
        certs,
        signer,
        timestamp_style="old",
        # Comment this out to use a real timestamp server so that we can
        # capture a response
        timestamp_url=httpserver.url,
    )

    # Check that we have 3 certificates in the signature
    if is_pefile(test_file):
        with signed_exe.open("rb") as f:
            certificates = get_certificates(f)
            sigs = get_signatures_from_certificates(certificates)
            assert len(certificates) == 1
            assert len(sigs) == 1
            assert len(sigs[0]["certificates"]) == 3

            assert verify_pefile(f)
Example #2
0
def get_dummy_signature(infile,
                        digest_algo,
                        url=None,
                        comment=None,
                        crosscert=None):
    """Sign a file using dummy keys.

    This is useful as a way to get the structure of a signature, without having
    to create it from scratch. The dummy signature will also include relevent
    Authenticode specific checksums.

    Args:
        infile (str): Path to the file to generate a dummy signature for
        digest_algo (str): What digest algorithm to use. Should be one of
                           'sha1', or 'sha256'
        url (str): A URL to embed into the signature
        comment (str): A string to embed into the signature
        crosscert (str): Extra certificates to attach to the signature

    Returns:
        bytes of the dummy signature as a DER encoded ASN.1 structure

    """
    with tempfile.TemporaryDirectory() as d:
        d = Path(d)
        cert_file = d / "cert.pem"
        cert_file.write_text(DUMMY_KEY)
        infile = Path(infile)
        dest = d / ("signed1" + infile.suffix)
        run_sign_command(
            infile,
            dest,
            cert_file,
            cert_file,
            digest_algo,
            url=url,
            comment=comment,
            crosscert=crosscert,
        )
        sig = d / "signature"
        extract_signature(dest, sig)
        if is_pefile(infile):
            pefile_cert = certificate.parse(sig.read_bytes())
            return pefile_cert.data
        else:
            return sig.read_bytes()
Example #3
0
def test_timestamp_rfc3161(test_file, digest_algo, tmp_path, signing_keys,
                           httpserver):
    """Verify that we can sign with RFC3161 timestamps."""
    signed_exe = tmp_path / "signed.exe"

    priv_key = load_private_key(open(signing_keys[0], "rb").read())
    certs = load_pem_certs(signing_keys[1].read_bytes())

    def signer(digest, digest_algo):
        return sign_signer_digest(priv_key, digest_algo, digest)

    httpserver.serve_content(
        (DATA_DIR / f"unsigned-{digest_algo}-ts-rfc3161.dat").read_bytes())
    assert sign_file(
        test_file,
        signed_exe,
        digest_algo,
        certs,
        signer,
        timestamp_style="rfc3161",
        # Comment this out to use a real timestamp server so that we can
        # capture a response
        timestamp_url=httpserver.url,
    )

    # Check that we have 1 certificate in the signature,
    # and have a counterSignature section
    if is_pefile(test_file):
        with signed_exe.open("rb") as f:
            certificates = get_certificates(f)
            sigs = get_signatures_from_certificates(certificates)
            assert len(certificates) == 1
            assert len(sigs) == 1
            assert len(sigs[0]["certificates"]) == 1
            assert any((sigs[0]["signerInfos"][0]["unauthenticatedAttributes"]
                        [i]["type"] == id_timestampSignature) for i in range(
                            len(sigs[0]["signerInfos"][0]
                                ["unauthenticatedAttributes"])))

            assert verify_pefile(f)
Example #4
0
def test_sign_file(test_file, digest_algo, tmp_path, signing_keys):
    """Check that we can sign with the osslsign wrapper."""
    signed_exe = tmp_path / "signed.exe"

    priv_key = load_private_key(open(signing_keys[0], "rb").read())
    certs = load_pem_certs(signing_keys[1].read_bytes())

    def signer(digest, digest_algo):
        return sign_signer_digest(priv_key, digest_algo, digest)

    assert sign_file(test_file, signed_exe, digest_algo, certs, signer)

    # Check that we have 1 certificate in the signature
    if test_file in TEST_PE_FILES:
        assert is_pefile(test_file)
        with signed_exe.open("rb") as f:
            certificates = get_certificates(f)
            sigs = get_signatures_from_certificates(certificates)
            assert len(certificates) == 1
            assert len(sigs) == 1
            assert len(sigs[0]["certificates"]) == 1

            assert verify_pefile(f)
Example #5
0
def write_signature(infile, outfile, sig):
    """Writes a signature into a file.

    Args:
        infile (str): Path to the unsigned file
        outfile (str): Path to write the signature into
        sig (str): bytes of signature to add into the file

    Returns:
        Same as `winsign.sign.osslsigncode`_

    """
    # PE files need their signatures encapsulated
    if is_pefile(infile):
        padlen = (8 - len(sig) % 8) % 8
        sig += b"\x00" * padlen
        cert = certificate.build({
            "size": len(sig) + 8,
            "revision": "REV2",
            "certtype": "PKCS7",
            "data": sig
        })
    else:
        cert = sig
    with tempfile.NamedTemporaryFile() as sigfile:
        sigfile.write(cert)
        sigfile.flush()
        cmd = [
            "attach-signature",
            "-sigin",
            sigfile.name,
            "-in",
            infile,
            "-out",
            outfile,
        ]
        osslsigncode(cmd)