def run():
    """Fetch the proof for the supplied certificate."""
    #TODO(eranm): Attempt fetching the SCT for this chain if none was given.
    if FLAGS.sct:
        cert_sct = client_pb2.SignedCertificateTimestamp()
        sct_data = open(FLAGS.sct, 'rb').read()
        if FLAGS.binary_sct:
            tls_message.decode(sct_data, cert_sct)
        else:
            cert_sct.ParseFromString(sct_data)
        sct_timestamp = cert_sct.timestamp
        print 'SCT for cert:', cert_sct
    else:
        sct_timestamp = FLAGS.timestamp

    constructed_leaf = construct_leaf_from_file(FLAGS.cert, sct_timestamp)
    leaf_hash = merkle.TreeHasher().hash_leaf(constructed_leaf)
    if FLAGS.verbose:
        print "Leaf hash: %s" % (leaf_hash.encode("hex"))

    (sth, proof) = fetch_single_proof(leaf_hash, FLAGS.log_url)
    if FLAGS.verbose:
        print "Leaf index in tree is %d, proof has %d hashes" % (
            proof.leaf_index, len(proof.audit_path))
        print "Audit path: %s" % ([t.encode('hex') for t in proof.audit_path])

    verifier = merkle.MerkleVerifier()
    if verifier.verify_leaf_inclusion(constructed_leaf, proof.leaf_index,
                                      proof.audit_path, sth):
        print 'Proof verifies OK.'
    def test_verify_embedded_scts_valid_signature(self):
        sct = client_pb2.SignedCertificateTimestamp()
        tls_message.decode(read_testdata_file('test-embedded-pre-cert.proof'),
                           sct)

        result = self._test_verify_embedded_scts(
                    ['test-embedded-cert.pem', 'ca-cert.pem'])
        self.assertEqual(result, [(sct, True)])
예제 #3
0
def verify_sct(chain, sct_tls, log_key_pem):
    sct = client_pb2.SignedCertificateTimestamp()
    tls_message.decode(sct_tls, sct)

    log_key = pem.from_pem(log_key_pem, 'PUBLIC KEY')[0]
    key_info = verify.create_key_info_from_raw_key(log_key)

    lv = verify.LogVerifier(key_info)
    print lv.verify_sct(sct, chain)
예제 #4
0
def verify_sct(chain, sct_tls, log_key_pem):
    sct = client_pb2.SignedCertificateTimestamp()
    tls_message.decode(sct_tls, sct)

    key_info = client_pb2.KeyInfo()
    key_info.type = client_pb2.KeyInfo.ECDSA
    key_info.pem_key = log_key_pem

    lv = verify.LogVerifier(key_info)
    print lv.verify_sct(sct, chain)
예제 #5
0
def dump_sctlist(sct_list):
    """Prints the proto representation of the SCTs contained in sct_list.
       Arguments:
       sct_list the packed SignedCertificateTransparencyList structure.
    """
    tr = tls_message.TLSReader(sct_list)
    sctlist = client_pb2.SignedCertificateTimestampList()
    tr.read(sctlist)
    for s in sctlist.sct_list:
        sct = client_pb2.SignedCertificateTimestamp()
        tls_message.decode(s, sct)
        print(sct)
