Ejemplo n.º 1
0
    def importKey(self, extern_key, passphrase=None):
        extern_key = tobytes(extern_key)
        if passphrase is not None:
            passphrase = tobytes(passphrase)
        if extern_key.startswith(b('-----')):
            der, marker, enc_flag = PEM.decode(tostr(extern_key), passphrase)
            if enc_flag:
                passphrase = None
            return self._importKeyDER(der, passphrase)
        elif extern_key.startswith(b('ssh-rsa ')):
            keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
            keyparts = []
            while len(keystring) > 4:
                l = struct.unpack('>I', keystring[:4])[0]
                keyparts.append(keystring[4:4 + l])
                keystring = keystring[4 + l:]

            e = bytes_to_long(keyparts[1])
            n = bytes_to_long(keyparts[2])
            return self.construct([n, e])
        elif bord(extern_key[0]) == 48:
            return self._importKeyDER(extern_key, passphrase)
        else:
            raise ValueError('RSA key format is not supported')
            return
Ejemplo n.º 2
0
def import_key(encoded, passphrase=None):
    """Import an ECC key (public or private).

    Args:
      encoded (bytes or multi-line string):
        The ECC key to import.

        An ECC **public** key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC **private** key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or OpenSSH)

        Private keys can be in the clear or password-protected.

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (byte string):
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

    Returns:
      :class:`EccKey` : a new ECC key object

    Raises:
      ValueError: when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    encoded = tobytes(encoded)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    # PEM
    if encoded.startswith(b('-----')):
        der_encoded, marker, enc_flag = PEM.decode(tostr(encoded), passphrase)
        if enc_flag:
            passphrase = None
        return _import_der(der_encoded, passphrase)

    # OpenSSH
    if encoded.startswith(b('ecdsa-sha2-')):
        return _import_openssh(encoded)

    # DER
    if bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    raise ValueError("ECC key format is not supported")
Ejemplo n.º 3
0
def verify_signature(fname,
                     sfname,
                     cert_file='public.crt',
                     ca_fname='ca-root.crt',
                     **kw):
    '''
        Given the fname, sfname cert_file and ca_fnames:

        return STATUS.FAIL if the signature doesn't match
        return STATUS.UNKNOWN if the certificate signature can't be verified with the ca cert
        return STATUS.VERIFIED if both the signature and the CA sig match

    '''
    x509 = X509(cert_file, ca_fname)
    ca_status = x509.verify_cert()
    try:
        with open(sfname, 'r') as fh:
            signature, _, _ = PEM.decode(
                fh.read())  # also returns header and decrypted-status
    except FileNotFoundError:
        log.error('failed to find %s for %s', sfname, fname)
        return STATUS.UNKNOWN
    if x509.verifier.verify(hash_target(fname, obj_mode=True), signature):
        return ca_status
    log.error('%s failed signature check (%s)', fname, sfname)
    return STATUS.FAIL
Ejemplo n.º 4
0
def import_key(encoded, passphrase=None):
    """Import an ECC key (public or private).

    :Parameters:
      encoded : bytes or a (multi-line) string
        The ECC key to import.

        An ECC public key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC private key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or OpenSSH)

        Private keys can be in the clear or password-protected.

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

    :Keywords:
      passphrase : byte string
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

    :Return: An ECC key object (`EccKey`)

    :Raise ValueError:
        When the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    encoded = tobytes(encoded)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    # PEM
    if encoded.startswith(b('-----')):
        der_encoded, marker, enc_flag = PEM.decode(tostr(encoded), passphrase)
        if enc_flag:
            passphrase = None
        return _import_der(der_encoded, passphrase)

    # OpenSSH
    if encoded.startswith(b('ecdsa-sha2-')):
        return _import_openssh(encoded)

    # DER
    if bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    raise ValueError("ECC key format is not supported")
Ejemplo n.º 5
0
    def importKey(self, extern_key, passphrase=None):
        extern_key = tobytes(extern_key)
        if passphrase is not None:
            passphrase = tobytes(passphrase)
        if extern_key.startswith(b('-----')):
            der, marker, enc_flag = PEM.decode(tostr(extern_key), passphrase)
            if enc_flag:
                passphrase = None
            return self._importKeyDER(der, passphrase)
        else:
            if extern_key.startswith(b('ssh-dss ')):
                keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
                keyparts = []
                while len(keystring) > 4:
                    length = struct.unpack('>I', keystring[:4])[0]
                    keyparts.append(keystring[4:4 + length])
                    keystring = keystring[4 + length:]

                if keyparts[0] == b('ssh-dss'):
                    tup = [bytes_to_long(keyparts[x]) for x in (4, 3, 1, 2)]
                    return self.construct(tup)
            if bord(extern_key[0]) == 48:
                return self._importKeyDER(extern_key, passphrase)
            raise ValueError('DSA key format is not supported')
            return
