ó
‚¾^Yc           @   s¤  d  Z  d d l Z d d l Z d d l Z d d l m Z d d l m Z e j Z e j Z d Z	 d Z
 d Z e j e ƒ Z d e f d „  ƒ  YZ d	 „  Z y/ d d
 l m Z e j Z e j Z e j Z Wn# e k
 rð d Z d Z e Z n Xy& d d l m Z e j Z e j Z Wn e k
 r6d Z d Z n Xe rLe Z e Z n! e rae Z e Z n e Z e Z d d „ Z d „  Z d „  Z d „  Z  d d „ Z! d S(   s)   Crypto-related routines for oauth2client.iÿÿÿÿN(   t   _helpers(   t   _pure_python_crypti,  i€Q t   AppIdentityErrorc           B   s   e  Z d  Z RS(   s!   Error to indicate crypto failure.(   t   __name__t
   __module__t   __doc__(    (    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyR   $   s   c          O   s   t  d ƒ ‚ d  S(   Ns#   pkcs12_key_as_pem requires OpenSSL.(   t   NotImplementedError(   t   argst   kwargs(    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyt   _bad_pkcs12_key_as_pem(   s    (   t   _openssl_crypt(   t   _pycrypto_cryptc         C   s±   i d d 6d d 6} | d k	 r- | | d <n  t j t j | ƒ ƒ t j t j | ƒ ƒ g } d j | ƒ } |  j | ƒ } | j t j | ƒ ƒ t j t	 | ƒ ƒ d j | ƒ S(   sR  Make a signed JWT.

    See http://self-issued.info/docs/draft-jones-json-web-token.html.

    Args:
        signer: crypt.Signer, Cryptographic signer.
        payload: dict, Dictionary of data to convert to JSON and then sign.
        key_id: string, (Optional) Key ID header.

    Returns:
        string, The JWT for the payload.
    t   JWTt   typt   RS256t   algt   kidt   .N(
   t   NoneR    t   _urlsafe_b64encodet   _json_encodet   joint   signt   appendt   loggert   debugt   str(   t   signert   payloadt   key_idt   headert   segmentst   signing_inputt	   signature(    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyt   make_signed_jwtJ   s    c         C   sL   x9 | D]1 } t  j | d t ƒ} | j |  | ƒ r d Sq Wt d ƒ ‚ d S(   s€  Verifies signed content using a list of certificates.

    Args:
        message: string or bytes, The message to verify.
        signature: string or bytes, The signature on the message.
        certs: iterable, certificates in PEM format.

    Raises:
        AppIdentityError: If none of the certificates can verify the message
                          against the signature.
    t   is_x509_certNs   Invalid token signature(   t   Verifiert   from_stringt   Truet   verifyR   (   t   messageR!   t   certst   pemt   verifier(    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyt   _verify_signaturei   s
    c         C   sq   | d k r d S|  j d ƒ } | d k rC t d j |  ƒ ƒ ‚ n  | | k rm t d j | | |  ƒ ƒ ‚ n  d S(   sA  Checks audience field from a JWT payload.

    Does nothing if the passed in ``audience`` is null.

    Args:
        payload_dict: dict, A dictionary containing a JWT payload.
        audience: string or NoneType, an audience to check for in
                  the JWT payload.

    Raises:
        AppIdentityError: If there is no ``'aud'`` field in the payload
                          dictionary but there is an ``audience`` to check.
        AppIdentityError: If the ``'aud'`` field in the payload dictionary
                          does not match the ``audience``.
    Nt   auds   No aud field in token: {0}s    Wrong recipient, {0} != {1}: {2}(   R   t   getR   t   format(   t   payload_dictt   audiencet   audience_in_payload(    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyt   _check_audience~   s    	c         C   s  t  t j ƒ  ƒ } |  j d ƒ } | d k rE t d j |  ƒ ƒ ‚ n  |  j d ƒ } | d k rx t d j |  ƒ ƒ ‚ n  | | t k r  t d j |  ƒ ƒ ‚ n  | t } | | k  rÔ t d j | | |  ƒ ƒ ‚ n  | t } | | k rt d j | | |  ƒ ƒ ‚ n  d S(	   sÜ  Verifies the issued at and expiration from a JWT payload.

    Makes sure the current time (in UTC) falls between the issued at and
    expiration for the JWT (with some skew allowed for via
    ``CLOCK_SKEW_SECS``).

    Args:
        payload_dict: dict, A dictionary containing a JWT payload.

    Raises:
        AppIdentityError: If there is no ``'iat'`` field in the payload
                          dictionary.
        AppIdentityError: If there is no ``'exp'`` field in the payload
                          dictionary.
        AppIdentityError: If the JWT expiration is too far in the future (i.e.
                          if the expiration would imply a token lifetime
                          longer than what is allowed.)
        AppIdentityError: If the token appears to have been issued in the
                          future (up to clock skew).
        AppIdentityError: If the token appears to have expired in the past
                          (up to clock skew).
    t   iats   No iat field in token: {0}t   exps   No exp field in token: {0}s    exp field too far in future: {0}s$   Token used too early, {0} < {1}: {2}s#   Token used too late, {0} > {1}: {2}N(   t   intt   timeR.   R   R   R/   t   MAX_TOKEN_LIFETIME_SECSt   CLOCK_SKEW_SECS(   R0   t   nowt	   issued_att
   expirationt   earliestt   latest(    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyt   _verify_time_rangeš   s(    
	
	c   	      C   sì   t  j |  ƒ }  |  j d ƒ d k r< t d j |  ƒ ƒ ‚ n  |  j d ƒ \ } } } | d | } t  j | ƒ } t  j | ƒ } y t j t  j	 | ƒ ƒ } Wn t d j | ƒ ƒ ‚ n Xt
 | | | j ƒ  ƒ t | ƒ t | | ƒ | S(   sþ  Verify a JWT against public certs.

    See http://self-issued.info/docs/draft-jones-json-web-token.html.

    Args:
        jwt: string, A JWT.
        certs: dict, Dictionary where values of public keys in PEM format.
        audience: string, The audience, 'aud', that this JWT should contain. If
                  None then the JWT's 'aud' parameter is not verified.

    Returns:
        dict, The deserialized JSON payload in the JWT.

    Raises:
        AppIdentityError: if any checks are failed.
    R   i   s&   Wrong number of segments in token: {0}s   Can't parse token: {0}(   R    t	   _to_bytest   countR   R/   t   splitt   _urlsafe_b64decodet   jsont   loadst   _from_bytesR,   t   valuesR?   R3   (	   t   jwtR)   R1   R   R   R!   t   message_to_signt   payload_bytesR0   (    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyt   verify_signed_jwt_with_certsÏ   s     
("   R   RD   t   loggingR7   t   oauth2clientR    R   t	   RsaSignert   RsaVerifierR9   t   AUTH_TOKEN_LIFETIME_SECSR8   t	   getLoggerR   R   t	   ExceptionR   R	   R
   t   OpenSSLSignert   OpenSSLVerifiert   pkcs12_key_as_pemt   ImportErrorR   R   t   PyCryptoSignert   PyCryptoVerifiert   SignerR$   R"   R,   R3   R?   RK   (    (    (    s8   /tmp/pip-build-kpPAdC/oauth2client/oauth2client/crypt.pyt   <module>   sT   					
	
					5