Compare commits

...

3 Commits

2 changed files with 9 additions and 102 deletions

View File

@ -334,7 +334,11 @@ namespace ristretto255 {
std::array<uint8_t, crypto_core_ristretto255_SCALARBYTES> blob;
static_assert(sizeof(blob) == 32, "watch for size and alignment bugs. Everyone should standarize on 256 bit secret keys except for special needs");
explicit scalar() = default;
~scalar() noexcept { wxSecretValue::Wipe(sizeof(*this), this); }
~scalar() noexcept { wxSecretValue::Wipe(sizeof(*this), this); } /*calls wipe to avoid leaving secrets around in memory.
Because wxSecretValue::Wipe is in a different optimisation unit, a separately compiled library,
optimisation of the destructor cannot optimise away the call to the wipe,
because the destructor optimiser does not know that all wipe does is
write to memory that is about to be discarded, nor can the wipe optimiser know that. */
explicit constexpr scalar(std::array<uint8_t, crypto_core_ristretto255_BYTES>&& in) : blob{ in } {};
explicit constexpr scalar(std::array<uint8_t, crypto_core_ristretto255_BYTES>* in) :blob(*in) {};
explicit constexpr scalar(uintmax_t k){ for (auto& j : blob) { j = k; k = k >> 8; } }
@ -345,9 +349,9 @@ namespace ristretto255 {
static_assert (ro::is_standard_signed_integer<T>);
if (i < 0) crypto_core_ristretto255_scalar_negate(&blob[0], &blob[0]);
}
scalar(scalar&&) = default; // Move constructor
scalar(scalar&&) = default; // Move constructor. Does not need to call wipe, because destructor will be called on source
scalar(const scalar&) = default; // Copy constructor
scalar& operator=(scalar&&) = default; // Move assignment.
scalar& operator=(scalar&&) = default; // Move assignment. Does not need to call wipe, because destructor will be called on source
scalar& operator=(const scalar&) = default; // Copy assignment.
/* Don't need constant time equality test
bool operator==(const scalar& sc) const& {

View File

@ -427,9 +427,8 @@ static bool OpenWallet(void) {
fWalletNameOk = true;
}
}
else fWalletNameOk = true;
std::unique_ptr<ISqlite3> db;
if (fWalletNameOk) {
else {
std::unique_ptr<ISqlite3> db;
if (!LastUsedSqlite.FileExists()) throw MyException("Expected wallet file not found", __LINE__, __func__, SrcFilename);
db.reset(Sqlite3_open(LastUsedSqlite.GetFullPath().ToUTF8()));
sql_read_from_misc read_from_misc(db.get());
@ -452,102 +451,6 @@ static bool OpenWallet(void) {
wxLogMessage(wxT("\t\t\"%s\" has expected public key #%s"), name, (wxString)(ro::base58(pubkey).operator const char* ()));
}
}
else {
// At this point in the code the filename LastUsedSqlite is a bad filename, normally the empty string, and the default wallet file does not exist in the default location.
// Construct default wallet and filename*/
wxFileName path{ StandardPaths.GetUserLocalDataDir() };
try {
// Disk operations to create wallet, which may throw.
// This try/catch block exists to catch disk io issues.
if (!path.DirExists())path.Mkdir();
if (!DefaultSqlite.DirExists())DefaultSqlite.Mkdir();
db.reset(Sqlite3_create(DefaultSqlite.GetFullPath().ToUTF8()));
db->exec(R"|(
PRAGMA journal_mode = WAL;
PRAGMA synchronous = 1;
BEGIN IMMEDIATE TRANSACTION;
CREATE TABLE "Keys"(
"ROWID" INTEGER PRIMARY KEY,
"pubkey" BLOB NOT NULL UNIQUE,
"id" integer NOT NULL,
"use" INTEGER NOT NULL
) STRICT;
CREATE UNIQUE INDEX i_pubkey ON Keys (pubkey);
CREATE UNIQUE INDEX i_id ON Keys (use, id);
CREATE TABLE "Names"(
"ROWID" INTEGER PRIMARY KEY,
"name" TEXT NOT NULL UNIQUE
) STRICT;
CREATE UNIQUE INDEX i_names ON Names (name);
CREATE TABLE "Misc"(
"ROWID" INTEGER PRIMARY KEY,
"m" ANY
) STRICT;
COMMIT;
BEGIN IMMEDIATE TRANSACTION;
CREATE VIEW UserZookoIDs AS
SELECT
"Names".name AS name,
"Keys".pubkey AS pubkey
FROM "Names" INNER JOIN "Keys"
ON "Names"."ROWID"="Keys"."id" AND "Keys"."use"=1
ORDER BY LOWER("name"), "name"
COLLATE BINARY;
COMMIT;
BEGIN IMMEDIATE TRANSACTION;
CREATE TRIGGER InsertUserZookoID INSTEAD OF INSERT ON UserZookoIDs FOR EACH ROW BEGIN
INSERT OR FAIL INTO "Names" VALUES(
NULL,
NEW."name"
);
INSERT OR FAIL INTO "Keys" VALUES(
NULL,
NEW."pubkey",
last_insert_rowid(),
1
);
END;
CREATE TRIGGER DeleteUserZookoID INSTEAD OF DELETE ON UserZookoIDs FOR EACH ROW BEGIN
DELETE FROM "Keys" WHERE "Keys"."pubkey" = OLD."pubkey";
DELETE FROM "Names" WHERE "Names"."name" = OLD."name";
END;
COMMIT;
)|");
LastUsedSqlite = DefaultSqlite;
singletonFrame->m_LastUsedWallet = LastUsedSqlite;
wxLogMessage(wxT("\t\tConstructing default wallet %s"), DefaultSqlite.GetFullPath());
// We now have a working wallet file with no valid data. Attempting to create a strong random secret, a name, and public and private keys for that name.
wxLogMessage(wxT("\t\tGenerating random 128 bit wallet secret"));
auto text_secret{ DeriveTextSecret(ristretto255::scalar::random(), 1) };
ro::msec start_time{ ro::msec_since_epoch() };
ristretto255::CMasterSecret MasterSecret(scalar(DeriveStrongSecretHash(&text_secret[0])) );
decltype(start_time) end_time{ ro::msec_since_epoch() };
wxLogMessage(wxT("\t\tStrong secret derivation took %d milliseconds"), (end_time - start_time).count());
sql_update_to_misc update_to_misc(db.get());
update_to_misc(1, WALLET_FILE_IDENTIFIER);
update_to_misc(2, WALLET_FILE_SCHEMA_VERSION_0_0);
update_to_misc(3, &text_secret[0]);
update_to_misc(4, MasterSecret);
sql_insert_name insert_name(db.get());
const char cpsz[]{ "Unit Tester" };
insert_name(cpsz, MasterSecret(cpsz).timesBase());
}
catch (const MyException & e) {
ILogError(R"|(Failed to create or failed to properly initialize wallet)|");
errorCode = 20;
szError = e.what();
ILogError(szError.c_str());
}
} // End of wallet creation branch
}
catch (const MyException& e) {
errorCode = e.what_num();