Ejemplo n.º 6
0
def import_key(data):
    der, marker, _ = PEM.decode(data)
    ints = DerSequence().decode(der)

    if not marker.startswith('myDSA'):
        raise ValueError('Invalid format')

    return dict(zip(('p', 'q', 'g', 'y', 'x'), map(Integer, ints)))
Ejemplo n.º 7
0
 def _load_private_key(self):
     """Load the private key used to sign HTTP requests.
         The private key is used to sign HTTP requests as defined in
         https://datatracker.ietf.org/doc/draft-cavage-http-signatures/.
     """
     if self.private_key is not None:
         return
     with open(self.private_key_path, 'r') as f:
         pem_data = f.read()
         # Verify PEM Pre-Encapsulation Boundary
         r = re.compile(r"\s*-----BEGIN (.*)-----\s+")
         m = r.match(pem_data)
         if not m:
             raise ValueError("Not a valid PEM pre boundary")
         pem_header = m.group(1)
         if pem_header == 'RSA PRIVATE KEY':
             self.private_key = RSA.importKey(pem_data,
                                              self.private_key_passphrase)
         elif pem_header == 'EC PRIVATE KEY':
             self.private_key = ECC.import_key(pem_data,
                                               self.private_key_passphrase)
         elif pem_header in {'PRIVATE KEY', 'ENCRYPTED PRIVATE KEY'}:
             # Key is in PKCS8 format, which is capable of holding many different
             # types of private keys, not just EC keys.
             (key_binary, pem_header, is_encrypted) = \
                 PEM.decode(pem_data, self.private_key_passphrase)
             (oid, privkey, params) = \
                 PKCS8.unwrap(key_binary, passphrase=self.private_key_passphrase)
             if oid == '1.2.840.10045.2.1':
                 self.private_key = ECC.import_key(
                     pem_data, self.private_key_passphrase)
             else:
                 raise Exception("Unsupported key: {0}. OID: {1}".format(
                     pem_header, oid))
         else:
             raise Exception("Unsupported key: {0}".format(pem_header))
         # Validate the specified signature algorithm is compatible with the private key.
         if self.signing_algorithm is not None:
             supported_algs = None
             if isinstance(self.private_key, RSA.RsaKey):
                 supported_algs = {
                     ALGORITHM_RSASSA_PSS, ALGORITHM_RSASSA_PKCS1v15
                 }
             elif isinstance(self.private_key, ECC.EccKey):
                 supported_algs = ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS
             if supported_algs is not None and self.signing_algorithm not in supported_algs:
                 raise Exception(
                     "Signing algorithm {0} is not compatible with private key"
                     .format(self.signing_algorithm))
