예제 #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)
예제 #2
0
def test_sign_file_dummy(tmp_path, signing_keys):
    """Check that we can sign with an additional dummy certificate.

    The extra dummy certs are used by the stub installer.
    """
    test_file = DATA_DIR / "unsigned.exe"
    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,
                     "sha1",
                     certs,
                     signer,
                     crosscert=signing_keys[1])

    # Check that we have 2 certificates in the signature
    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"]) == 2
예제 #3
0
async def async_main(argv=None):
    """Main CLI entry point for signing (async)."""
    parser = build_parser()
    args = parser.parse_args(argv)

    logging.basicConfig(format="%(asctime)s - %(message)s",
                        level=args.loglevel)

    if not args.priv_key:
        if not (args.autograph_user and args.autograph_secret):
            parser.error(
                "--key, or all of --autograph-url, --autograph-user, and "
                "--autograph-secret must be specified")

    if not args.outfile:
        args.outfile = args.infile

    certs = []
    certs_data = open(args.certs, "rb").read()
    certs = load_pem_certs(certs_data)
    priv_key = load_private_key(open(args.priv_key, "rb").read())

    signer = key_signer(priv_key)

    with tempfile.TemporaryDirectory() as d:
        d = Path(d)
        if args.infile == "-":
            args.infile = d / "unsigned"
            with args.infile.open("wb") as f:
                _copy_stream(sys.stdin.buffer, f)
        else:
            args.infile = Path(args.infile)

        if args.outfile == "-":
            outfile = d / "signed"
        else:
            outfile = Path(args.outfile)

        r = await sign_file(
            args.infile,
            outfile,
            args.digest_algo,
            certs,
            signer,
            url=args.url,
            comment=args.comment,
            timestamp_style=args.timestamp,
        )

        # TODO: Extra cross-cert
        # TODO: Check with a cert chain
        if not r:
            return 1

        if args.outfile == "-":
            with outfile.open("rb") as f:
                _copy_stream(f, sys.stdout.buffer)

        return 0
예제 #4
0
def test_sign_file_badfile(tmp_path, signing_keys):
    """Verify that we can't sign non-exe files."""
    test_file = Path(__file__)
    signed_file = tmp_path / "signed.py"

    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 not sign_file(test_file, signed_file, "sha1", certs, signer)
예제 #5
0
async def test_sign(test_file, digest_algo, tmp_path, signing_keys):
    """Check that we can sign a PE file."""
    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())
    # TODO: Make sure multiple works
    cert = certs[0]

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

    with test_file.open("rb") as infile, signed_exe.open("wb+") as outfile:
        assert await sign_file(infile, outfile, digest_algo, cert, signer)

        assert verify_pefile(outfile)
예제 #6
0
def test_sign_file_twocerts(tmp_path, signing_keys):
    """Check that we can include multiple certificates."""
    test_file = DATA_DIR / "unsigned.exe"
    signed_exe = tmp_path / "signed.exe"

    priv_key = load_private_key(open(signing_keys[0], "rb").read())
    certs = load_pem_certs(open(DATA_DIR / "twocerts.pem", "rb").read())

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

    assert sign_file(test_file, signed_exe, "sha1", certs, signer)

    # Check that we have 2 certificates in the signature
    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"]) == 2
예제 #7
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)
예제 #8
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)