mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Merge pull request #15384 from roxanneskelly/Case21707
Case21707 - Wallet doesn't work if user has unicode characters in windows username
This commit is contained in:
commit
d00ba2a9f1
1 changed files with 72 additions and 60 deletions
|
@ -96,28 +96,32 @@ int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EC_KEY* readKeys(const char* filename) {
|
EC_KEY* readKeys(QString filename) {
|
||||||
FILE* fp;
|
QFile file(filename);
|
||||||
EC_KEY *key = NULL;
|
EC_KEY* key = NULL;
|
||||||
if ((fp = fopen(filename, "rt"))) {
|
if (file.open(QFile::ReadOnly)) {
|
||||||
// file opened successfully
|
// file opened successfully
|
||||||
qCDebug(commerce) << "opened key file" << filename;
|
qCDebug(commerce) << "opened key file" << filename;
|
||||||
|
|
||||||
if ((key = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL))) {
|
QByteArray pemKeyBytes = file.readAll();
|
||||||
|
BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length());
|
||||||
|
if ((key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL))) {
|
||||||
// now read private key
|
// now read private key
|
||||||
|
|
||||||
qCDebug(commerce) << "read public key";
|
qCDebug(commerce) << "read public key";
|
||||||
|
|
||||||
if ((key = PEM_read_ECPrivateKey(fp, &key, passwordCallback, NULL))) {
|
if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) {
|
||||||
qCDebug(commerce) << "read private key";
|
qCDebug(commerce) << "read private key";
|
||||||
fclose(fp);
|
BIO_free(bufio);
|
||||||
return key;
|
file.close();
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "failed to read private key";
|
||||||
}
|
}
|
||||||
qCDebug(commerce) << "failed to read private key";
|
|
||||||
} else {
|
} else {
|
||||||
qCDebug(commerce) << "failed to read public key";
|
qCDebug(commerce) << "failed to read public key";
|
||||||
}
|
}
|
||||||
fclose(fp);
|
BIO_free(bufio);
|
||||||
|
file.close();
|
||||||
} else {
|
} else {
|
||||||
qCDebug(commerce) << "failed to open key file" << filename;
|
qCDebug(commerce) << "failed to open key file" << filename;
|
||||||
}
|
}
|
||||||
|
@ -131,8 +135,7 @@ bool Wallet::writeBackupInstructions() {
|
||||||
QFile outputFile(outputFilename);
|
QFile outputFile(outputFilename);
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
if (getKeyFilePath().isEmpty())
|
if (getKeyFilePath().isEmpty()) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +155,7 @@ bool Wallet::writeBackupInstructions() {
|
||||||
outputFile.write(text.toUtf8());
|
outputFile.write(text.toUtf8());
|
||||||
|
|
||||||
// Close the output file
|
// Close the output file
|
||||||
outputFile.close();
|
outputFile.close();
|
||||||
|
|
||||||
retval = true;
|
retval = true;
|
||||||
qCDebug(commerce) << "wrote html file successfully";
|
qCDebug(commerce) << "wrote html file successfully";
|
||||||
|
@ -165,28 +168,35 @@ bool Wallet::writeBackupInstructions() {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool writeKeys(const char* filename, EC_KEY* keys) {
|
bool writeKeys(QString filename, EC_KEY* keys) {
|
||||||
FILE* fp;
|
BIO* bio = BIO_new(BIO_s_mem());
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
if ((fp = fopen(filename, "wt"))) {
|
if (!PEM_write_bio_EC_PUBKEY(bio, keys)) {
|
||||||
if (!PEM_write_EC_PUBKEY(fp, keys)) {
|
BIO_free(bio);
|
||||||
fclose(fp);
|
qCCritical(commerce) << "failed to write public key";
|
||||||
qCCritical(commerce) << "failed to write public key";
|
return retval;
|
||||||
return retval;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!PEM_write_ECPrivateKey(fp, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) {
|
if (!PEM_write_bio_ECPrivateKey(bio, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) {
|
||||||
fclose(fp);
|
BIO_free(bio);
|
||||||
qCCritical(commerce) << "failed to write private key";
|
qCCritical(commerce) << "failed to write private key";
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFile file(filename);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
const char* bio_data;
|
||||||
|
long bio_size = BIO_get_mem_data(bio, &bio_data);
|
||||||
|
|
||||||
|
QByteArray keyBytes(bio_data, bio_size);
|
||||||
|
file.write(keyBytes);
|
||||||
retval = true;
|
retval = true;
|
||||||
qCDebug(commerce) << "wrote keys successfully";
|
qCDebug(commerce) << "wrote keys successfully";
|
||||||
fclose(fp);
|
file.close();
|
||||||
} else {
|
} else {
|
||||||
qCDebug(commerce) << "failed to open key file" << filename;
|
qCDebug(commerce) << "failed to open key file" << filename;
|
||||||
}
|
}
|
||||||
|
BIO_free(bio);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +225,6 @@ QByteArray Wallet::getWallet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QPair<QByteArray*, QByteArray*> generateECKeypair() {
|
QPair<QByteArray*, QByteArray*> generateECKeypair() {
|
||||||
|
|
||||||
EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1);
|
EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||||
QPair<QByteArray*, QByteArray*> retval{};
|
QPair<QByteArray*, QByteArray*> retval{};
|
||||||
|
|
||||||
|
@ -235,7 +244,6 @@ QPair<QByteArray*, QByteArray*> generateECKeypair() {
|
||||||
if (publicKeyLength <= 0 || privateKeyLength <= 0) {
|
if (publicKeyLength <= 0 || privateKeyLength <= 0) {
|
||||||
qCDebug(commerce) << "Error getting DER public or private key from EC struct -" << ERR_get_error();
|
qCDebug(commerce) << "Error getting DER public or private key from EC struct -" << ERR_get_error();
|
||||||
|
|
||||||
|
|
||||||
// cleanup the EC struct
|
// cleanup the EC struct
|
||||||
EC_KEY_free(keyPair);
|
EC_KEY_free(keyPair);
|
||||||
|
|
||||||
|
@ -251,8 +259,7 @@ QPair<QByteArray*, QByteArray*> generateECKeypair() {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!writeKeys(keyFilePath(), keyPair)) {
|
||||||
if (!writeKeys(keyFilePath().toStdString().c_str(), keyPair)) {
|
|
||||||
qCDebug(commerce) << "couldn't save keys!";
|
qCDebug(commerce) << "couldn't save keys!";
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -273,13 +280,18 @@ QPair<QByteArray*, QByteArray*> generateECKeypair() {
|
||||||
// END copied code (which will soon change)
|
// END copied code (which will soon change)
|
||||||
|
|
||||||
// the public key can just go into a byte array
|
// the public key can just go into a byte array
|
||||||
QByteArray readPublicKey(const char* filename) {
|
QByteArray readPublicKey(QString filename) {
|
||||||
FILE* fp;
|
QByteArray retval;
|
||||||
EC_KEY* key = NULL;
|
QFile file(filename);
|
||||||
if ((fp = fopen(filename, "r"))) {
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
// file opened successfully
|
// file opened successfully
|
||||||
qCDebug(commerce) << "opened key file" << filename;
|
qCDebug(commerce) << "opened key file" << filename;
|
||||||
if ((key = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL))) {
|
|
||||||
|
QByteArray pemKeyBytes = file.readAll();
|
||||||
|
BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length());
|
||||||
|
|
||||||
|
EC_KEY* key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL);
|
||||||
|
if (key) {
|
||||||
// file read successfully
|
// file read successfully
|
||||||
unsigned char* publicKeyDER = NULL;
|
unsigned char* publicKeyDER = NULL;
|
||||||
int publicKeyLength = i2d_EC_PUBKEY(key, &publicKeyDER);
|
int publicKeyLength = i2d_EC_PUBKEY(key, &publicKeyDER);
|
||||||
|
@ -287,17 +299,19 @@ QByteArray readPublicKey(const char* filename) {
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
EC_KEY_free(key);
|
EC_KEY_free(key);
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
qCDebug(commerce) << "parsed public key file successfully";
|
qCDebug(commerce) << "parsed public key file successfully";
|
||||||
|
|
||||||
QByteArray retval((char*)publicKeyDER, publicKeyLength);
|
QByteArray retval((char*)publicKeyDER, publicKeyLength);
|
||||||
OPENSSL_free(publicKeyDER);
|
OPENSSL_free(publicKeyDER);
|
||||||
|
BIO_free(bufio);
|
||||||
|
file.close();
|
||||||
return retval;
|
return retval;
|
||||||
} else {
|
} else {
|
||||||
qCDebug(commerce) << "couldn't parse" << filename;
|
qCDebug(commerce) << "couldn't parse" << filename;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
BIO_free(bufio);
|
||||||
|
file.close();
|
||||||
} else {
|
} else {
|
||||||
qCDebug(commerce) << "couldn't open" << filename;
|
qCDebug(commerce) << "couldn't open" << filename;
|
||||||
}
|
}
|
||||||
|
@ -306,13 +320,17 @@ QByteArray readPublicKey(const char* filename) {
|
||||||
|
|
||||||
// the private key should be read/copied into heap memory. For now, we need the EC_KEY struct
|
// the private key should be read/copied into heap memory. For now, we need the EC_KEY struct
|
||||||
// so I'll return that.
|
// so I'll return that.
|
||||||
EC_KEY* readPrivateKey(const char* filename) {
|
EC_KEY* readPrivateKey(QString filename) {
|
||||||
FILE* fp;
|
QFile file(filename);
|
||||||
EC_KEY* key = NULL;
|
EC_KEY* key = NULL;
|
||||||
if ((fp = fopen(filename, "r"))) {
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
// file opened successfully
|
// file opened successfully
|
||||||
qCDebug(commerce) << "opened key file" << filename;
|
qCDebug(commerce) << "opened key file" << filename;
|
||||||
if ((key = PEM_read_ECPrivateKey(fp, &key, passwordCallback, NULL))) {
|
|
||||||
|
QByteArray pemKeyBytes = file.readAll();
|
||||||
|
BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length());
|
||||||
|
|
||||||
|
if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) {
|
||||||
qCDebug(commerce) << "parsed private key file successfully";
|
qCDebug(commerce) << "parsed private key file successfully";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -320,7 +338,8 @@ EC_KEY* readPrivateKey(const char* filename) {
|
||||||
// if the passphrase is wrong, then let's not cache it
|
// if the passphrase is wrong, then let's not cache it
|
||||||
DependencyManager::get<Wallet>()->setPassphrase("");
|
DependencyManager::get<Wallet>()->setPassphrase("");
|
||||||
}
|
}
|
||||||
fclose(fp);
|
BIO_free(bufio);
|
||||||
|
file.close();
|
||||||
} else {
|
} else {
|
||||||
qCDebug(commerce) << "couldn't open" << filename;
|
qCDebug(commerce) << "couldn't open" << filename;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +380,7 @@ Wallet::Wallet() {
|
||||||
if (wallet->getKeyFilePath().isEmpty() || !wallet->getSecurityImage()) {
|
if (wallet->getKeyFilePath().isEmpty() || !wallet->getSecurityImage()) {
|
||||||
if (keyStatus == "preexisting") {
|
if (keyStatus == "preexisting") {
|
||||||
status = (uint) WalletStatus::WALLET_STATUS_PREEXISTING;
|
status = (uint) WalletStatus::WALLET_STATUS_PREEXISTING;
|
||||||
} else{
|
} else {
|
||||||
status = (uint) WalletStatus::WALLET_STATUS_NOT_SET_UP;
|
status = (uint) WalletStatus::WALLET_STATUS_NOT_SET_UP;
|
||||||
}
|
}
|
||||||
} else if (!wallet->walletIsAuthenticatedWithPassphrase()) {
|
} else if (!wallet->walletIsAuthenticatedWithPassphrase()) {
|
||||||
|
@ -371,7 +390,6 @@ Wallet::Wallet() {
|
||||||
} else {
|
} else {
|
||||||
status = (uint) WalletStatus::WALLET_STATUS_READY;
|
status = (uint) WalletStatus::WALLET_STATUS_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
walletScriptingInterface->setWalletStatus(status);
|
walletScriptingInterface->setWalletStatus(status);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -569,10 +587,10 @@ bool Wallet::walletIsAuthenticatedWithPassphrase() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, we have a passphrase but no keys, so we have to check
|
// otherwise, we have a passphrase but no keys, so we have to check
|
||||||
auto publicKey = readPublicKey(keyFilePath().toStdString().c_str());
|
auto publicKey = readPublicKey(keyFilePath());
|
||||||
|
|
||||||
if (publicKey.size() > 0) {
|
if (publicKey.size() > 0) {
|
||||||
if (auto key = readPrivateKey(keyFilePath().toStdString().c_str())) {
|
if (auto key = readPrivateKey(keyFilePath())) {
|
||||||
EC_KEY_free(key);
|
EC_KEY_free(key);
|
||||||
|
|
||||||
// be sure to add the public key so we don't do this over and over
|
// be sure to add the public key so we don't do this over and over
|
||||||
|
@ -631,8 +649,7 @@ QStringList Wallet::listPublicKeys() {
|
||||||
QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
|
QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
|
||||||
EC_KEY* ecPrivateKey = NULL;
|
EC_KEY* ecPrivateKey = NULL;
|
||||||
|
|
||||||
auto keyFilePathString = keyFilePath().toStdString();
|
if ((ecPrivateKey = readPrivateKey(keyFilePath()))) {
|
||||||
if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) {
|
|
||||||
unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)];
|
unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)];
|
||||||
|
|
||||||
unsigned int signatureBytes = 0;
|
unsigned int signatureBytes = 0;
|
||||||
|
@ -641,12 +658,8 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
|
||||||
|
|
||||||
QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256);
|
QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256);
|
||||||
|
|
||||||
|
int retrn = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(hashedPlaintext.constData()), hashedPlaintext.size(),
|
||||||
int retrn = ECDSA_sign(0,
|
sig, &signatureBytes, ecPrivateKey);
|
||||||
reinterpret_cast<const unsigned char*>(hashedPlaintext.constData()),
|
|
||||||
hashedPlaintext.size(),
|
|
||||||
sig,
|
|
||||||
&signatureBytes, ecPrivateKey);
|
|
||||||
|
|
||||||
EC_KEY_free(ecPrivateKey);
|
EC_KEY_free(ecPrivateKey);
|
||||||
QByteArray signature(reinterpret_cast<const char*>(sig), signatureBytes);
|
QByteArray signature(reinterpret_cast<const char*>(sig), signatureBytes);
|
||||||
|
@ -682,7 +695,6 @@ void Wallet::updateImageProvider() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::chooseSecurityImage(const QString& filename) {
|
void Wallet::chooseSecurityImage(const QString& filename) {
|
||||||
|
|
||||||
if (_securityImage) {
|
if (_securityImage) {
|
||||||
delete _securityImage;
|
delete _securityImage;
|
||||||
}
|
}
|
||||||
|
@ -754,7 +766,7 @@ QString Wallet::getKeyFilePath() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wallet::writeWallet(const QString& newPassphrase) {
|
bool Wallet::writeWallet(const QString& newPassphrase) {
|
||||||
EC_KEY* keys = readKeys(keyFilePath().toStdString().c_str());
|
EC_KEY* keys = readKeys(keyFilePath());
|
||||||
auto ledger = DependencyManager::get<Ledger>();
|
auto ledger = DependencyManager::get<Ledger>();
|
||||||
// Remove any existing locker, because it will be out of date.
|
// Remove any existing locker, because it will be out of date.
|
||||||
if (!_publicKeys.isEmpty() && !ledger->receiveAt(_publicKeys.first(), _publicKeys.first(), QByteArray())) {
|
if (!_publicKeys.isEmpty() && !ledger->receiveAt(_publicKeys.first(), _publicKeys.first(), QByteArray())) {
|
||||||
|
@ -768,7 +780,7 @@ bool Wallet::writeWallet(const QString& newPassphrase) {
|
||||||
setPassphrase(newPassphrase);
|
setPassphrase(newPassphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeKeys(tempFileName.toStdString().c_str(), keys)) {
|
if (writeKeys(tempFileName, keys)) {
|
||||||
if (writeSecurityImage(_securityImage, tempFileName)) {
|
if (writeSecurityImage(_securityImage, tempFileName)) {
|
||||||
// ok, now move the temp file to the correct spot
|
// ok, now move the temp file to the correct spot
|
||||||
QFile(QString(keyFilePath())).remove();
|
QFile(QString(keyFilePath())).remove();
|
||||||
|
@ -834,10 +846,10 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer<ReceivedMessage> pack
|
||||||
challengingNodeUUID = packet->read(challengingNodeUUIDByteArraySize);
|
challengingNodeUUID = packet->read(challengingNodeUUIDByteArraySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
EC_KEY* ec = readKeys(keyFilePath().toStdString().c_str());
|
EC_KEY* ec = readKeys(keyFilePath());
|
||||||
QString sig;
|
QString sig;
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
sig = signWithKey(text, ""); // base64 signature, QByteArray cast (on return) to QString FIXME should pass ec as string so we can tell which key to sign with
|
sig = signWithKey(text, ""); // base64 signature, QByteArray cast (on return) to QString FIXME should pass ec as string so we can tell which key to sign with
|
||||||
status = 1;
|
status = 1;
|
||||||
|
|
Loading…
Reference in a new issue