Exemplo n.º 1
0
def test_add_signature_sha384(tmpdir, test_keys):
    tmpmar = tmpdir.join('test.mar')
    with open(TEST_MAR_XZ, 'rb') as f:
        with tmpmar.open('wb') as dst:
            add_signature_block(f, dst, 'sha384')

    with MarReader(tmpmar.open('rb')) as m:
        hashes = m.calculate_hashes()
    assert hashes == [(2, b'\x08>\x82\x8d$\xbb\xa6Cg\xca\x15L\x9c\xf1\xde\x170\xbe\xeb8]\x17\xb9\xfdB\xa9\xd6\xf1(y\'\xf44\x1f\x01c%\xd4\x92\x1avm!\t\xd9\xc4\xfbv')]

    h = hashes[0][1]

    priv, pub = test_keys[4096]
    sig = sign_hash(priv, h, 'sha384')

    sigfile = tmpdir.join('signature')
    with sigfile.open('wb') as f:
        f.write(sig)

    tmpmar = tmpdir.join('output.mar')
    cli.do_add_signature(TEST_MAR_XZ, str(tmpmar), str(sigfile))

    pubkey = tmpdir.join('pubkey')
    with pubkey.open('wb') as f:
        f.write(pub)
    assert cli.do_verify(str(tmpmar), [str(pubkey)])
Exemplo n.º 2
0
async def sign_mar384_with_autograph_hash(context, from_, fmt, to=None):
    """Signs a hash with autograph, injects it into the file, and writes the result to arg `to` or `from_` if `to` is None.

    Args:
        context (Context): the signing context
        from_ (str): the source file to sign
        fmt (str): the format to sign with
        to (str, optional): the target path to sign to. If None, overwrite
            `from_`. Defaults to None.

    Raises:
        Requests.RequestException: on failure
        SigningScriptError: when no suitable signing server is found for fmt

    Returns:
        str: the path to the signed file

    """
    cert_type = task.task_cert_type(context)
    # Get any key id that the task may have specified
    fmt, keyid = utils.split_autograph_format(fmt)
    # Call to check that we have a server available
    get_suitable_signing_servers(context.signing_servers, cert_type, [fmt],
                                 raise_on_empty_list=True)

    hash_algo, expected_signature_length = 'sha384', 512

    # Add a dummy signature into a temporary file (TODO: dedup with mardor.cli do_hash)
    with tempfile.TemporaryFile() as tmp:
        with open(from_, 'rb') as f:
            add_signature_block(f, tmp, hash_algo)

        tmp.seek(0)

        with MarReader(tmp) as m:
            hashes = m.calculate_hashes()
        h = hashes[0][1]

    signature = await sign_hash_with_autograph(context, h, fmt, keyid)

    # Add a signature to the MAR file (TODO: dedup with mardor.cli do_add_signature)
    if len(signature) != expected_signature_length:
        raise SigningScriptError(
            "signed mar hash signature has invalid length for hash algo {}. Got {} expected {}.".format(hash_algo, len(signature), expected_signature_length)
        )

    # use the tmp file in case param `to` is `from_` which causes stream errors
    tmp_dst = tempfile.NamedTemporaryFile(mode='w+b', delete=False)
    with open(tmp_dst.name, 'w+b') as dst:
        with open(from_, 'rb') as src:
            add_signature_block(src, dst, hash_algo, signature)

    to = to or from_
    shutil.copyfile(tmp_dst.name, to)
    os.unlink(tmp_dst.name)

    verify_mar_signature(cert_type, fmt, to, keyid)

    log.info("wrote mar with autograph signed hash %s to %s", from_, to)
    return to
Exemplo n.º 3
0
def do_add_signature(input_file, output_file, signature_file):
    """Add a signature to the MAR file."""
    signature = open(signature_file, 'rb').read()
    if len(signature) == 256:
        hash_algo = 'sha1'
    elif len(signature) == 512:
        hash_algo = 'sha384'
    else:
        raise ValueError()

    with open(output_file, 'w+b') as dst:
        with open(input_file, 'rb') as src:
            add_signature_block(src, dst, hash_algo, signature)
