o
                         @   sl   d 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
dad	d
 ZG dd deZG dd deZdS )zPure 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.
    )pemN)_helpersz\
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
)   @                      )z-----BEGIN RSA PRIVATE KEY-----z-----END RSA PRIVATE KEY-----)z-----BEGIN PRIVATE KEY-----z-----END PRIVATE KEY-----c                 C   s^   t | }t }tjd|dD ]}| ||d  }tdd tt|D }|| qt	|S )zConverts 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.
    r   r   c                 s   s    | ]	\}}|| V  qd S N ).0valdigitr   r   H/tmp/google-cloud-sdk/lib/third_party/oauth2client/_pure_python_crypt.py	<genexpr>8   s    z%_bit_list_to_bytes.<locals>.<genexpr>)
len	bytearraysixmovesxrangesumzip_POW2appendbytes)bit_listnum_bits	byte_valsstart	curr_bitschar_valr   r   r   _bit_list_to_bytes.   s   r#   c                   @   s,   e Zd ZdZdd Zdd Zedd ZdS )	RsaVerifierzVerifies the signature on a message.

    Args:
        pubkey: rsa.key.PublicKey (or equiv), The public key to verify with.
    c                 C   
   || _ d S r   )_pubkey)selfpubkeyr   r   r   __init__E      
zRsaVerifier.__init__c              	   C   s@   t j|dd}z
tj||| jW S  ttjjfy   Y dS w )a  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.
        utf-8encodingF)r   	_to_bytesrsapkcs1verifyr&   
ValueErrorVerificationError)r'   message	signaturer   r   r   r1   H   s   zRsaVerifier.verifyc                 C   s   t |}|rEddlm} ddlm} tj|d}|j	||
 d\}}|dkr.td||d d	 }t|d
 }	tj|	d}
| |
S tj|d}
| |
S )a  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-----".
        r   decoder)rfc2459CERTIFICATEasn1Spec    Unused bytestbsCertificatesubjectPublicKeyInfosubjectPublicKeyDERPEM)r   r.   pyasn1.codec.derr7   pyasn1_modulesr8   r/   r   load_pemdecodeCertificater2   r#   	PublicKey
load_pkcs1)clskey_pemis_x509_certr7   r8   der	asn1_cert	remaining	cert_info	key_bytesr(   r   r   r   from_string[   s   

zRsaVerifier.from_stringN)__name__
__module____qualname____doc__r)   r1   classmethodrR   r   r   r   r   r$   >   s    r$   c                   @   s.   e Zd ZdZdd Zdd Zed
ddZd	S )	RsaSignerz}Signs messages with a private key.

    Args:
        pkey: rsa.key.PrivateKey (or equiv), The private key to sign with.
    c                 C   r%   r   )_key)r'   pkeyr   r   r   r)      r*   zRsaSigner.__init__c                 C   s    t j|dd}tj|| jdS )zSigns a message.

        Args:
            message: bytes, Message to be signed.

        Returns:
            string, The signature of the message for the given key.
        r+   r,   zSHA-256)r   r.   r/   r0   signrY   )r'   r4   r   r   r   r[      s   	zRsaSigner.sign
notasecretc                 C   s   t |}tt|tt\}}|dkr"tj	j
j|dd}| |S |dkr`ddlm} ddlm} tdu r:| a|j|td\}}	|	d	krLtd
|	|d}
tj	j
j|
 dd}| |S td)a  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.
        r   rA   )formatr   r6   )rfc5208Nr:   r<   r=   
privateKeyzNo key could be detected.)r   _from_bytesr   readPemBlocksFromFiler   StringIO_PKCS1_MARKER_PKCS8_MARKERr/   key
PrivateKeyrI   rC   r7   rD   r^   _PKCS8_SPECPrivateKeyInforF   r2   getComponentByNameasOctets)rJ   re   password	marker_idrQ   rZ   r7   r^   key_inforO   	pkey_infor   r   r   rR      s2   




zRsaSigner.from_stringN)r\   )rS   rT   rU   rV   r)   r[   rW   rR   r   r   r   r   rX      s    rX   )rV   rD   r   r/   r   oauth2clientr   _PKCS12_ERRORr   rc   rd   rg   r#   objectr$   rX   r   r   r   r   <module>   s   	B