예제 #6
0
    def test_verify_sct_valid_signature(self):
        test_cert = cert.Certificate.from_pem_file(
            os.path.join(FLAGS.testdata_dir, 'test-cert.pem'))
        sct = client_pb2.SignedCertificateTimestamp()
        tls_message.decode(read_testdata_file('test-cert.proof'), sct)

        key_info = client_pb2.KeyInfo()
        key_info.type = client_pb2.KeyInfo.ECDSA
        key_info.pem_key = read_testdata_file('ct-server-key-public.pem')

        verifier = verify.LogVerifier(key_info)
        self.assertTrue(verifier.verify_sct(sct, test_cert))
    def test_verify_sth_for_bad_asn1_signature(self):
        # www.google.com certificate for which a bad SCT was issued.
        google_cert = (
            '-----BEGIN CERTIFICATE-----',
            'MIIEgDCCA2igAwIBAgIIdJ7+eILLLSgwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE',
            'BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl',
            'cm5ldCBBdXRob3JpdHkgRzIwHhcNMTUxMDA3MTExMDM4WhcNMTYwMTA1MDAwMDAw',
            'WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN',
            'TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3',
            'Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCR6Knj',
            'TG6eyvY6C1VO7daC0AbWe3cenr9y9lVFQH2ej5r87znUvep4pC/bmG71aTd25wds',
            'ScpclWNR4lkR9Ph45j8K+SjMXU7syiqFiWPWgVzyi4N3bXZw4w83RoTzfyUTn4Kx',
            '9nsQLmjVS4wUMSEpWBmYfORwUwMF8BYp5qSkIUogZTADPY7Qr8tmwEq8jLHv9z62',
            'SiYd9JEcGdhnajgXg/+/f+iIb1jhkbjsTjFJBHClgrtRqLZHSU1THZCK6iULTd1B',
            '4yBNvXcHDaSBTPUSvZvZXo/msKfOqd0fHtny1icgl5CSU0tZrZPteomMnLMGdLlN',
            'KHyqIX7XsAd3pNoXAgMBAAGjggFLMIIBRzAdBgNVHSUEFjAUBggrBgEFBQcDAQYI',
            'KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE',
            'XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0',
            'MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G',
            'A1UdDgQWBBSUPOkxr+tGC3JYs2JIdXVB2R+f8zAMBgNVHRMBAf8EAjAAMB8GA1Ud',
            'IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMCEGA1UdIAQaMBgwDAYKKwYBBAHW',
            'eQIFATAIBgZngQwBAgIwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29n',
            'bGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAfBoIl5qeaJ7NZ6hB',
            'WqeBZwbDV/DOHCPg3/84n8YGlfYdfXQpQdOWC5hfgEkkinBT0yp8dDTdXMUIT9Al',
            'ZMrxE54xJ1cU6FPuZPDWOnzV+6YEW6P9RnTbqKgYCNkHFiFwVvFRm5RTEGei5TLv',
            'l0zFDBusT/mgyvYBMIfW3vVPteEKKEz+aRCZHRiLAHbmJHj2+blVJeHGSF+eKN5q',
            'GWgk7/pMww4JAXsLQ0mmL8qdJKivuiNcyyhbr8IeERiVcItKqfBsX1nwyUnYFWY3',
            'HPkV+sXAPnpTGuxgYvTjcYDf8UO9lgDX5QubEFjjTuTIYAAabmc6Z4UKOS0O46Ne',
            'z28m7Q==',
            '-----END CERTIFICATE-----')
        # The SCT with the bad signature.
        sct_bytes = (
            '00ddeb1d2b7a0d4fa6208b81ad8168707e2e8e9d01d55c888d3d11c4cdb6ecbecc'
            '00000150421dfbb6000004030047304502200035de73784699d2ad8c3631aeda77'
            'f70b2c899492b16f051fd6d38d46afc892022100a4d1b58c63002e5d0862a9f623'
            'f67c8ccf5fc934bd28133fbc8f240aae4cab38'
        ).decode('hex')

        symantec_sct = client_pb2.SignedCertificateTimestamp()
        tls_message.decode(sct_bytes, symantec_sct)
        key_info = client_pb2.KeyInfo()
        key_info.type = client_pb2.KeyInfo.ECDSA
        key_info.pem_key = pem.to_pem(
            base64.decodestring(SYMANTEC_B64_KEY),
            'PUBLIC KEY')
        verifier = verify.LogVerifier(key_info)
        self.assertRaises(
            error.SignatureError,
            verifier.verify_sct,
            symantec_sct,
            [cert.Certificate.from_pem("\n".join(google_cert)),])
    def setUp(self):
        sct_proto = client_pb2.SignedCertificateTimestamp()
        sct_proto.version = client_pb2.V1
        sct_proto.id.key_id = (
            "a4b90990b418581487bb13a2cc67700a3c359804f91bdfb8e377cd0ec80ddc10"
            ).decode('hex')

        sct_proto.timestamp = 1365427532443
        sct_proto.signature.hash_algorithm = client_pb2.DigitallySigned.SHA256
        sct_proto.signature.sig_algorithm = client_pb2.DigitallySigned.ECDSA
        sct_proto.signature.signature = (
            "304502210089de897f603e590b1aa0d7c4236c2f697e90602795f7a469215fda5e"
            "460123fc022065ab501ce3dbaf49bd563d1c9ff0ac76120bc11f65a44122b3cd8b"
            "89fc77a48c").decode("hex")
        self._sct_proto = sct_proto
    def _test_verify_sct(self, proof, chain, fake_timestamp = None):
        sct = client_pb2.SignedCertificateTimestamp()
        tls_message.decode(read_testdata_file(proof), sct)
        if fake_timestamp is not None:
            sct.timestamp = fake_timestamp

        chain = map(lambda name: cert.Certificate.from_pem_file(
                        os.path.join(FLAGS.testdata_dir, name)), chain)

        key_info = client_pb2.KeyInfo()
        key_info.type = client_pb2.KeyInfo.ECDSA
        key_info.pem_key = read_testdata_file('ct-server-key-public.pem')

        verifier = verify.LogVerifier(key_info)
        return verifier.verify_sct(sct, chain)
