Ejemplo n.º 1
0
    /// <summary>
    /// Encrypts the wallet data asynchronously.
    /// </summary>
    /// <param name="seed"> The <see langword="byte"/>[] seed to encrypt. </param>
    /// <param name="password"> The base password to use for encryption, retrieved from the user input. </param>
    /// <param name="onWalletEncrypted"> Action called once the wallet has been encrypted. </param>
    private void AsyncEncryptWallet(
        byte[] seed,
        byte[] password,
        Action <string[], string, string> onWalletEncrypted)
    {
        string[] encryptedHashes    = null;
        string   saltedPasswordHash = null;
        string   encryptedSeed      = null;

        byte[] derivedPassword = playerPrefPassword.Derive(password);

        using (var dataEncryptor = new DataEncryptor(new AdvancedSecureRandom(new Blake2bDigest(512), derivedPassword)))
        {
            byte[] hash1 = RandomBytes.Secure.Blake2.GetBytes(512);
            byte[] hash2 = RandomBytes.Secure.Blake2.GetBytes(1024);

            saltedPasswordHash = new PBKDF2PasswordHashing(new Blake2b_512_Engine()).GetSaltedPasswordHash(password).GetBase64String();
            encryptedSeed      = dataEncryptor.Encrypt(dataEncryptor.Encrypt(seed.GetHexString(), hash1), hash2);

            encryptedHashes = new string[]
            {
                dataEncryptor.Encrypt(hash1).GetBase64String(),
                dataEncryptor.Encrypt(hash2).GetBase64String()
            };

            hash1.ClearBytes();
            hash2.ClearBytes();
        }

        dynamicDataCache.SetData("pass", new ProtectedString(password, this));
        dynamicDataCache.SetData("mnemonic", null);

        MainThreadExecutor.QueueAction(() => onWalletEncrypted?.Invoke(encryptedHashes, saltedPasswordHash, encryptedSeed));
    }
    /// <summary>
    /// Checks if the hardware wallet is connected and invokes any required events.
    /// </summary>
    public async void PeriodicUpdate()
    {
        if (isPolling || initializing)
        {
            return;
        }

        isPolling = true;

        bool isConnected = await IsHardwareWalletConnected().ConfigureAwait(false);

        if (!isConnected)
        {
            if (wasConnected)
            {
                MainThreadExecutor.QueueAction(() => OnHardwareWalletDisconnected?.Invoke());
            }
        }
        else
        {
            if (!wasConnected)
            {
                MainThreadExecutor.QueueAction(() => OnHardwareWalletConnected?.Invoke());
            }
        }

        wasConnected = isConnected;
        isPolling    = false;
    }
Ejemplo n.º 3
0
 /// <summary>
 /// Downloads a string from a url.
 /// </summary>
 /// <param name="url"> The url which contains the string data. </param>
 /// <param name="onStringReceived"> Action to call once the string has been received. </param>
 public static void DownloadString(string url, Action<string> onStringReceived)
 {
     Task.Factory.StartNew(async () =>
     {
         string downloadedString = await DownloadString(url).ConfigureAwait(false);
         MainThreadExecutor.QueueAction(() => onStringReceived?.Invoke(downloadedString));
     });
 }
    /// <summary>
    /// Generates a spoof key asynchronously.
    /// </summary>
    /// <returns> The task used for generating the spoof key. </returns>
    private async Task GenerateSpoofKey()
    {
        string key = await Task.Run(() => RandomString.Secure.SHA3.GetString(PASSWORD_LENGTH)).ConfigureAwait(false);

        string value = await Task.Run(() => RandomString.Secure.SHA3.GetString()).ConfigureAwait(false);

        MainThreadExecutor.QueueAction(() => SecurePlayerPrefsAsync.SetString(key, value));
    }
Ejemplo n.º 5
0
    /// <summary>
    /// Called when the pin needs to be entered.
    /// Invokes the ReloadPINSection event.
    /// </summary>
    public void ReEnterPIN()
    {
        if (!checkingPin)
        {
            return;
        }

        MainThreadExecutor.QueueAction(() => ReloadPINSection?.Invoke());

        checkingPin = false;
    }
Ejemplo n.º 6
0
    /// <summary>
    /// Calls events based on the current status of the pin section.
    /// </summary>
    public void UpdatePINSection()
    {
        if (!pinSectionOpen)
        {
            pinSectionOpen = true;

            MainThreadExecutor.QueueAction(() => TrezorPINSectionOpening?.Invoke());
        }
        else
        {
            MainThreadExecutor.QueueAction(() => ReloadPINSection?.Invoke());
        }
    }
