/* * Copyright (c) 2015 Cryptonomex, Inc., and contributors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * * 1. Any modified source or binaries are used only with the BitShares network. * * 2. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * * 3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #pragma GCC diagnostic ignored "-Wunknown-pragmas" #include #include #include #include #include using std::string; using std::vector; using std::set; using fc::flat_set; using std::map; using graphene::chain::public_key_type; using graphene::chain::digest_type; using graphene::chain::signature_type; using fc::optional; class Transaction; QString toQString(public_key_type k); struct key_data { string label; /** unique label assigned to this key */ /** encrypted as a packed std::string containing a wif private key */ vector encrypted_private_key; int32_t brain_sequence = -1; optional owner; /// if this key was derived from an owner key + sequence }; struct wallet_file { vector encrypted_brain_key; fc::sha512 brain_key_digest; vector encrypted_master_key; fc::sha512 master_key_digest; map encrypted_private_keys; }; /** * @class Wallet * @brief Securely maintains a set of labeled public and private keys * * @note this API is designed for use with QML which does not support exceptions so * all errors are passed via return values. */ class Wallet : public QObject { Q_OBJECT Q_PROPERTY(bool isOpen READ isOpen NOTIFY isOpenChanged) Q_PROPERTY(bool isLocked READ isLocked NOTIFY isLockedChanged) public: Wallet( QObject* parent = nullptr ); ~Wallet(); Q_INVOKABLE bool open(QString file_path); Q_INVOKABLE bool close(); bool isOpen()const; Q_INVOKABLE bool save(); Q_INVOKABLE bool saveAs(QString file_path); Q_INVOKABLE bool create(QString file_path, QString password, QString brain_key = QString()); /** required to generate new owner keys */ Q_INVOKABLE bool loadBrainKey(QString brain_key); /** removes brain key to secure owner keys */ Q_INVOKABLE bool purgeBrainKey(); Q_INVOKABLE bool hasBrainKey()const; /** @pre hasBrainKey() */ Q_INVOKABLE QString getBrainKey(); bool isLocked()const; Q_INVOKABLE bool unlock(QString password); Q_INVOKABLE bool lock(); Q_INVOKABLE bool changePassword(QString new_password); /** * @pre !isLocked(); * @post save() * @return WIF private key */ Q_INVOKABLE QString getActivePrivateKey(QString owner_public_key, uint32_t sequence); Q_INVOKABLE QString getActivePublicKey(QString owner_public_key, uint32_t sequence); /** * @pre !isLocked(); * @pre hasBrainKey(); * @post save() * @return WIF private key */ Q_INVOKABLE QString getOwnerPrivateKey(uint32_t sequence); Q_INVOKABLE QString getOwnerPublicKey(uint32_t sequence); Q_INVOKABLE QString getPublicKey(QString wif_private_key)const; Q_INVOKABLE QString getKeyLabel(QString pubkey); Q_INVOKABLE bool setKeyLabel(QString pubkey, QString label); Q_INVOKABLE QString getPublicKey(QString label); Q_INVOKABLE QString getPrivateKey(QString pubkey); Q_INVOKABLE bool hasPrivateKey(QString pubkey, bool include_with_brain_key = false); /** imports a public key and assigns it a label */ Q_INVOKABLE bool importPublicKey(QString pubkey, QString label = QString()); /** * @param wifkey a private key in (WIF) Wallet Import Format * @pre !isLocked() **/ Q_INVOKABLE bool importPrivateKey(QString wifkey, QString label = QString()); /** removes the key, its lablel and its private key */ Q_INVOKABLE bool removePublicKey(QString pubkey); /** removes only the private key, keeping the public key and label */ Q_INVOKABLE bool removePrivateKey(QString pubkey); /** * @param only_if_private filter any public keys for which the wallet lacks a private key * @return a list of PUBLICKEY, LABEL for all known public keys */ Q_INVOKABLE QList> getAllPublicKeys(bool only_if_private)const; /** * @pre !isLocked() */ vector signDigest(const digest_type& d, const set& keys)const; const flat_set& getAvailablePrivateKeys()const; Q_SIGNALS: void isLockedChanged(bool state); void isOpenChanged(bool state); private: fc::path _wallet_file_path; wallet_file _data; /** used to decrypt all of the encrypted private keys */ fc::sha512 _decrypted_master_key; flat_set _available_private_keys; map _label_to_key; QString _brain_key; }; QML_DECLARE_TYPE(Wallet) FC_REFLECT( key_data, (label)(encrypted_private_key)(brain_sequence)(owner) ) FC_REFLECT( wallet_file, (encrypted_brain_key) (brain_key_digest) (encrypted_master_key) (master_key_digest) (encrypted_private_keys) )