#!/usr/bin/env python2

import binascii
import json
import os
import ssl
import sys
try:
    import libnacl
    import requests
    __import__('pyasn1')  # not using module itself
except ImportError:
    sys.stderr.write(
        'Please install all dependancies (pip install -r requirements.txt):\n')
    raise

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
from pyasn1.type import univ, namedtype
from pyasn1.codec.der import decoder as der_decoder


class SaneTLS(HTTPAdapter):

    """By default, requests doesn't set sane defaults for TLS.

    We'll at least make sure that Python is using TLSv1. Your Python stack may
    or may not include support for the TLSv1 protocol.
    """

    def __init__(self, ca_certs):
        """Construct a new SantTLS instance."""
        super(SaneTLS, self).__init__()

    def init_poolmanager(self, connections, maxsize, block=False):
        """Initialize a new PoolManager instance to satisfy urllib3."""
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            ssl_version=ssl.PROTOCOL_TLSv1,
        )


# Our sane requests handler
sane = requests.Session()

# Python's json encoder doesn't understand bytes (which should default to a
# base64 encoded string).
json_bytes = lambda b: binascii.b2a_base64(b).rstrip().decode('utf-8')


class Key(univ.Sequence):

    """ASN.1 sequence for a serialized key."""

    componentType = namedtype.NamedTypes(
        namedtype.NamedType('id', univ.ObjectIdentifier()),
        namedtype.NamedType('publicKey', univ.OctetString()),
        namedtype.OptionalNamedType('privateKey', univ.OctetString()),
    )


class Client(object):

    """Secrets client."""

    OIDPrivateKey = univ.ObjectIdentifier('1.3.6.1.4.1.27266.11.17.2')
    OIDPublicKey = univ.ObjectIdentifier('1.3.6.1.4.1.27266.11.17.1')
    PEMPrivateKey = "SECRETS PRIVATE KEY"
    PEMPublicKey = "SECRETS PUBLIC KEY"

    def __init__(self, keyfile, baseurl, verify=None):
        """Initialize a new secrets client.

        Supplied are a efault private key and base URL.
        """
        self.keyfile = keyfile
        self.baseurl = baseurl
        self.verify = verify
        self.key = Client.loadKeyFile(self.PEMPrivateKey, self.keyfile)

        if self.key.getComponentByName('id') != self.OIDPrivateKey:
            raise TypeError(
                'Key file {0} does not contain a SECRETS private key'.format(
                    keyfile))

        self.publicKey = self.key.getComponentByName('publicKey').asOctets()
        self.publicKeyBase64 = binascii.b2a_base64(self.publicKey).rstrip()
        self.privateKey = self.key.getComponentByName('privateKey').asOctets()

        if self.baseurl.endswith('/'):