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
예제 #2
0
 def strip_signatures(key: PGPKey) -> None:
     # pylint: disable=protected-access
     key._signatures = SorteDeque()