Ejemplo n.º 7
0
    /// <summary>
    /// Decrypts the wallet given the user's password.
    /// </summary>
    /// <param name="walletInfo"> The wallet to decrypt. </param>
    /// <param name="password"> The user's password to the wallet. </param>
    /// <param name="onWalletDecrypted"> Action called once the wallet has been decrypted, passing the <see langword="byte"/>[] seed of the wallet. </param>
    public void DecryptWallet(WalletInfo walletInfo, byte[] password, Action <byte[]> onWalletDecrypted)
    {
        MainThreadExecutor.QueueAction(() =>
        {
            playerPrefPassword.PopulatePrefDictionary(walletInfo.WalletAddresses[0][0]);

            Task.Factory.StartNew(() => AsyncDecryptWallet(
                                      walletInfo.EncryptedWalletData.EncryptionHashes,
                                      walletInfo.EncryptedWalletData.EncryptedSeed,
                                      password,
                                      onWalletDecrypted));
        });
    }
    public void SignTransaction(string walletAddress, string path, byte[] encryptedPasswordBytes, Action <TransactionSignedUnityRequest> onRequestReceived)
    {
        var plainTextBytes = passwordEncryptor.Decrypt(encryptedPasswordBytes);

        walletDecryptor.DecryptWallet(hopeWalletInfoManager.GetWalletInfo(walletAddress), plainTextBytes, seed =>
        {
            TransactionSignedUnityRequest request = new TransactionSignedUnityRequest(
                new Wallet(seed, path).GetAccount(walletAddress),
                ethereumNetworkManager.CurrentNetwork.NetworkUrl);

            MainThreadExecutor.QueueAction(() => onRequestReceived?.Invoke(request));
            ClearData(seed, plainTextBytes);
        });
    }
Ejemplo n.º 9
0
    /// <summary>
    /// Sets a string value to the <see cref="SecurePlayerPrefs"/> asynchronously.
    /// Gets the secure key, secure entropy, and encrypted value all asynchronously.
    /// </summary>
    /// <param name="baseKeyEncrypted"> The encrypted base key to use to get the secure key of this SecurePlayerPref. </param>
    /// <param name="key"> The key to use to set the PlayerPref. </param>
    /// <param name="value"> The value to use for the PlayerPref. </param>
    /// <param name="onValueSet"> Action called once the PlayerPref has been set successfully. </param>
    /// <returns> The task for creating the hashed key/values and setting the PlayerPref. </returns>
    private static async Task InternalSetString(string baseKeyEncrypted, string key, string value, Action onValueSet)
    {
        string secureKey = await GetSecureKey(baseKeyEncrypted, key).ConfigureAwait(false);

        string secureEntropy = await Task.Run(() => GetValueHash(secureKey)).ConfigureAwait(false);

        string encryptedValue = await Task.Run(() => dataEncryptor.Encrypt(value, secureEntropy)).ConfigureAwait(false);

        MainThreadExecutor.QueueAction(() =>
        {
            PlayerPrefs.SetString(secureKey, encryptedValue);
            onValueSet?.Invoke();
        });
    }
Ejemplo n.º 10
0
        //[ReflectionProtect(typeof(DisposableData<string>))]
        public DisposableDataPromise <TType> CreateDisposableData()
        {
            DisposableDataPromise <TType> promise = new DisposableDataPromise <TType>();

            byte[] data = memoryEncryptor.Decrypt(protectedData);

            AsyncTaskScheduler.Schedule(() => Task.Run(() =>
            {
                SetValue((byte[])data.Clone());

                GC.Collect();

                disposableData = disposableData?.Disposed != false ? (TDisposable)Activator.CreateInstance(typeof(TDisposable), data) : disposableData;
                MainThreadExecutor.QueueAction(() => promise.Build(() => disposableData));
            }));

            return(promise);
        }
