a
    (b`^                     @   s   d Z ddlmZmZmZmZ ddlZddlZddlm	Z	 ddl
Zddlm  m  m  mZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z" dd Z#dd
dZ$dd Z%dddZ&dd Z'dS )a   conda_content_trust.authentication
This module contains functions that verify signatures and thereby authenticate
data.

Function Manifest for this Module
    verify_signature
    verify_gpg_signature
    verify_signable
    verify_root
    verify_delegation


    )absolute_importdivisionprint_functionunicode_literalsN)string_types   )canonserialize	PublicKeyis_a_signablecheckformat_signableis_hex_signature
is_hex_keyis_signatureis_gpg_signatureis_a_signaturecheckformat_gpg_signaturecheckformat_hex_keycheckformat_byteslikecheckformat_delegationcheckformat_delegating_metadataSignatureErrorUnknownRoleErrorMetadataVerificationErrorc           
      C   s   t |  t | | d d dks0|d d dkr8td| d d d }|d }|d }|d d d }|d }|d }| d d }|d d }	|d	 |	krtd
t| d t|	 d t|||dd t|||dd dS )ui  
    Given currently trusted root metadata, verify that new root metadata is
    trustworthy per the currently trusted root metadata.

    This requires a root chaining process as specified in The Update Framework
    specification.  (Version N must be used in order to verify version N+1.
    Versions cannot be skipped.)

    # TODO✅: Proper docstring.
    signedtyperootzxExpected two instances of root metadata.  Listed metadata type in one or both pieces of metadata provided is not "root".delegations	thresholdpubkeysversionr   zYRoot chaining failure: we currently trust a version of root that marks itself as version zG, and the provided new root metadata to verify marks itself as version z; the new version must be 1 more than the old version: root updates MUST be processed one at a time for security reasons: no root version may be skipped.TgpgN)r   
ValueErrorr   strverify_signable)
Ztrusted_current_root_metadataZuntrusted_new_root_metadataZroot_expectationsZexpected_thresholdauthorized_pub_keysZnew_root_expectationsZnew_expected_thresholdZnew_authorized_pub_keysZtrusted_root_versionZuntrusted_root_version r&   Alib/python3.9/site-packages/conda_content_trust/authentication.pyverify_root>   sT    
	r(   Fc                 C   s   t | tstdtt|  |dvr.tdt| t| zt| W n   Y n20 | |d d krtd|  d |d d  d |d d	 }| |vrtd
|  d ||  d }||  d }t	||||d dS )a  
    Verify that the given untrusted, delegated-to metadata is trustworthy,
    based on the given trusted metadata's expectations (expected keys and
    threshold).  This function returns if verification succeeds.


    In other words, check trusted_delegating_metadata's delegation
    to delegation_name to find the expected signing keys and threshold for
    delegation_name, and then check untrusted_delegated_metadata to see if it
    is signed by enough of the right keys to be trustworthy.

    For example, using root metadata to verify key_mgr metadata looks like
    this:
        verify_delegation(
                'key_mgr', <full root metadata>, <full key_mgr metadata>)

    Arguments:
        (string) delegation_name is the name of the role delegated.
        (dict)   trusted_delegating_metadata is a signable JSON-serializable
                 object representing the full metadata that delegates to role
                 delegation_name.
        (dict)   untrusted_delegated_metadata is a signable JSON-serializable
                 object
        (bool)   gpg should be true if the signatures to be verified in the
                 delegated metadata are expected to be OpenPGP signatures
                 rather than the usual raw ed25519 signatures.

    Exceptions:
        - raises UnknownRoleError if there's no matching delegation
        - raises SignatureError if a signature is bad or signatures
          don't match expectations (threshold, wrong keys, etc.)
            # TODO: Consider exception handling to raise MetadataVerificationError instead?
        - raises MetadataVerificationError if the metadata type is unexpected
        - raises TypeError or ValueError if the arguments are invalid
    z(delegation_name must be a string, not a )TFz!Argument "gpg" must be a boolean.r   r   z<Instructed to verify provided metadata as if it is of type "z ", but it claims to be of type "z"!r   zRole z, not found in the given delegating metadata.r   r   r    N)

isinstancer   	TypeErrorr#   r   r   r   r   r   r$   )Zdelegation_nameZuntrusted_delegated_metadataZtrusted_delegating_metadatar!   r   Zexpected_keysr   r&   r&   r'   verify_delegation   sN    *



r+   c                 C   sp   t |tjs tdtt| t| s<tdtt|  t |tsZtdtt| |t	
| | dS )u  
    Raises ❌cryptography.exceptions.InvalidSignature if signature is not a
    correct signature by the given key over the given data.

    Raises ❌TypeError if public_key, signature, or data are not correctly
    formatted.

    Otherwise, returns (nothing), indicating the signature was verified.

    Note that this does not use the generalized signature format (which would
    be compatible with OpenPGP/GPG signatures as well as pyca/cryptography's
    simple ed25519 sigs).

    Args:
        - public_key must be an ed25519.Ed25519PublicKeyObject
        - signature must be a hex string, length 128, representing a 64-byte
          raw ed25519 signature
        - data must be bytes
    zverify_signature expects a cryptography.hazmat.primitives.asymmetric.ed25519ed25519.Ed25519PublicKeyobject as the "public_key" argument.  Instead, received zverify_signature expects a hex string representing an ed25519 signature as the "signature" argument. Instead, received object of type zXverify_signature expects a bytes object as the "signature" argument.  Instead, received N)r)   ed25519ZEd25519PublicKeyr*   r#   r   r   bytesverifybinascii	unhexlify)	signature
public_keydatar&   r&   r'   verify_signature  s(    



r4   c           	   	   C   s  t | stdt|tr,tdd |D s4tdt|trF|dkrNtdt| d }i }| d  D ]\}}t|st	d	t
|  qj|st|st	d
t
|  qj|rt|st	dt
|  qj||vrt	dt
| d  qj|sHt|}t|st	d qjzt|d || W n tjjy<   Y qjY n
0 |||< qj|sRJ zt||| W n tjjy~   Y qjY qj0 |||< qjt||k rtdt
| d t
t| d t
t| d  d t
t| d dS )u  
    Raises a ❌SignatureError if signable does not include at least threshold
    good signatures from (unique) keys with public keys listed in
    authorized_pub_keys, over the data contained in signable['signed'].

    Raises ❌TypeError if the arguments are invalid.

    Else returns (nothing).

    Args:
        - signable
            common.is_a_signable(signable) must return true.
            wrap_as_signable() produces output of this type.  See those
            functions.

        - authorized_pub_keys
            a list of ed25519 public keys (32 bytes) expressed as 64-character
            hex strings.  This is the form in which they appear in authority
            metadata (root.json, etc.)  Only good signatures from keys listed
            in authorized_pub_keys count against the threshold of signatures
            required to verify the signable.

        - threshold
            the number of good signatures from unique authorized keys required
            in order to verify the signable.

        - gpg (boolean, default False)
            If True, expects OpenPGP ed25519 signatures (see RFC 4880 bis-08)
            instead of raw ed25519 signatures.
            If False, expects raw ed25519 signatures.
    zOverify_signable expects a signable dictionary.  Given argument failed the test.c                 S   s   g | ]}t |qS r&   )r   ).0kr&   r&   r'   
<listcomp>r      z#verify_signable.<locals>.<listcomp>z2authorized_pub_keys must be a list of hex strings r   z%threshold must be a positive integer.r   Z
signatureszYIgnoring signature from "key" with public key value that does not look like a key value: zDIgnoring "signature" that does not look like a hex signature value: zDIgnoring "signature" that does not look like a gpg signature value: z Ignoring signature from a key ("z0") that is not authorized to sign this metadata.zKIgnoring "signature" that does not look like a raw ed25519 signature value.r1   z'Expected good signatures from at least z unique keys from a set of z keys.  Saw z signatures, only zJ of which were good signatures over the given data from the expected keys.N)r
   r*   r)   listallintr   itemsr   printr#   r   r   r	   from_hexr4   cryptography
exceptionsZInvalidSignatureverify_gpg_signaturelenr   )	Zsignabler%   r   r!   Zsigned_dataZgood_sigs_from_trusted_keysZ
pubkey_hexr1   Zpublicr&   r&   r'   r$   @  s    -










	r$   c                 C   s   t |  t| t| t|}t| d }tjj	j
tjj	j
 tjj }|| || |d |tdt| | }|t| d | dS )u?  
    Verifies a raw ed25519 signature that happens to have been produced by an
    OpenPGP signing process (RFC4880).

    NOTE that this code DISREGARDS most OpenPGP semantics: is interested solely
    in the verification of a signature over the given data, with the raw
    ed25519 public key given (in the form of a hex string).  This code does not
    care about the GPG public key infrastructure, including key
    self-revocation, expiry, or the relationship of any key with any other key
    through OpenPGP (subkeys, key-to-key signoff, etc.).

    This codebase uses OpenPGP signatures solely as a means of facilitating a
    TUF-style public key infrastructure, where the public key values are
    trusted with specific privileges directly.


    ⚠️💣 ABSOLUTELY DO NOT use this for general purpose verification of GPG
         signatures!!  It is for our root signatures only, where OpenPGP
         signing is just a proxy for a simple ed25519 signature through a
         hardware signing mechanism.


    # TODO: ✅ Proper docstring modeled on verify_signature.
    Zother_headerss   z>Ir1   N)r   r   r   r	   r>   r/   r0   r?   hazmat
primitivesZhashesZHashZSHA256ZbackendsZdefault_backendupdatestructpackrB   finalizer.   )r1   	key_valuer3   r2   Zadditional_header_dataZhasherZdigestr&   r&   r'   rA     s$    





rA   )F)F)(__doc__Z
__future__r   r   r   r   r/   rF   Zsixr   Zcryptography.exceptionsr?   Z1cryptography.hazmat.primitives.asymmetric.ed25519rC   rD   Z
asymmetricr,   commonr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r(   r+   r4   r$   rA   r&   r&   r&   r'   <module>   s   Lk 
m-
 .