Ejemplo n.º 8
0
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private half), encoded in standard
    form.
    :Parameter extern_key:
        The RSA key to import, encoded as a byte string.
        An RSA public key can be in any of the following formats:
        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)
        An RSA private key can be in any of the following formats:
        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)
        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.
    :Type extern_key: string
    :Parameter passphrase:
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.
    :Type passphrase: string
    :Return: An RSA key object (`RsaKey`).
    :Raise ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).
    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """
    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    raise ValueError("RSA key format is not supported")
Ejemplo n.º 9
0
    def __init__(self, crt_fname, ca_fname):
        self.crt_fname = crt_fname
        self.ca_fname = ca_fname
        with open(ca_fname, 'r') as fh:
            self.ca_raw = fh.read()
        with open(crt_fname, 'r') as fh:
            self.crt_raw = fh.read()

        self.ca = ossl.load_certificate(ossl.FILETYPE_PEM, self.ca_raw)

        ossl_crt = ossl.load_certificate(ossl.FILETYPE_PEM, self.crt_raw)
        self.pdat = self.PEMData(*PEM.decode(self.crt_raw))
        self.cdat = self.CrtData(*asn1.DerSequence().decode(self.pdat.cert))
        _sig = asn1.DerObject().decode(self.cdat.sig).payload
        self.sig = self.SigData(_sig[0], _sig[1:],
                                ossl_crt.get_signature_algorithm().decode())
        self.crt = RSA.importKey(self.pdat.cert)
        self.verifier = PKCS1_v1_5.new(self.crt)
Ejemplo n.º 10
0
def forge(certificate_path: str, key_pem: str):
    """
    given a valid certificate_path and key_pem create a forged key
    """
    public_key_point = get_public_key(certificate_path)
    Q = Point(int(public_key_point[0:96], 16),
              int(public_key_point[96:], 16),
              curve=P384)

    # Generate rogue generator
    privkey_inv = 2
    # we take the private key as being the inverse of 2 modulo the curve order
    private_key = gmpy2.invert(privkey_inv, P384.q)  # pylint: disable=c-extension-no-member
    private_key = unhexlify(f"{private_key:x}".encode())
    # we multply our public key Q with the inverse of our chosen private key value
    roug_g = privkey_inv * Q
    roug_g = unhexlify(b"04" + f"{roug_g.x:x}".encode() +
                       f"{roug_g.y:x}".encode())

    # Generate the file with explicit parameters
    with open(key_pem, mode="rt") as handle:
        keyfile = PEM.decode(handle.read())

    seq_der = DerSequence()
    der = seq_der.decode(keyfile[0])

    # Replace private key
    octet_der = DerOctetString(private_key)
    der[1] = octet_der.encode()

    # Replace public key
    bits_der = DerBitString(unhexlify(b"04" + public_key_point))
    der[3] = b"\xa1\x64" + bits_der.encode()

    # Replace the generator
    seq_der = DerSequence()
    s = seq_der.decode(der[2][4:])  # pylint: disable=invalid-name
    octet_der = DerOctetString(roug_g)
    s[3] = octet_der.encode()
    der[2] = der[2][:4] + s.encode()

    return PEM.encode(der.encode(), "EC PRIVATE KEY")
Ejemplo n.º 11
0
def importKey(extern_key, passphrase=None):
    """Import an RSA key (public or private half), encoded in standard
    form.

    :Parameter extern_key:
        The RSA key to import, encoded as a byte string.

        An RSA public key can be in any of the following formats:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        An RSA private key can be in any of the following formats:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.
    :Type extern_key: string

    :Parameter passphrase:
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.
    :Type passphrase: string

    :Return: An RSA key object (`RsaKey`).

    :Raise ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """
    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _importKeyDER(der, passphrase)

    if extern_key.startswith(b('ssh-rsa ')):
            # This is probably an OpenSSH key
            keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
            keyparts = []
            while len(keystring) > 4:
                l = struct.unpack(">I", keystring[:4])[0]
                keyparts.append(keystring[4:4 + l])
                keystring = keystring[4 + l:]
            e = Integer.from_bytes(keyparts[1])
            n = Integer.from_bytes(keyparts[2])
            return construct([n, e])

    if bord(extern_key[0]) == 0x30:
            # This is probably a DER encoded key
            return _importKeyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Ejemplo n.º 12
0
def import_key(encoded, passphrase=None):
    """Import an ECC key (public or private).

    Args:
      encoded (bytes or multi-line string):
        The ECC key to import.

        An ECC **public** key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC **private** key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or OpenSSH)

        Private keys can be in the clear or password-protected.

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (byte string):
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

    Returns:
      :class:`EccKey` : a new ECC key object

    Raises:
      ValueError: when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    encoded = tobytes(encoded)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    # PEM
    if encoded.startswith(b'-----'):

        text_encoded = tostr(encoded)

        # Remove any EC PARAMETERS section
        # Ignore its content because the curve type must be already given in the key
        if sys.version_info[:2] != (2, 6):
            ecparams_start = "-----BEGIN EC PARAMETERS-----"
            ecparams_end = "-----END EC PARAMETERS-----"
            text_encoded = re.sub(ecparams_start + ".*?" + ecparams_end, "",
                                  text_encoded,
                                  flags=re.DOTALL)

        der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase)
        if enc_flag:
            passphrase = None
        try:
            result = _import_der(der_encoded, passphrase)
        except UnsupportedEccFeature as uef:
            raise uef
        except ValueError:
            raise ValueError("Invalid DER encoding inside the PEM file")
        return result

    # OpenSSH
    if encoded.startswith(b'ecdsa-sha2-'):
        return _import_openssh(encoded)

    # DER
    if len(encoded) > 0 and bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    raise ValueError("ECC key format is not supported")
