Exemple #1
0
def get_private_key() -> bytes:
    app_path = click.get_app_dir("ledgerctl")
    if not os.path.exists(app_path):
        os.makedirs(app_path)

    cfg_file = os.path.join(app_path, "config.ini")
    try:
        config = configparser.RawConfigParser()
        config.read(cfg_file)

        default_config = config["DEFAULT"]
        private_key = bytes.fromhex(default_config["private_key"])
    except KeyError:
        new_private_key = PrivateKey()
        public_key = new_private_key.pubkey
        pubkey_bytes = public_key.serialize(compressed=False)

        config = configparser.RawConfigParser()
        config["DEFAULT"] = {
            "public_key": pubkey_bytes.hex(),
            "private_key": new_private_key.serialize().hex(),
        }
        with click.open_file(cfg_file, "w") as f:
            config.write(f)
        private_key = bytes.fromhex(new_private_key.serialize().hex())

    return private_key
Exemple #2
0
 def __init__(self, device, cla=0xE0, private_key=None):
     self.device = device
     self.cla = cla
     self._target_id = None
     self.scp = None
     if private_key is None:
         self.private_key = PrivateKey()
     else:
         self.private_key = PrivateKey(private_key)
     device.open()
Exemple #3
0
 def __init__(self, device=None, cla=0xE0, private_key=None):
     if device is None:
         devices = enumerate_devices()
         if len(devices) == 0:
             raise NoLedgerDeviceException("No Ledger device has been found.")
         device = devices[0]
     self.device = device
     self.cla = cla
     self._target_id = None
     self.scp = None
     if private_key is None:
         self.private_key = PrivateKey()
     else:
         self.private_key = PrivateKey(private_key)
     self.device.open()
Exemple #4
0
 def test_get_ecdh_secret(self, client):
     pubkey = PrivateKey().pubkey.serialize(compressed=False)
     payload = Bip32Path.build(DEFAULT_PATH) + pubkey
     client.apdu_exchange(self.INS,
                          payload,
                          sw1=P1.FIRST,
                          sw2=Curve.PRIME256)
Exemple #5
0
    def receive_certificate_chain(self):
        cert_chain = []
        if self.cert_chain is not None:
            cert_chain.append(self.cert_chain)
        else:
            data_to_sign = bytes([CERT_ROLE_SIGNER]) + self.master_public
            master_signature = self.master_private.sign(data_to_sign)
            cert_chain.append(
                serialize(self.master_public) + serialize(master_signature))

        # Provide the ephemeral certificate, signed with the master public key
        self.ephemeral_private = PrivateKey()
        ephemeral_public = self.ephemeral_private.pubkey.serialize(
            compressed=False)
        # print("Using ephemeral key {}".format(ephemeral_public.hex()))

        data_to_sign = (bytes([CERT_ROLE_SIGNER_EPHEMERAL]) +
                        self.server_nonce + self.device_nonce +
                        ephemeral_public)
        signature = self.master_private.sign(data_to_sign)
        cert_chain.append(serialize(ephemeral_public) + serialize(signature))

        return cert_chain
Exemple #6
0
def install_ca(get_client, name, public_key):
    if public_key is None:
        raw_private_key = get_private_key()
        pubkey_bytes = PrivateKey(raw_private_key).pubkey.serialize(compressed=False)
    else:
        pubkey_bytes = bytes.fromhex(public_key)

    try:
        get_client().install_ca(name, pubkey_bytes)
        click.echo("Custom certificate has been successfully installed.")
    except CommException as e:
        if e.sw == 0x6982:
            click.echo("A certificate is already installed on the device.")
        elif e.sw == 0x6802:  # INVALID_PARAMETER
            click.echo("The provided certificate is invalid.")
        else:
            raise
Exemple #7
0
class SimpleServer(LedgerServer):
    def __init__(self, master_private: PrivateKey, cert_chain=None):
        self.device_nonce = None
        self.server_nonce = None
        self.master_private = master_private
        self.master_public = master_private.pubkey.serialize(False)
        self.shared_secret = None
        self.ephemeral_private = None

        self.cert_chain = cert_chain

    def receive_certificate_chain(self):
        cert_chain = []
        if self.cert_chain is not None:
            cert_chain.append(self.cert_chain)
        else:
            data_to_sign = bytes([CERT_ROLE_SIGNER]) + self.master_public
            master_signature = self.master_private.sign(data_to_sign)
            cert_chain.append(
                serialize(self.master_public) + serialize(master_signature))

        # Provide the ephemeral certificate, signed with the master public key
        self.ephemeral_private = PrivateKey()
        ephemeral_public = self.ephemeral_private.pubkey.serialize(
            compressed=False)
        # print("Using ephemeral key {}".format(ephemeral_public.hex()))

        data_to_sign = (bytes([CERT_ROLE_SIGNER_EPHEMERAL]) +
                        self.server_nonce + self.device_nonce +
                        ephemeral_public)
        signature = self.master_private.sign(data_to_sign)
        cert_chain.append(serialize(ephemeral_public) + serialize(signature))

        return cert_chain

    def send_certicate_chain(self, chain):
        assert len(chain) == 2

        last_dev_pub_key = PublicKey(self.master_public)
        for i, item in enumerate(chain):
            certificate_header, item = unserialize(item)
            certificate_public_key, item = unserialize(item)
            certificate_signature_array, _ = unserialize(item)
            certificate_signature = certificate_signature_array

            # first cert contains a header field which holds the certificate's public key role
            if i == 0:
                # device_public_key = certificate_public_key
                certificate_signed_data = (bytes([CERT_ROLE_DEVICE]) +
                                           certificate_header +
                                           certificate_public_key)
            # Could check if the device certificate is signed by the issuer public key
            # ephemeral key certificate
            else:
                certificate_signed_data = (
                    bytes([CERT_ROLE_DEVICE_EPHEMERAL]) + self.device_nonce +
                    self.server_nonce + certificate_public_key)

            if not last_dev_pub_key.verify(certificate_signed_data,
                                           certificate_signature):
                """
                if index == 0:
                    # Not an error if loading from user key
                    print("Broken certificate chain - loading from user key")
                else:
                    raise Exception("Broken certificate chain")
                """
                if i != 0:
                    raise Exception("Broken certificate chain")

            last_dev_pub_key = PublicKey(certificate_public_key)
        self.shared_secret = self.ephemeral_private.exchange(last_dev_pub_key)

    def get_nonce(self) -> bytes:
        self.server_nonce = os.urandom(8)
        return self.server_nonce

    def send_nonce(self, nonce: bytes):
        assert len(nonce) == 8
        self.device_nonce = nonce

    def get_shared_secret(self):
        return self.shared_secret