import collections
import os
from tempfile import NamedTemporaryFile as tempfile

from utlz import flo

from ctutlz.utils import run_cmd


SctValidationResult = collections.namedtuple(
    typename='SctValidationResult',
    field_names=[
        'ee_cert',   # DER format
        'sct',       # type: Sct
        'log',       # type: Log
        'verified',  # True or False
        'output',    # type: str
        'cmd_res',   # CmdResult (for debugging) # FIXME remove
    ]
)


def find_log(sct, logs):
    for log in logs:
        if log.id_der == sct.log_id:
            return log
    return None


def verify_signature_CLUNKY(signature_input, signature, pubkey):
    # with-cascade requiered for python2.6 support
    with tempfile() as signature_input_file:
        with tempfile() as signature_file:
            with tempfile() as pubkey_file:

                signature_input_file.write(signature_input)
                signature_input_file.seek(0)

                signature_file.write(signature)
                signature_file.seek(0)

                pubkey_file.write(pubkey)
                pubkey_file.seek(0)

                openssl = os.environ.get('OPENSSL_CMD', 'openssl')
                cmd = flo('{openssl}  dgst -sha256 -verify {pubkey_file.name} '
                          '-signature {signature_file.name} '
                          '{signature_input_file.name}')
                res = run_cmd(cmd, timeout=30, max_try=3)
                # print(output)  # TODO DEBUG
                output = res.stdout_str + res.stderr_str
                if res.exitcode == 0:
                    return True, output, res
                return False, output, res


verify_signature = verify_signature_CLUNKY  # FIXME: use pyopenssl instead


def validate_sct(ee_cert, sct, logs, issuer_cert, sign_input_func):
    log = find_log(sct, logs)
    if log:
        verified, output, cmd_res = verify_signature(
            signature_input=sign_input_func(ee_cert, sct, issuer_cert),
            signature=sct.signature,
            pubkey=log.pubkey.encode('ascii')
        )
        return SctValidationResult(ee_cert, sct, log,
                                   verified, output, cmd_res)
    return SctValidationResult(ee_cert, sct, log,
                               verified=False, output='', cmd_res=None)


def validate_scts(ee_cert, scts, logs, issuer_cert, sign_input_func):
    if scts:
        return [validate_sct(ee_cert, sct, logs, issuer_cert, sign_input_func)
                for sct
                in scts]
    return []

@@ -75,16 +75,215 @@
 mpfile%0A%0A
+from OpenSSL.crypto import verify, X509, PKey, Error as OpenSSL_crypto_Error%0Afrom cryptography.hazmat.backends.openssl.backend import backend%0Afrom cryptography.hazmat.primitives import serialization%0A
 from utl
@@ -328,16 +328,27 @@
  run_cmd
+, CmdResult
 %0A%0A%0ASctVa
@@ -899,17 +899,16 @@
 de requi
-e
 red for 
@@ -1885,16 +1885,20 @@
 , res%0A%0A%0A
+def 
 verify_s
@@ -1909,66 +1909,654 @@
 ture
- = verify_signature_CLUNKY  # FIXME: use pyopenssl instead
+(signature_input, signature, pubkey):%0A    cryptography_key = serialization.load_pem_public_key(pubkey, backend)%0A%0A    pkey = PKey.from_cryptography_key(cryptography_key)%0A%0A    auxiliary_cert = X509()%0A    auxiliary_cert.set_pubkey(pkey)%0A%0A    try:%0A        verify(cert=auxiliary_cert,%0A               signature=signature,%0A               data=signature_input,%0A               digest='sha256')%0A    except OpenSSL_crypto_Error:%0A        cmd_res = CmdResult(1, None, None, None, None, None, None)%0A        return False, 'Verification Failure%5Cn', cmd_res%0A%0A    cmd_res = CmdResult(0, None, None, None, None, None, None)%0A    return True, 'Verified OK%5Cn', cmd_res
 %0A%0A%0Ad

verify a SCT signature wiht pyopenssl