Ejemplo n.º 13
0
def importKey(extern_key, passphrase=None):
    """Import a DSA key (public or private).

    :Parameters:
      extern_key : (byte) string
        The DSA key to import.

        An DSA *public* key can be in any of the following formats:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` (binary or PEM)
        - OpenSSH (one line of text, see `RFC4253`_)

        A DSA *private* key can be in any of the following formats:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSL/OpenSSH (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.

      passphrase : string
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

    :Return: A DSA key object (`DsaKey`).
    :Raise ValueError:
        When the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _importKeyDER(der, passphrase, None)

    if extern_key.startswith(b('ssh-dss ')):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b("ssh-dss"):
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _importKeyDER(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")
Ejemplo n.º 14
0
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private half), encoded in standard
    form.

    Args:
      extern_key (string or byte string):
        The RSA key to import.

        The following formats are supported for an RSA **public key**:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        The following formats are supported for an RSA **private key**:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.

    Returns: An RSA key object (:class:`RsaKey`).

    Raises:
      ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b('ssh-rsa ')):
        # This is probably an OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            l = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + l])
            keystring = keystring[4 + l:]
        e = Integer.from_bytes(keyparts[1])
        n = Integer.from_bytes(keyparts[2])
        return construct([n, e])

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Ejemplo n.º 15
0
def import_key(extern_key, passphrase=None):
    """Import a DSA key.

    Args:
      extern_key (string or byte string):
        The DSA key to import.

        The following formats are supported for a DSA **public** key:

        - X.509 certificate (binary DER or PEM)
        - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM)
        - OpenSSH (ASCII one-liner, see `RFC4253`_)

        The following formats are supported for a DSA **private** key:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM)
        - OpenSSL/OpenSSH custom format (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

        Encryption may be applied either at the `PKCS#8`_ or at the PEM level.

    Returns:
      :class:`DsaKey` : a DSA key object

    Raises:
      ValueError : when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_key_der(der, passphrase, None)

    if extern_key.startswith(b('ssh-dss ')):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b("ssh-dss"):
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_key_der(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")
Ejemplo n.º 16
0
def main():
    parser = argparse.ArgumentParser(
        description="Pad and append CSV file to FPGA bitstream")
    parser.add_argument("-b",
                        "--bitstream",
                        required=True,
                        help="file containing FPGA bitstream",
                        type=str)
    parser.add_argument("-c",
                        "--csv-file",
                        required=True,
                        help="file containing CSV input",
                        type=str)
    parser.add_argument("-o",
                        "--output-file",
                        required=True,
                        help="destination file for binary data",
                        type=str)
    parser.add_argument("--key",
                        required=False,
                        help="signing key",
                        type=str,
                        nargs='?',
                        metavar=('signing key'),
                        const=DEVKEY_PATH)

    args = parser.parse_args()

    if args.key is None:
        key = DEVKEY_PATH
    else:
        key = args.key

    with open(key) as key_f:
        key_pem = key_f.read()
        try:
            pem = PEM.decode(key_pem, None)
        except:
            passphrase = input("Enter loader key passphrase: ")
            pem = PEM.decode(key_pem, passphrase)

        (key_pkey, pemtype, enc) = pem
        if pemtype != 'PRIVATE KEY':
            print("PEM type for loader was not a private key. Aborting.")
            exit(1)

    checksum = hashlib.md5(open(args.bitstream, 'rb').read()).digest()

    # NOTE NOTE NOTE
    # can't find a good ASN.1 ED25519 key decoder, just relying on the fact that the last 32 bytes are "always" the private key. always? the private key?
    signing_key = SigningKey(key_pkey[-32:], encoder=RawEncoder)
    signing_data = list()

    TOTAL_LEN = 0x28_0000
    SIGNATURE_LOC = 0x27_F000
    CSR_CSV_LOC = 0x27_7000
    METADATA_LOC = 0x27_6000
    pad_to = 0x7FC0
    with open(args.bitstream, "rb") as bitstream:
        with open(args.csv_file, "rb") as ifile:
            with open(args.output_file, "wb") as ofile:
                # create the CSV appendix
                data = ifile.read()  # read in the whole block of CSV data

                git_rev = subprocess.Popen(
                    ["git", "describe", "--long", "--always"],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)
                (rev, err) = git_rev.communicate()
                data += b"git_rev,"
                data += rev

                odata = bytearray()
                odata += len(data).to_bytes(4, 'little')
                odata += data

                padding = bytes([0xff]) * (pad_to - len(data) - 4)
                odata += padding

                hasher = hashlib.sha512()
                hasher.update(odata)
                digest = hasher.digest()
                odata += digest
                # odata now contains the csv appendix

                # assemble the final output file
                bits = bitstream.read()  # read in all the bitstream
                position = 0
                # seek past the preamble junk that's ignored
                while position < len(bits):
                    sync = int.from_bytes(bits[position:position + 4], 'big')
                    if sync == 0xaa995566:
                        break
                    position = position + 1
                program_data = bits[position:]

                aes_padding = 8  # insert padding so that AES blocks line up on erase block boundaries
                # this may have to be adjusted if you change the bitstream header parameters
                written = 0
                written += ofile.write(bytes([0xff] * aes_padding))
                signing_data += bytes([0xff] * aes_padding)

                written += ofile.write(program_data)
                signing_data += program_data

                # insert metadata
                metadata_pad = bytes([0xff]) * (METADATA_LOC - written)
                written += ofile.write(metadata_pad)
                signing_data += metadata_pad
                metadata = compute_metadata(checksum)
                assert (written == METADATA_LOC)
                written += ofile.write(metadata)
                signing_data += metadata

                assert (written == CSR_CSV_LOC)
                # add the CSR data
                written += ofile.write(odata)
                signing_data += odata

                assert (written == SIGNATURE_LOC)

                signature = signing_key.sign(signing_data, encoder=RawEncoder)
                written += ofile.write(
                    (int(SIGNER_VERSION).to_bytes(4, 'little')))
                written += ofile.write(len(signing_data).to_bytes(4, 'little'))
                written += ofile.write(signature.signature)
                written += ofile.write(bytes([0xff]) * (TOTAL_LEN - written))
                assert (written == TOTAL_LEN)
Ejemplo n.º 17
0
def main():
    global DEVKEY_PATH

    parser = argparse.ArgumentParser(description="Sign binary images for Precursor")
    parser.add_argument(
        "--loader-image", required=False, help="loader image", type=str, nargs='?', metavar=('loader image'), const='../target/riscv32imac-unknown-none-elf/release/loader_presign.bin'
    )
    parser.add_argument(
        "--kernel-image", required=False, help="kernel image", type=str, nargs='?', metavar=('kernel image'), const='../target/riscv32imac-unknown-none-elf/release/xous_presign.img'
    )
    parser.add_argument(
        "--loader-key", required=False, help="loader signing key", type=str, nargs='?', metavar=('loader signing key'), const=DEVKEY_PATH
    )
    parser.add_argument(
        "--kernel-key", required=False, help="kernel signing key", type=str, nargs='?', metavar=('kernel signing key'), const=DEVKEY_PATH
    )
    parser.add_argument(
        "--loader-output", required=False, help="loader output image", type=str, nargs='?', metavar=('loader output image'),  const='../target/riscv32imac-unknown-none-elf/release/loader.bin'
    )
    parser.add_argument(
        "--kernel-output", required=False, help="kernel output image", type=str, nargs='?', metavar=('kernel output image'),  const='../target/riscv32imac-unknown-none-elf/release/xous.img'
    )
    parser.add_argument(
        "--defile", help="patch the resulting image, to create a test file to catch signature failure", default=False, action="store_true"
    )
    args = parser.parse_args()
    if not len(sys.argv) > 1:
        print("No arguments specified, doing nothing. Use --help for more information.")
        exit(1)

    if args.loader_image and (args.loader_key is None):
        loader_key = DEVKEY_PATH
    else:
        loader_key = args.loader_key
    if args.loader_image and (args.loader_output is None):
        loader_output = '../target/riscv32imac-unknown-none-elf/release/loader.bin'
    else:
        loader_output = args.loader_output

    if loader_key is not None and loader_key is not DEVKEY_PATH:
        with open(loader_key) as loader_f:
            loader_pem = loader_f.read()
            try:
                pem = PEM.decode(loader_pem, None)
            except:
                passphrase = input("Enter loader key passphrase: ")
                pem = PEM.decode(loader_pem, passphrase)

            (loader_pkey, pemtype, enc) = pem
            if pemtype != 'PRIVATE KEY':
                print("PEM type for loader was not a private key. Aborting.")
                exit(1)
    else:
        loader_pkey = None

    if loader_pkey != None:
        blob_sign(args.loader_image, loader_output, loader_pkey, defile=args.defile)

    # for now, the kernel signing path is just signing a blob that is the overall binary
    # however, there is some aspiration to sign individual binaries, and to incorporate
    # signatures into the kernel tags. leave this path separate so there's an on-ramp
    # to add these features
    if args.kernel_image and (args.kernel_key is None):
        kernel_key = DEVKEY_PATH
    else:
        kernel_key = args.kernel_key
    if args.kernel_image and (args.kernel_output is None):
        kernel_output = '../target/riscv32imac-unknown-none-elf/release/xous.img'
    else:
        kernel_output = args.kernel_output

    if kernel_key is not None and kernel_key is not DEVKEY_PATH:
        with open(kernel_key) as kernel_f:
            kernel_pem = kernel_f.read()
            try:
                pem = PEM.decode(kernel_pem, None)
            except:
                passphrase = input("Enter kernel key passphrase: ")
                pem = PEM.decode(kernel_pem, passphrase)

            (kernel_pkey, pemtype, enc) = pem
            if pemtype != 'PRIVATE KEY':
                print("PEM type for kernel was not a private key. Aborting.")
                exit(1)
    else:
        kernel_pkey = None

    if kernel_pkey != None:
        blob_sign(args.kernel_image, kernel_output, kernel_pkey, defile=args.defile)
Ejemplo n.º 18
0
def importKey(extern_key, passphrase=None, verify_x509_cert=True):
    """Import an RSA key (public or private half), encoded in standard
    form.

    :Parameter extern_key:
        The RSA key to import, encoded as a byte string.

        An RSA public key can be in any of the following formats:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        An RSA private key can be in any of the following formats:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.
    :Type extern_key: string

    :Parameter passphrase:
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.
    :Type passphrase: string

    :Parameter verify_x509_cert:
        When importing the public key from an X.509 certificate, whether
        the certificate should be validated. **Since verification is not
        yet supported, this value must always be set to False**.

        This value is ignored if an X.509 certificate is not passed.
    :Type verify_x509_cert: bool

    :Return: An RSA key object (`RsaKey`).

    :Raise ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """
    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _importKeyDER(der, passphrase, verify_x509_cert)

    if extern_key.startswith(b('ssh-rsa ')):
            # This is probably an OpenSSH key
            keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
            keyparts = []
            while len(keystring) > 4:
                l = struct.unpack(">I", keystring[:4])[0]
                keyparts.append(keystring[4:4 + l])
                keystring = keystring[4 + l:]
            e = Integer.from_bytes(keyparts[1])
            n = Integer.from_bytes(keyparts[2])
            return construct([n, e])

    if bord(extern_key[0]) == 0x30:
            # This is probably a DER encoded key
            return _importKeyDER(extern_key,
                                 passphrase,
                                 verify_x509_cert)

    raise ValueError("RSA key format is not supported")
Ejemplo n.º 19
0
def import_key(encoded, passphrase=None):
    """Import an ECC key (public or private).

    Args:
      encoded (bytes or multi-line string):
        The ECC key to import.

        An ECC **public** key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC **private** key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or `OpenSSH 6.5+`_)

        Private keys can be in the clear or password-protected.

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (byte string):
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

    Returns:
      :class:`EccKey` : a new ECC key object

    Raises:
      ValueError: when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    .. _`OpenSSH 6.5+`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
    """

    from Crypto.IO import PEM

    encoded = tobytes(encoded)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    # PEM
    if encoded.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'):
        text_encoded = tostr(encoded)
        openssh_encoded, marker, enc_flag = PEM.decode(text_encoded,
                                                       passphrase)
        result = _import_openssh_private_ecc(openssh_encoded, passphrase)
        return result

    elif encoded.startswith(b'-----'):

        text_encoded = tostr(encoded)

        # Remove any EC PARAMETERS section
        # Ignore its content because the curve type must be already given in the key
        ecparams_start = "-----BEGIN EC PARAMETERS-----"
        ecparams_end = "-----END EC PARAMETERS-----"
        text_encoded = re.sub(ecparams_start + ".*?" + ecparams_end,
                              "",
                              text_encoded,
                              flags=re.DOTALL)

        der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase)
        if enc_flag:
            passphrase = None
        try:
            result = _import_der(der_encoded, passphrase)
        except UnsupportedEccFeature as uef:
            raise uef
        except ValueError:
            raise ValueError("Invalid DER encoding inside the PEM file")
        return result

    # OpenSSH
    if encoded.startswith(b'ecdsa-sha2-'):
        return _import_openssh_public(encoded)

    # DER
    if len(encoded) > 0 and bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    raise ValueError("ECC key format is not supported")
Ejemplo n.º 20
0
Archivo: DSA.py Proyecto: cloudera/hue
def import_key(extern_key, passphrase=None):
    """Import a DSA key.

    Args:
      extern_key (string or byte string):
        The DSA key to import.

        The following formats are supported for a DSA **public** key:

        - X.509 certificate (binary DER or PEM)
        - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM)
        - OpenSSH (ASCII one-liner, see `RFC4253`_)

        The following formats are supported for a DSA **private** key:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM)
        - OpenSSL/OpenSSH custom format (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

        Encryption may be applied either at the `PKCS#8`_ or at the PEM level.

    Returns:
      :class:`DsaKey` : a DSA key object

    Raises:
      ValueError : when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_key_der(der, passphrase, None)

    if extern_key.startswith(b('ssh-dss ')):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b("ssh-dss"):
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_key_der(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")
Ejemplo n.º 21
0
def verify_signature(fname,
                     sfname,
                     public_crt=None,
                     ca_crt=None,
                     extra_crt=None,
                     **kwargs):  # pylint: disable=unused-argument
    """
        Given the fname, sfname public_crt and ca_crt:

        return STATUS.FAIL if the signature doesn't match
        return STATUS.UNKNOWN if the certificate signature can't be verified with the ca cert
        return STATUS.VERIFIED if both the signature and the CA sig match
    """

    if check_verif_timestamp(fname):
        log_error = log.error
        log_info = log.info
    else:
        log_error = log_info = log.debug

    if Options.verify_cache_age > 0:
        cache_key = _cache_key(fname, sfname, public_crt, ca_crt, extra_crt)
        res = _get_verify_cache(cache_key)
        if res is not None:
            log_info('using cached verify_signature(%s, %s) -> %s', fname,
                     sfname, res)
            return res

    if public_crt is None:
        public_crt = Options.public_crt
    if ca_crt is None:
        ca_crt = Options.ca_crt

    if not (fname and sfname):
        status = STATUS.UNKNOWN
        log_info('!(fname=%s and sfname=%s) => status=%s', fname, sfname,
                 status)
        return status

    short_fname = os.path.basename(fname)

    try:
        with open(sfname, 'r') as fh:
            sig, _, _ = PEM.decode(
                fh.read())  # also returns header and decrypted-status
    except IOError:
        status = STATUS.UNKNOWN
        verif_key = ':'.join([fname, sfname])
        log_error('%s | file "%s" | status: %s ', short_fname, fname, status)
        return status

    x509 = X509AwareCertBucket(public_crt, ca_crt, extra_crt)
    hasher, chosen_hash = hash_target(fname, obj_mode=True)
    digest = hasher.finalize()

    salt_padding_bits_list = Options.salt_padding_bits
    if not isinstance(salt_padding_bits_list, (list, tuple)):
        salt_padding_bits_list = [salt_padding_bits_list]

    sha256sum = ''.join(f'{x:02x}' for x in digest)

    for crt, txt, pcrt_status in x509.public_crt:
        args = {'signature': sig, 'data': digest}
        pubkey = crt.get_pubkey().to_cryptography_key()
        for salt_padding_bits in salt_padding_bits_list:
            salt_padding_bits = _format_padding_bits(salt_padding_bits)
            if isinstance(pubkey, rsa.RSAPublicKey):
                args['padding'] = padding.PSS(mgf=padding.MGF1(
                    hashes.SHA256()),
                                              salt_length=salt_padding_bits)
                args['algorithm'] = utils.Prehashed(chosen_hash)
            try:
                pubkey.verify(**args)
                log_info(
                    'verify_signature(%s, %s) | sbp: %s | status: %s | sha256sum: "%s" | (1) public cert fingerprint and requester: "%s"',
                    fname, sfname, _format_padding_bits_txt(salt_padding_bits),
                    pcrt_status, sha256sum, txt)
                if Options.verify_cache_age < 1:
                    return pcrt_status
                return _set_verify_cache(cache_key, pcrt_status)
            except TypeError as tee:
                log_info(
                    'verify_signature(%s, %s) | sbp: %s | internal error using %s.verify() (%s): (2) %s',
                    fname, sfname, _format_padding_bits_txt(salt_padding_bits),
                    type(pubkey).__name__, stringify_cert_files(crt), tee)
            except InvalidSignature:
                log_info(
                    'verify_signature(%s, %s) InvalidSignature | sbp: %s | sha256sum: "%s" | public cert fingerprint and requester: "%s"',
                    fname, sfname, _format_padding_bits_txt(salt_padding_bits),
                    sha256sum, txt)
    status = STATUS.FAIL
    log_error(
        'verify_signature(%s, %s) UnverifiedSignature | status: %s | sha256sum: "%s" | (4)',
        fname, sfname, status, sha256sum)
    return _set_verify_cache(cache_key, status)
Ejemplo n.º 22
0
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private).

    Args:
      extern_key (string or byte string):
        The RSA key to import.

        The following formats are supported for an RSA **public key**:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        The following formats are supported for an RSA **private key**:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (text format, introduced in `OpenSSH 6.5`_)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string or byte string):
        For private keys only, the pass phrase that encrypts the key.

    Returns: An RSA key object (:class:`RsaKey`).

    Raises:
      ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
    """

    from Crypto.IO import PEM

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'):
        text_encoded = tostr(extern_key)
        openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase)
        result = _import_openssh_private_rsa(openssh_encoded, passphrase)
        return result

    if extern_key.startswith(b'-----'):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b'ssh-rsa '):
        # This is probably an OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b' ')[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        e = Integer.from_bytes(keyparts[1])
        n = Integer.from_bytes(keyparts[2])
        return construct([n, e])

    if len(extern_key) > 0 and bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Ejemplo n.º 23
