ó
‚¾^Yc           @   sÈ   d  Z  d d l m Z d d l m Z d d l m Z d d l m Z d d l	 Z	 d d l
 Z
 d d l m Z d Z d Z d Z d Z e ƒ  Z d „  Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d S(   s¾   Pure Python crypto-related routines for oauth2client.

Uses the ``rsa``, ``pyasn1`` and ``pyasn1_modules`` packages
to parse PEM files storing PKCS#1 or PKCS#8 keys as well as
certificates.
iÿÿÿÿ(   t   decoder(   t   pem(   t   Certificate(   t   PrivateKeyInfoN(   t   _helperssô   \
PKCS12 format is not supported by the RSA library.
Either install PyOpenSSL, or please convert .p12 format
to .pem format:
    $ cat key.p12 | \
    >   openssl pkcs12 -nodes -nocerts -passin pass:notasecret | \
    >   openssl rsa > key.pem
i€   i@   i    i   i   i   i   i   s   -----BEGIN RSA PRIVATE KEY-----s   -----END RSA PRIVATE KEY-----s   -----BEGIN PRIVATE KEY-----s   -----END PRIVATE KEY-----c         C   s   t  |  ƒ } t ƒ  } x] t j j d | d ƒ D]C } |  | | d !} t d „  t t | ƒ Dƒ ƒ } | j | ƒ q. Wt	 | ƒ S(   sŠ   Converts an iterable of 1's and 0's to bytes.

    Combines the list 8 at a time, treating each group of 8 bits
    as a single byte.
    i    i   c         s   s   |  ] \ } } | | Vq d  S(   N(    (   t   .0t   valt   digit(    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pys	   <genexpr>;   s   (
   t   lent	   bytearrayt   sixt   movest   xranget   sumt   zipt   _POW2t   appendt   bytes(   t   bit_listt   num_bitst	   byte_valst   startt	   curr_bitst   char_val(    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyt   _bit_list_to_bytes1   s    		t   RsaVerifierc           B   s/   e  Z d  Z d „  Z d „  Z e d „  ƒ Z RS(   s   Verifies the signature on a message.

    Args:
        pubkey: rsa.key.PublicKey (or equiv), The public key to verify with.
    c         C   s   | |  _  d  S(   N(   t   _pubkey(   t   selft   pubkey(    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyt   __init__H   s    c         C   sW   t  j | d d ƒ} y t j j | | |  j ƒ SWn t t j j f k
 rR t SXd S(   sè  Verifies a message against a signature.

        Args:
            message: string or bytes, The message to verify. If string, will be
                     encoded to bytes as utf-8.
            signature: string or bytes, The signature on the message. If
                       string, will be encoded to bytes as utf-8.

        Returns:
            True if message was signed by the private key associated with the
            public key that this object was constructed with.
        t   encodings   utf-8N(	   R   t	   _to_bytest   rsat   pkcs1t   verifyR   t
   ValueErrort   VerificationErrort   False(   R   t   messaget	   signature(    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyR"   K   s
    c   	      C   s»   t  j | ƒ } | rœ t j j | d ƒ } t j | d t ƒ  ƒ\ } } | d k rf t d | ƒ ‚ n  | d d } t	 | d ƒ } t j
 j | d ƒ } n t j
 j | d	 ƒ } |  | ƒ S(
   s¿  Construct an RsaVerifier instance from a string.

        Args:
            key_pem: string, public key in PEM format.
            is_x509_cert: bool, True if key_pem is an X509 cert, otherwise it
                          is expected to be an RSA key in PEM format.

        Returns:
            RsaVerifier instance.

        Raises:
            ValueError: if the key_pem can't be parsed. In either case, error
                        will begin with 'No PEM start marker'. If
                        ``is_x509_cert`` is True, will fail to find the
                        "-----BEGIN CERTIFICATE-----" error, otherwise fails
                        to find "-----BEGIN RSA PUBLIC KEY-----".
        t   CERTIFICATEt   asn1Spect    s   Unused bytest   tbsCertificatet   subjectPublicKeyInfot   subjectPublicKeyt   DERt   PEM(   R   R   R    R   t   load_pemR    t   decodeR   R#   R   t	   PublicKeyt
   load_pkcs1(	   t   clst   key_pemt   is_x509_certt   dert	   asn1_certt	   remainingt	   cert_infot	   key_bytesR   (    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyt   from_string^   s    (   t   __name__t
   __module__t   __doc__R   R"   t   classmethodR<   (    (    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyR   A   s   		t	   RsaSignerc           B   s2   e  Z d  Z d „  Z d „  Z e d d „ ƒ Z RS(   s}   Signs messages with a private key.

    Args:
        pkey: rsa.key.PrivateKey (or equiv), The private key to sign with.
    c         C   s   | |  _  d  S(   N(   t   _key(   R   t   pkey(    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyR   ‡   s    c         C   s.   t  j | d d ƒ} t j j | |  j d ƒ S(   s°   Signs a message.

        Args:
            message: bytes, Message to be signed.

        Returns:
            string, The signature of the message for the given key.
        R   s   utf-8s   SHA-256(   R   R   R    R!   t   signRB   (   R   R&   (    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyRD   Š   s    	t
   notasecretc   	      C   së   t  j | ƒ } t j t j | ƒ t t ƒ \ } } | d k r] t j	 j
 j | d d ƒ} n„ | d k rÕ t j | d t ƒ\ } } | d k r¢ t d | ƒ ‚ n  | j d ƒ } t j	 j
 j | j ƒ  d d ƒ} n t d	 ƒ ‚ |  | ƒ S(
   sˆ  Construct an RsaSigner instance from a string.

        Args:
            key: string, private key in PEM format.
            password: string, password for private key file. Unused for PEM
                      files.

        Returns:
            RsaSigner instance.

        Raises:
            ValueError if the key cannot be parsed as PKCS#1 or PKCS#8 in
            PEM format.
        i    t   formatR.   i   R)   R*   s   Unused bytest
   privateKeys   No key could be detected.(   R   t   _from_bytesR   t   readPemBlocksFromFileR
   t   StringIOt   _PKCS1_MARKERt   _PKCS8_MARKERR    t   keyt
   PrivateKeyR3   R    R1   t   _PKCS8_SPECR#   t   getComponentByNamet   asOctets(	   R4   RM   t   passwordt	   marker_idR;   RC   t   key_infoR9   t	   pkey_info(    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyR<   –   s     (   R=   R>   R?   R   RD   R@   R<   (    (    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyRA   €   s
   		(   i€   i@   i    i   i   i   i   i   (   s   -----BEGIN RSA PRIVATE KEY-----s   -----END RSA PRIVATE KEY-----(   s   -----BEGIN PRIVATE KEY-----s   -----END PRIVATE KEY-----(   R?   t   pyasn1.codec.derR    t   pyasn1_modulesR   t   pyasn1_modules.rfc2459R   t   pyasn1_modules.rfc5208R   R    R
   t   oauth2clientR   t   _PKCS12_ERRORR   RK   RL   RO   R   t   objectR   RA   (    (    (    sE   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/_pure_python_crypt.pyt   <module>   s"   
  		?