Ejemplo n.º 11
0
    /// <summary>
    /// Queries the transaction data for a TradableAsset.
    /// </summary>
    /// <param name="query1"> The first query for the TradableAsset's transaction data. </param>
    /// <param name="query2"> The second query for the TradableAsset's transaction data. </param>
    private void QueryTransactionData(AssetTransactionQuery query1, AssetTransactionQuery query2)
    {
        query1.Query?.Invoke().OnSuccess(txData1 =>
        {
            query2.Query?.Invoke().OnSuccess(txData2 =>
            {
                Observable.Start(() =>
                {
                    query1.ProcessTransactionList(txData1, query1.AssetAddress, query1.IgnoreReceipt);
                    query2.ProcessTransactionList(txData2, query2.AssetAddress, query2.IgnoreReceipt);
                }).SubscribeOnMainThread().Subscribe(_ =>
                {
                    addressLastUpdatedTimes.AddOrReplace(query1.AssetAddress, DateTimeUtils.GetCurrentUnixTime());

                    MainThreadExecutor.QueueAction(() => OnTransactionsAdded?.Invoke());
                    isScraping = false;
                });
            });
        });
    }
        private void OnNewWalletEncrypted(string[] hashes, string passwordHash, string encryptedSeed)
        {
            hopeWalletInfoManager.UpdateWalletInfo(
                walletInfo.WalletNum,
                new WalletInfo(
                    new WalletInfo.EncryptedDataContainer(hashes, encryptedSeed, passwordHash),
                    walletInfo.WalletName,
                    walletInfo.WalletAddresses,
                    walletInfo.WalletNum));

            playerPrefPasswordDerivation.SetupPlayerPrefs(walletInfo.WalletAddresses[0][0], () =>
            {
                MainThreadExecutor.QueueAction(() =>
                {
                    newPasswordField.Text     = string.Empty;
                    confirmPasswordField.Text = string.Empty;
                    settingsPopupAnimator.ShowLoadingIcon(saveButton.gameObject, loadingIcon, false);
                    settingsPopupAnimator.AnimateIcon(saveButton.transform.GetChild(0).gameObject);
                });
            }, false);
        }
Ejemplo n.º 13
0
    /// <summary>
    /// Gets the public key data from the Trezor wallet.
    /// </summary>
    /// <returns> Task returning the ExtendedPublicKeyDataHolder instance. </returns>
    protected override async Task <ExtendedPublicKeyDataHolder> GetExtendedPublicKeyData()
    {
        var trezorManager = TrezorConnector.GetWindowsConnectedTrezor(GetExtendedPublicKeyDataEnterPin);

        if (trezorManager == null)
        {
            return(null);
        }

        var publicKeyRequest = new GetPublicKey {
            AddressNs = KeyPath.Parse(EXTENDED_PUBLIC_KEY_PATH).Indexes, ShowDisplay = false
        };
        var publicKeyResponse = (PublicKey)null;

        while (publicKeyResponse == null)
        {
            try
            {
                publicKeyResponse = await trezorManager.SendMessageAsync <PublicKey, GetPublicKey>(publicKeyRequest).ConfigureAwait(false);
            }
            catch (FailureException <Failure> )
            {
                MainThreadExecutor.QueueAction(() => PINIncorrect?.Invoke());

                publicKeyResponse = null;
                advance           = false;
            }
        }

        if (publicKeyResponse == null)
        {
            return(null);
        }

        return(new ExtendedPublicKeyDataHolder {
            publicKeyData = publicKeyResponse.Node.PublicKey, chainCodeData = publicKeyResponse.Node.ChainCode
        });
    }
Ejemplo n.º 14
0
    /// <summary>
    /// Enter pin callback for when the Trezor is requested a transaction signature.
    /// </summary>
    /// <returns> Task returning the pin string. </returns>
    private async Task <string> GetSignedTransactionDataEnterPin()
    {
        var popup = (EnterTrezorPINPopup)null;

        MainThreadExecutor.QueueAction(() => popup = popupManager.GetPopup <EnterTrezorPINPopup>(true));

        while (popup == null)
        {
            await Task.Delay(100);
        }

        var advanceAction = new UnityAction(() => advance = true);

        popup.ReEnterPIN();
        popup.TrezorPINSection.NextButton.onClick.AddListener(advanceAction);

        while (!advance)
        {
            if (popupManager.ActivePopupType != typeof(EnterTrezorPINPopup))
            {
                forceCancel = true;
                advance     = false;

                return(string.Empty);
            }

            await Task.Delay(100);
        }

        advance = false;

        popup.CheckPIN();
        popup.TrezorPINSection.NextButton.onClick.RemoveListener(advanceAction);

        return(popup.TrezorPINSection.PinText);
    }