0
# USERTrust ECC Certification Authority public key
pubkey = b"1aac545aa9f96823e77ad5246f53c65ad84babc6d5b6d1e67371aedd9cd60c61fddba08903b80514ec57ceee5d3fe221b3cef7d48a79e0a3837e2d97d061c4f199dc259163ab7f30a3b470e2c7a1339cf3bf2e5c53b15fb37d327f8a34e37979"
Q = Point(int(pubkey[0:96], 16), int(pubkey[96:], 16), curve=P384)

# Generate rogue generator
privkey_inv = 2
# we take the private key as being the inverse of 2 modulo the curve order
privkey = gmpy2.invert(privkey_inv, P384.q)
privkey = unhexlify(f'{privkey:x}'.encode())
# we multply our public key Q with the inverse of our chosen private key value
rogueG = privkey_inv * Q
rogueG = unhexlify(b"04" + f'{rogueG.x:x}'.encode() + f'{rogueG.y:x}'.encode())

# Generate the file with explicit parameters
f = open('p384-key.pem', 'rt')
keyfile = PEM.decode(f.read())
#print(hexlify(keyfile[0]))
f.close()
seq_der = DerSequence()
der = seq_der.decode(keyfile[0])

# Replace private key
octet_der = DerOctetString(privkey)
der[1] = octet_der.encode()

