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)
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
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
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)
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)
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
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)
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)