Exemplo n.º 4
0
def do_hash(hash_algo, marfile, asn1=False):
    """Output the hash for this MAR file."""
    # Add a dummy signature into a temporary file
    dst = tempfile.TemporaryFile()
    with open(marfile, 'rb') as f:
        add_signature_block(f, dst, hash_algo)

    dst.seek(0)

    with MarReader(dst) as m:
        hashes = m.calculate_hashes()
        h = hashes[0][1]
        if asn1:
            h = format_hash(h, hash_algo)

        print(base64.b64encode(h).decode('ascii'))
Exemplo n.º 5
0
def test_add_signature(tmpdir, mar_cue, test_keys):
    dest_mar = tmpdir.join('test.mar')

    # Add a dummy signature
    with mar_cue.open('rb') as s, dest_mar.open('w+b') as f:
        add_signature_block(s, f, 'sha384')

    with mar_cue.open('rb') as s, MarReader(s) as m, dest_mar.open(
            'rb') as f, MarReader(f) as m1:
        assert m.productinfo == m1.productinfo
        assert m.mardata.additional.sections == m1.mardata.additional.sections

        assert len(m.mardata.index.entries) == len(m1.mardata.index.entries)
        assert m1.mardata.signatures.count == 1

        hashes = m1.calculate_hashes()
        assert len(hashes) == 1
        assert hashes[0][
            1][:20] == b"\r\xa9x\x7f#\xf2m\x93a\xcc\xafJ=\x85\xa3Ss\xb43;"

    # Now sign the hash using the test keys, and add the signature back into the file
    private_key, public_key = test_keys[4096]

    sig = sign_hash(private_key, hashes[0][1], 'sha384')
    # Add the signature back into the file
    with mar_cue.open('rb') as s, dest_mar.open('w+b') as f:
        add_signature_block(s, f, 'sha384', sig)

    with dest_mar.open('rb') as f, MarReader(f) as m1:
        assert m1.verify(public_key)

    # Assert file contents are the same
    with dest_mar.open('rb') as f, MarReader(f) as m1:
        with MarReader(mar_cue.open('rb')) as m:
            offset_delta = m1.mardata.data_offset - m.mardata.data_offset
            for (e, e1) in zip(m.mardata.index.entries,
                               m1.mardata.index.entries):
                assert e.name == e1.name
                assert e.flags == e1.flags
                assert e.size == e1.size
                assert e.offset == e1.offset - offset_delta

                s = b''.join(m.extract_entry(e, decompress=None))
                s1 = b''.join(m1.extract_entry(e1, decompress=None))
                assert len(s) == e.size
                assert len(s1) == e1.size
                assert s == s1
Exemplo n.º 6
0
def test_add_signature(tmpdir, mar_cue, test_keys):
    dest_mar = tmpdir.join('test.mar')

    # Add a dummy signature
    with mar_cue.open('rb') as s, dest_mar.open('w+b') as f:
        add_signature_block(s, f, 'sha384')

    with mar_cue.open('rb') as s, MarReader(s) as m, dest_mar.open('rb') as f, MarReader(f) as m1:
        assert m.productinfo == m1.productinfo
        assert m.mardata.additional.sections == m1.mardata.additional.sections

        assert len(m.mardata.index.entries) == len(m1.mardata.index.entries)
        assert m1.mardata.signatures.count == 1

        hashes = m1.calculate_hashes()
        assert len(hashes) == 1
        assert hashes[0][1][:20] == b"\r\xa9x\x7f#\xf2m\x93a\xcc\xafJ=\x85\xa3Ss\xb43;"


    # Now sign the hash using the test keys, and add the signature back into the file
    private_key, public_key = test_keys[4096]

    sig = sign_hash(private_key, hashes[0][1], 'sha384')
    # Add the signature back into the file
    with mar_cue.open('rb') as s, dest_mar.open('w+b') as f:
        add_signature_block(s, f, 'sha384', sig)

    with dest_mar.open('rb') as f, MarReader(f) as m1:
        assert m1.verify(public_key)

    # Assert file contents are the same
    with dest_mar.open('rb') as f, MarReader(f) as m1:
        with MarReader(mar_cue.open('rb')) as m:
            offset_delta = m1.mardata.data_offset - m.mardata.data_offset
            for (e, e1) in zip(m.mardata.index.entries, m1.mardata.index.entries):
                assert e.name == e1.name
                assert e.flags == e1.flags
                assert e.size == e1.size
                assert e.offset == e1.offset - offset_delta

                s = b''.join(m.extract_entry(e, decompress=None))
                s1 = b''.join(m1.extract_entry(e1, decompress=None))
                assert len(s) == e.size
                assert len(s1) == e1.size
                assert s == s1