# Replace public key
#print(hexlify(der[3]))
bits_der = DerBitString(unhexlify(b"04" + pubkey))
der[3] = b"\xa1\x64" + bits_der.encode()
#print(hexlify(der[3]))
Ejemplo n.º 24
0
def verify_signature(fname,
                     sfname,
                     public_crt='public.crt',
                     ca_crt='ca-root.crt',
                     extra_crt=None,
                     **kwargs):  # pylint: disable=unused-argument
    ### make
    """
        Given the fname, sfname public_crt and ca_crt:

        return STATUS.FAIL if the signature doesn't match
        return STATUS.UNKNOWN if the certificate signature can't be verified with the ca cert
        return STATUS.VERIFIED if both the signature and the CA sig match
    """
    log_level = log.debug
    if fname is None or sfname is None:
        status = STATUS.UNKNOWN
        log_level('fname=%s or sfname=%s is Nones => status=%s', fname, sfname,
                  status)
        return status
    short_fname = fname.split('/')[-1]
    try:
        with open(sfname, 'r') as fh:
            sig, _, _ = PEM.decode(
                fh.read())  # also returns header and decrypted-status
    except IOError:
        status = STATUS.UNKNOWN
        verif_key = ':'.join([fname, sfname])
        if check_verif_timestamp(verif_key):
            log_level = log.error
        log_level('%s | file "%s" | status: %s ', short_fname, fname, status)
        return status
    x509 = X509AwareCertBucket(public_crt, ca_crt, extra_crt)
    hasher, chosen_hash = hash_target(fname, obj_mode=True)
    digest = hasher.finalize()

    args = {'signature': sig, 'data': digest}
    for crt, txt, status in x509.public_crt:
        log_level = log.debug
        sha256sum = hash_target(fname)
        pubkey = crt.get_pubkey().to_cryptography_key()
        if isinstance(pubkey, rsa.RSAPublicKey):
            args['padding'] = padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                #salt_length=padding.PSS.MAX_LENGTH)
                salt_length=32)
            args['algorithm'] = utils.Prehashed(chosen_hash)
        try:
            pubkey.verify(**args)
            log_level(
                '%s | file "%s" | status: %s | sha256sum: "%s" | public cert fingerprint and requester: "%s"',
                short_fname, fname, status, sha256sum, txt)
            return status
        except InvalidSignature:
            status = STATUS.FAIL
            if check_verif_timestamp(fname):
                log_level = log.critical
            log_level(
                '%s | file "%s" | status: %s | sha256sum: "%s" | public cert fingerprint and requester: "%s"',
                short_fname, fname, status, sha256sum, txt)
            pass
    return STATUS.FAIL