def _nosecrete_private_key(pubkey):
     """ Create the parent certify key without the private parts """
     km = OpaquePrivKey()
     km.parse(pubkey.keymaterial.__bytearray__())
     # S2K GNU extension: private key without secrete parts
     km.s2k.parse(bytearray(b'\xff\x00\x65\x00GNU\x01'))
     # wrap key material in PrivKeyV4 containing info about algo, creation timestamp, ...
     privkey = PrivKeyV4()
     privkey.pkalg = pubkey.pkalg
     privkey.keymaterial = km
     privkey.created = pubkey.created
     privkey.update_hlen()
     # wrap private key in a PGPKey object
     key = PGPKey()
     key._key = privkey
     return key
    def _create_private_key(self, pubkey, subkey=True):
        """ Create a private (sub)key from public key and firmware key material """
        fp = bytes(pubkey.fingerprint)
        if fp not in self._keys:
            return None
        key = self._keys[fp]
        pubkm = pubkey._key.keymaterial

        if key.algo == KeyAlgo.RSA2048 or key.algo == KeyAlgo.RSA4096:
            assert pubkey._key.pkalg in [PubKeyAlgorithm.RSAEncryptOrSign,
                    PubKeyAlgorithm.RSAEncrypt, PubKeyAlgorithm.RSASign]
            plen = len(key.priv) // 2
            km = RSAPriv()
            km.n = pubkm.n
            km.e = pubkm.e
            km.p = MPI(MPIs.bytes_to_int(key.priv[:plen]))
            km.q = MPI(MPIs.bytes_to_int(key.priv[plen:]))
            km.d = MPI(rsa.rsa_crt_iqmp((km.p-1) * (km.q-1), km.e))
            km.u = MPI(rsa.rsa_crt_iqmp(km.q, km.p))
        elif key.algo == KeyAlgo.CURVE25519:
            km = ECDHPriv()
            km.oid = EllipticCurveOID.Curve25519
            km.p = pubkm.p
            km.kdf = pubkm.kdf
            # GnuPG stores the secret value in the wrong order
            # https://lists.gnupg.org/pipermail/gnupg-devel/2018-February/033437.html
            km.s = MPI(MPIs.bytes_to_int(key.priv, 'little'))
        elif key.algo == KeyAlgo.ED25519:
            # GNUK stores "SHA-512(secret)"
            # PGP private key stores "secret"
            logging.warning("Cannot extract Ed25519 key: GNUK format incompatible with PGP format\n"
                            "          sha512(secret) = {}".format(hexlify(key.priv).decode('utf-8')))
            return None
        elif key.algo in [KeyAlgo.SECP256K1, KeyAlgo.NISTP256R1]:
            # Secp256k1 can be used with both ECDH and ECDSA
            if isinstance(pubkm, ECDSAPub):
                km = ECDSAPriv()
            elif isinstance(pubkm, ECDHPub):
                km = ECDHPriv()
                km.kdf = pubkm.kdf
            else:
                raise Exception("Curve {} cannot be used with algorithm {}".format(
                    str(key.algo), pubkm.__class__.__name__))
            if key.algo == KeyAlgo.SECP256K1:
                km.oid = EllipticCurveOID.SECP256K1
            elif key.algo == KeyAlgo.NISTP256R1:
                km.oid = EllipticCurveOID.NIST_P256
            else:
                raise Exception("Should not happen")
            km.p = pubkm.p
            km.s = MPI(MPIs.bytes_to_int(key.priv))
        else:
            # https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-06
            raise Exception("Key algo {} not implemented yet".format(str(key.algo)))

        km._compute_chksum()
        privkey = PrivSubKeyV4() if subkey else PrivKeyV4()
        privkey.pkalg = pubkey._key.pkalg
        privkey.keymaterial = km
        privkey.created = pubkey._key.created
        privkey.update_hlen()
        key = PGPKey()
        key._key = privkey
        key._signatures = pubkey._signatures
        return key
Esempio n. 3
0
                rsa_priv = RSAPriv()
                rsa_priv.e = MPI(int(gpg['e'], 16))
                rsa_priv.n = MPI(int(gpg['n'], 16))
                rsa_priv.d = MPI(int(gpg['d'], 16))
                rsa_priv.p = MPI(int(gpg['p'], 16))
                rsa_priv.q = MPI(int(gpg['q'], 16))
                rsa_priv.u = MPI(int(gpg['u'], 16))
                rsa_priv._compute_chksum()

                restored_priv_key = PrivKeyV4()
                restored_priv_key.pkalg = PubKeyAlgorithm.RSAEncryptOrSign
                restored_priv_key.keymaterial = rsa_priv
                restored_priv_key.update_hlen()

                pgp_key = PGPKey()
                pgp_key._key = restored_priv_key

                public_key, _ = PGPKey.from_blob(gpg['public'])
                # fingerprint contains cration date so we need explicit copy this one
                pgp_key._key.created = public_key._key.created

                pgp_key.add_uid(public_key.userids[0],
                                usage={
                                    KeyFlags.Sign,
                                    KeyFlags.EncryptCommunications,
                                    KeyFlags.EncryptStorage
                                },
                                hashes=[
                                    HashAlgorithm.SHA256, HashAlgorithm.SHA384,
                                    HashAlgorithm.SHA512, HashAlgorithm.SHA224
                                ],