bool Wallet::writeBackupInstructions() { QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html"); QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE); QFile outputFile(outputFilename); bool retval = false; if (QFile::exists(outputFilename) || getKeyFilePath() == "") { return false; } QFile::copy(inputFilename, outputFilename); if (QFile::exists(outputFilename) && outputFile.open(QIODevice::ReadWrite)) { QByteArray fileData = outputFile.readAll(); QString text(fileData); text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath()); outputFile.seek(0); // go to the beginning of the file outputFile.write(text.toUtf8()); // write the new text back to the file outputFile.close(); // close the file handle. retval = true; qCDebug(commerce) << "wrote html file successfully"; } else { qCDebug(commerce) << "failed to open output html file" << outputFilename; } return retval; }
bool Wallet::writeWallet(const QString& newPassphrase) { EC_KEY* keys = readKeys(keyFilePath()); auto ledger = DependencyManager::get<Ledger>(); // Remove any existing locker, because it will be out of date. if (!_publicKeys.isEmpty() && !ledger->receiveAt(_publicKeys.first(), _publicKeys.first(), QByteArray())) { return false; // FIXME: receiveAt could fail asynchronously. } if (keys) { // we read successfully, so now write to a new temp file QString tempFileName = QString("%1.%2").arg(keyFilePath(), QString("temp")); QString oldPassphrase = *_passphrase; if (!newPassphrase.isEmpty()) { setPassphrase(newPassphrase); } if (writeKeys(tempFileName, keys)) { if (writeSecurityImage(_securityImage, tempFileName)) { // ok, now move the temp file to the correct spot QFile(QString(keyFilePath())).remove(); QFile(tempFileName).rename(QString(keyFilePath())); qCDebug(commerce) << "wallet written successfully"; emit keyFilePathIfExistsResult(getKeyFilePath()); if (!walletIsAuthenticatedWithPassphrase() || !ledger->receiveAt()) { // FIXME: Should we fail the whole operation? // Tricky, because we'll need the the key and file from the TEMP location... qCWarning(commerce) << "Failed to update locker"; } return true; } else { qCDebug(commerce) << "couldn't write security image to temp wallet"; } } else { qCDebug(commerce) << "couldn't write keys to temp wallet"; } // if we are here, we failed, so cleanup QFile(tempFileName).remove(); if (!newPassphrase.isEmpty()) { setPassphrase(oldPassphrase); } } else { qCDebug(commerce) << "couldn't read wallet - bad passphrase?"; // TODO: review this, but it seems best to reset the passphrase // since we couldn't decrypt the existing wallet (or is doesn't // exist perhaps). setPassphrase(""); } return false; }
bool Wallet::copyKeyFileFrom(const QString& pathname) { QString existing = getKeyFilePath(); qCDebug(commerce) << "Old keyfile" << existing; if (!existing.isEmpty()) { QString backup = QString(existing).insert(existing.indexOf(KEY_FILE) - 1, QDateTime::currentDateTime().toString(Qt::ISODate).replace(":", "")); qCDebug(commerce) << "Renaming old keyfile to" << backup; if (!QFile::rename(existing, backup)) { qCCritical(commerce) << "Unable to backup" << existing << "to" << backup; return false; } } QString destination = keyFilePath(); bool result = QFile::copy(pathname, destination); qCDebug(commerce) << "copy" << pathname << "to" << destination << "=>" << result; return result; }
bool Wallet::walletIsAuthenticatedWithPassphrase() { // try to read existing keys if they exist... // FIXME: initialize OpenSSL elsewhere soon initialize(); qCDebug(commerce) << "walletIsAuthenticatedWithPassphrase: checking" << (!_passphrase || !_passphrase->isEmpty()); // this should always be false if we don't have a passphrase // cached yet if (!_passphrase || _passphrase->isEmpty()) { if (!getKeyFilePath().isEmpty()) { // If file exists, then it is an old school file that has not been lockered. Must get user's passphrase. qCDebug(commerce) << "walletIsAuthenticatedWithPassphrase: No passphrase, but there is an existing wallet."; return false; } else { qCDebug(commerce) << "walletIsAuthenticatedWithPassphrase: New setup."; setPassphrase("ACCOUNT"); // Going forward, consider this an account-based client. } } if (_publicKeys.count() > 0) { // we _must_ be authenticated if the publicKeys are there DependencyManager::get<WalletScriptingInterface>()->setWalletStatus((uint)WalletStatus::WALLET_STATUS_READY); qCDebug(commerce) << "walletIsAuthenticatedWithPassphrase: wallet was ready"; return true; } // otherwise, we have a passphrase but no keys, so we have to check auto publicKey = readPublicKey(keyFilePath()); if (publicKey.size() > 0) { if (auto key = readPrivateKey(keyFilePath())) { EC_KEY_free(key); // be sure to add the public key so we don't do this over and over _publicKeys.push_back(publicKey.toBase64()); if (*_passphrase != "ACCOUNT") { changePassphrase("ACCOUNT"); // Rewrites with salt and constant, and will be lockered that way. } qCDebug(commerce) << "walletIsAuthenticatedWithPassphrase: wallet now ready"; return true; } } qCDebug(commerce) << "walletIsAuthenticatedWithPassphrase: wallet not ready"; return false; }
bool Wallet::writeBackupInstructions() { QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html"); QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE); QFile inputFile(inputFilename); QFile outputFile(outputFilename); bool retval = false; if (getKeyFilePath().isEmpty()) { return false; } if (QFile::exists(inputFilename) && inputFile.open(QIODevice::ReadOnly)) { if (outputFile.open(QIODevice::ReadWrite)) { // Read the data from the original file, then close it QByteArray fileData = inputFile.readAll(); inputFile.close(); // Translate the data from the original file into a QString QString text(fileData); // Replace the necessary string text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath()); // Write the new text back to the file outputFile.write(text.toUtf8()); // Close the output file outputFile.close(); retval = true; qCDebug(commerce) << "wrote html file successfully"; } else { qCDebug(commerce) << "failed to open output html file" << outputFilename; } } else { qCDebug(commerce) << "failed to open input html file" << inputFilename; } return retval; }
Wallet::Wallet() { auto nodeList = DependencyManager::get<NodeList>(); auto ledger = DependencyManager::get<Ledger>(); auto& packetReceiver = nodeList->getPacketReceiver(); _passphrase = new QString(""); packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "handleChallengeOwnershipPacket"); packetReceiver.registerListener(PacketType::ChallengeOwnershipRequest, this, "handleChallengeOwnershipPacket"); connect(ledger.data(), &Ledger::accountResult, this, [](QJsonObject result) { auto wallet = DependencyManager::get<Wallet>(); auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>(); uint status; QString keyStatus = result.contains("data") ? result["data"].toObject()["keyStatus"].toString() : ""; if (wallet->getKeyFilePath().isEmpty() || !wallet->getSecurityImage()) { if (keyStatus == "preexisting") { status = (uint) WalletStatus::WALLET_STATUS_PREEXISTING; } else { status = (uint) WalletStatus::WALLET_STATUS_NOT_SET_UP; } } else if (!wallet->walletIsAuthenticatedWithPassphrase()) { status = (uint) WalletStatus::WALLET_STATUS_NOT_AUTHENTICATED; } else if (keyStatus == "conflicting") { status = (uint) WalletStatus::WALLET_STATUS_CONFLICTING; } else { status = (uint) WalletStatus::WALLET_STATUS_READY; } walletScriptingInterface->setWalletStatus(status); }); connect(ledger.data(), &Ledger::accountResult, this, &Wallet::sendChallengeOwnershipResponses); auto accountManager = DependencyManager::get<AccountManager>(); connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { getWalletStatus(); clear(); }); }
Wallet::Wallet() { auto nodeList = DependencyManager::get<NodeList>(); auto ledger = DependencyManager::get<Ledger>(); auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "handleChallengeOwnershipPacket"); packetReceiver.registerListener(PacketType::ChallengeOwnershipRequest, this, "handleChallengeOwnershipPacket"); connect(ledger.data(), &Ledger::accountResult, this, [&]() { auto wallet = DependencyManager::get<Wallet>(); auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>(); uint status; if (wallet->getKeyFilePath() == "" || !wallet->getSecurityImage()) { status = (uint)WalletStatus::WALLET_STATUS_NOT_SET_UP; } else if (!wallet->walletIsAuthenticatedWithPassphrase()) { status = (uint)WalletStatus::WALLET_STATUS_NOT_AUTHENTICATED; } else { status = (uint)WalletStatus::WALLET_STATUS_READY; } walletScriptingInterface->setWalletStatus(status); }); auto accountManager = DependencyManager::get<AccountManager>(); connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { getWalletStatus(); _publicKeys.clear(); if (_securityImage) { delete _securityImage; } _securityImage = nullptr; // tell the provider we got nothing updateImageProvider(); _passphrase->clear(); }); }
bool Wallet::writeWallet(const QString& newPassphrase) { EC_KEY* keys = readKeys(keyFilePath().toStdString().c_str()); if (keys) { // we read successfully, so now write to a new temp file QString tempFileName = QString("%1.%2").arg(keyFilePath(), QString("temp")); QString oldPassphrase = *_passphrase; if (!newPassphrase.isEmpty()) { setPassphrase(newPassphrase); } if (writeKeys(tempFileName.toStdString().c_str(), keys)) { if (writeSecurityImage(_securityImage, tempFileName)) { // ok, now move the temp file to the correct spot QFile(QString(keyFilePath())).remove(); QFile(tempFileName).rename(QString(keyFilePath())); qCDebug(commerce) << "wallet written successfully"; emit keyFilePathIfExistsResult(getKeyFilePath()); return true; } else { qCDebug(commerce) << "couldn't write security image to temp wallet"; } } else { qCDebug(commerce) << "couldn't write keys to temp wallet"; } // if we are here, we failed, so cleanup QFile(tempFileName).remove(); if (!newPassphrase.isEmpty()) { setPassphrase(oldPassphrase); } } else { qCDebug(commerce) << "couldn't read wallet - bad passphrase?"; // TODO: review this, but it seems best to reset the passphrase // since we couldn't decrypt the existing wallet (or is doesn't // exist perhaps). setPassphrase(""); } return false; }
void QmlCommerce::getKeyFilePathIfExists() { auto wallet = DependencyManager::get<Wallet>(); emit keyFilePathIfExistsResult(wallet->getKeyFilePath()); }