예제 #10
0
 def _parse_sct(self, sct_response):
     sct_data = json.loads(sct_response)
     try:
         sct = client_pb2.SignedCertificateTimestamp()
         sct_version = sct_data["sct_version"]
         if sct_version != 0:
             raise InvalidResponseError(
                 "Unknown SCT version: %d" % sct_version)
         sct.version = client_pb2.V1
         sct.id.key_id = base64.b64decode(sct_data["id"])
         sct.timestamp = sct_data["timestamp"]
         hash_algorithm, sig_algorithm, sig_data = verify.decode_signature(
             base64.b64decode(sct_data["signature"]))
         sct.signature.hash_algorithm = hash_algorithm
         sct.signature.sig_algorithm = sig_algorithm
         sct.signature.signature = sig_data
         return sct
     except KeyError as e:
         raise InvalidResponseError("SCT Missing field: %s" % e)
예제 #11
0
    def verify_embedded_scts(self, chain):
        """Extract and verify SCTs embedded in an X.509 certificate.

        Args:
            chain: list of cert.Certificate instances.

        Returns:
            List of (SignedCertificateTimestamp, bool) pairs, one for each SCT
                present in the certificate. The boolean is True if the
                corresponding SCT is valid, False otherwise.

        Raises:
            ct.crypto.error.EncodingError: failed to encode signature input,
                or decode the signature.
            ct.crypto.error.IncompleteChainError: the chain is empty.
        """

        try:
            leaf_cert = chain[0]
        except IndexError:
            raise error.IncompleteChainError(
                "Chain must contain leaf certificate.")

        scts_blob = leaf_cert.embedded_sct_list()
        if scts_blob is None:
            return []

        scts = client_pb2.SignedCertificateTimestampList()
        tls_message.decode(scts_blob, scts)

        result = []
        for sct_blob in scts.sct_list:
            sct = client_pb2.SignedCertificateTimestamp()
            tls_message.decode(sct_blob, sct)

            try:
                self.verify_sct(sct, chain)
                result.append((sct, True))
            except error.VerifyError:
                result.append((sct, False))

        return result
예제 #12
0
    def test_correctly_encodes_sct_list_multiple_scts(self):
        first_sct = tls_message.encode(self._sct_proto)
        sct_proto_2 = client_pb2.SignedCertificateTimestamp()
        sct_proto_2.CopyFrom(self._sct_proto)
        sct_proto_2.timestamp = 1365427530000
        second_sct = tls_message.encode(sct_proto_2)

        sct_list = client_pb2.SignedCertificateTimestampList()
        sct_list.sct_list.extend([first_sct, second_sct])
        encoded_sct_list = tls_message.encode(sct_list)
        # First 2 bytes are list length prefix - 240 bytes in total
        # Next 2 bytes are the length of the first SCT: 118
        self.assertEqual(encoded_sct_list[:4], "00f00076".decode("hex"))
        first_sct_end = len(first_sct) + 4
        # The actual SCT
        self.assertEqual(encoded_sct_list[4:first_sct_end], first_sct)
        # Next 2 bytes are the length of the second SCT (118 again)
        self.assertEqual(encoded_sct_list[first_sct_end:first_sct_end + 2],
                         "0076".decode("hex"))
        # The 2nd SCT
        self.assertEqual(encoded_sct_list[first_sct_end + 2:], second_sct)
def read_sct_from_file(sct_file):
    cert_sct = client_pb2.SignedCertificateTimestamp()
    cert_sct.ParseFromString(open(sct_file, 'rb').read())
    return cert_sct