async def sign_mar384_with_autograph_hash(context, from_, fmt, to=None):
    """Signs a hash with autograph, injects it into the file, and writes the result to arg `to` or `from_` if `to` is None.

    Args:
        context (Context): the signing context
        from_ (str): the source file to sign
        fmt (str): the format to sign with
        to (str, optional): the target path to sign to. If None, overwrite
            `from_`. Defaults to None.

    Raises:
        Requests.RequestException: on failure
        SigningScriptError: when no suitable signing server is found for fmt

    Returns:
        str: the path to the signed file

    """
    log.info(
        "sign_mar384_with_autograph_hash(): signing {} with {}... using autograph /sign/hash"
        .format(from_, fmt))
    if not utils.is_autograph_signing_format(fmt):
        raise SigningScriptError(
            "No signing servers found supporting signing format {}".format(
                fmt))
    cert_type = task.task_cert_type(context)
    servers = get_suitable_signing_servers(context.signing_servers,
                                           cert_type, [fmt],
                                           raise_on_empty_list=True)
    s = servers[0]
    to = to or from_

    hash_algo, expected_signature_length = 'sha384', 512

    # Add a dummy signature into a temporary file (TODO: dedup with mardor.cli do_hash)
    tmp = tempfile.TemporaryFile()
    with open(from_, 'rb') as f:
        add_signature_block(f, tmp, hash_algo)

    tmp.seek(0)

    with MarReader(tmp) as m:
        hashes = m.calculate_hashes()
    h = hashes[0][1]

    tmp.close()

    # build and run the hash signature request
    sign_req = [{"input": base64.b64encode(h).decode('ascii')}]
    log.debug(
        "signing mar with hash alg %s using the default autograph keyid for %s",
        hash_algo, s.user)

    url = "%s/sign/hash" % s.server

    async def make_sign_req():
        auth = HawkAuth(id=s.user, key=s.password)
        with requests.Session() as session:
            r = session.post(url, json=sign_req, auth=auth)
            log.debug("Autograph response: {}".format(
                r.text[:120] if len(r.text) >= 120 else r.text))
            r.raise_for_status()
            return r.json()

    sign_resp = await retry_async(make_sign_req)
    signature = base64.b64decode(sign_resp[0]['signature'])

    # Add a signature to the MAR file (TODO: dedup with mardor.cli do_add_signature)
    if len(signature) != expected_signature_length:
        raise SigningScriptError(
            "signed mar hash signature has invalid length for hash algo {}. Got {} expected {}."
            .format(hash_algo, len(signature), expected_signature_length))

    # use the tmp file in case param `to` is `from_` which causes stream errors
    tmp_dst = tempfile.NamedTemporaryFile(mode='w+b', delete=False)
    with open(tmp_dst.name, 'w+b') as dst:
        with open(from_, 'rb') as src:
            add_signature_block(src, dst, hash_algo, signature)

    shutil.copyfile(tmp_dst.name, to)
    os.unlink(tmp_dst.name)

    verify_mar_signature(cert_type, fmt, to)

    log.info("wrote mar with autograph signed hash %s to %s", from_, to)
    return to