Ejemplo n.º 15
0
    /// <summary>
    /// Method used for initializing all the addresses for this hardware wallet.
    /// </summary>
    public async void InitializeAddresses()
    {
        addresses[0] = new string[50];
        addresses[1] = new string[50];

        var data = await GetExtendedPublicKeyData().ConfigureAwait(false);

        if (data == null || data.chainCodeData.Length != 32)
        {
            MainThreadExecutor.QueueAction(WalletLoadUnsuccessful);
            return;
        }

        var electrumLedgerXPub = new ExtPubKey(new PubKey(data.publicKeyData).Compress(), data.chainCodeData);
        var defaultXPub        = electrumLedgerXPub.Derive(0);

        for (uint i = 0; i < addresses[0].Length; i++)
        {
            addresses[0][i] = new EthECKey(defaultXPub.Derive(i).PubKey.ToBytes(), false).GetPublicAddress().ConvertToEthereumChecksumAddress();
            addresses[1][i] = new EthECKey(electrumLedgerXPub.Derive(i).PubKey.ToBytes(), false).GetPublicAddress().ConvertToEthereumChecksumAddress();
        }

        MainThreadExecutor.QueueAction(WalletLoadSuccessful);
    }
Ejemplo n.º 16
0
 /// <summary>
 /// Calls the CheckingPIN event.
 /// </summary>
 public void CheckPIN()
 {
     MainThreadExecutor.QueueAction(() => CheckingPIN?.Invoke());
 }
Ejemplo n.º 17
0
    /// <summary>
    /// Signs a transaction using this IWallet.
    /// </summary>
    /// <typeparam name="T"> The type of the popup to display the transaction confirmation for. </typeparam>
    /// <param name="onTransactionSigned"> The action to call if the transaction is confirmed and signed. </param>
    /// <param name="gasLimit"> The gas limit to use with the transaction. </param>
    /// <param name="gasPrice"> The gas price to use with the transaction. </param>
    /// <param name="value"> The amount of ether in wei being sent along with the transaction. </param>
    /// <param name="addressFrom"> The address of the wallet signing the transaction. </param>
    /// <param name="addressTo"> The address the transaction is being sent to. </param>
    /// <param name="data"> The data sent along with the transaction. </param>
    /// <param name="path"> The path of the wallet to sign the transaction with. </param>
    /// <param name="displayInput"> The display input that goes along with the transaction request. </param>
    public void SignTransaction <T>(
        Action <TransactionSignedUnityRequest> onTransactionSigned,
        BigInteger gasLimit,
        BigInteger gasPrice,
        BigInteger value,
        string addressFrom,
        string addressTo,
        string data,
        string path,
        params object[] displayInput) where T : ConfirmTransactionPopupBase <T>
    {
        if (signingTransaction)
        {
            return;
        }

        signingTransaction = true;

        TransactionUtils.GetAddressTransactionCount(addressFrom).OnSuccess(async txCount =>
        {
            var currentPopupType = popupManager.ActivePopupType;

            var transaction = new Transaction(
                txCount.ToBytesForRLPEncoding(),
                gasPrice.ToBytesForRLPEncoding(),
                gasLimit.ToBytesForRLPEncoding(),
                addressTo.HexToByteArray(),
                value.ToBytesForRLPEncoding(),
                data.HexToByteArray(),
                new byte[] { 0 },
                new byte[] { 0 },
                (byte)ethereumNetworkSettings.networkType);

            var signedTransactionData = await GetSignedTransactionData(
                transaction,
                path,
                () => MainThreadExecutor.QueueAction(() => popupManager.GetPopup <T>(true)?.SetConfirmationValues(null, gasLimit, gasPrice, displayInput))).ConfigureAwait(false);

            signingTransaction = false;

            if (signedTransactionData == null)
            {
                return;
            }
            else if (!signedTransactionData.signed)
            {
                if (currentPopupType != popupManager.ActivePopupType)
                {
                    MainThreadExecutor.QueueAction(() => popupManager.CloseActivePopup());
                }

                return;
            }

            var transactionChainId = new TransactionChainId(
                transaction.Nonce,
                transaction.GasPrice,
                transaction.GasLimit,
                transaction.ReceiveAddress,
                transaction.Value,
                transaction.Data,
                new byte[] { (byte)ethereumNetworkSettings.networkType },
                signedTransactionData.r,
                signedTransactionData.s,
                new byte[] { (byte)signedTransactionData.v });

            MainThreadExecutor.QueueAction(() =>
            {
                onTransactionSigned?.Invoke(new TransactionSignedUnityRequest(transactionChainId.GetRLPEncoded().ToHex(), ethereumNetworkManager.CurrentNetwork.NetworkUrl));
                popupManager.CloseAllPopups();
            });
        });
    }