o
    F                      @   s  d Z ddlZddlZddlZddlmZ dZdZdZe	e
ZG dd deZdd	 Zzdd
lmZ ejZejZejZW n eyK   dZdZeZY nw erSeZeZn$zddlmZ ejZejZW n eyv   ddlmZ ejZejZY nw dddZdd Zdd Zdd ZdddZ dS )z)Crypto-related routines for oauth2client.    N)_helpersi,  iQ c                   @   s   e Zd ZdZdS )AppIdentityErrorz!Error to indicate crypto failure.N)__name__
__module____qualname____doc__ r   r   ;/tmp/google-cloud-sdk/lib/third_party/oauth2client/crypt.pyr       s    r   c                  O   s   t d)Nz#pkcs12_key_as_pem requires OpenSSL.)NotImplementedError)argskwargsr   r   r	   _bad_pkcs12_key_as_pem$   s   r   )_openssl_crypt)_pycrypto_crypt)_pure_python_cryptc                 C   sv   ddd}|dur||d< t t |t t |g}d|}| |}|t | tt| d|S )aR  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.
    JWTRS256)typalgNkid   .)	r   _urlsafe_b64encode_json_encodejoinsignappendloggerdebugstr)signerpayloadkey_idheadersegmentssigning_input	signaturer   r   r	   make_signed_jwtA   s   



r&   c                 C   s2   |D ]}t j|dd}|| |r dS qtd)a  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_certNzInvalid token signature)Verifierfrom_stringverifyr   )messager%   certspemverifierr   r   r	   _verify_signature`   s   r/   c                 C   sJ   |du rdS |  d}|du rtd| ||kr#td||| dS )aA  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``.
    NaudzNo aud field in token: {0}z Wrong recipient, {0} != {1}: {2})getr   format)payload_dictaudienceaudience_in_payloadr   r   r	   _check_audienceu   s   
r6   c                 C   s   t t }| d}|du rtd| | d}|du r&td| ||t kr3td| |t }||k rDtd||| |t }||krUtd||| dS )	a  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).
    iatNzNo iat field in token: {0}expzNo exp field in token: {0}z exp field too far in future: {0}z$Token used too early, {0} < {1}: {2}z#Token used too late, {0} > {1}: {2})inttimer1   r   r2   MAX_TOKEN_LIFETIME_SECSCLOCK_SKEW_SECS)r3   now	issued_at
expirationearliestlatestr   r   r	   _verify_time_range   s4   

rB   c           	      C   s   t | } | ddkrtd| | d\}}}|d | }t |}t |}z
tt 	|}W n
   td|t
|||  t| t|| |S )a  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      z&Wrong number of segments in token: {0}zCan't parse token: {0})r   	_to_bytescountr   r2   split_urlsafe_b64decodejsonloads_from_bytesr/   valuesrB   r6   )	jwtr,   r4   r"   r    r%   message_to_signpayload_bytesr3   r   r   r	   verify_signed_jwt_with_certs   s"   



rO   )N)!r   rH   loggingr:   oauth2clientr   r<   AUTH_TOKEN_LIFETIME_SECSr;   	getLoggerr   r   	Exceptionr   r   r   OpenSSLSignerOpenSSLVerifierpkcs12_key_as_pemImportErrorSignerr(   r   PyCryptoSignerPyCryptoVerifierr   	RsaSignerRsaVerifierr&   r/   r6   rB   rO   r   r   r   r	   <module>   sL   




5