SVN
This commit is contained in:
231
Managers/CryptoManager.cs
Normal file
231
Managers/CryptoManager.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace SimPas2_Windows.Managers
|
||||
{
|
||||
internal class CryptoManager
|
||||
{
|
||||
private readonly string mConnectionString;
|
||||
private readonly byte[] mEncryptionKey;
|
||||
private readonly string mCulture;
|
||||
|
||||
private string mJpLang;
|
||||
|
||||
public CryptoManager(string databasePath, byte[] encryptionKey, string culture)
|
||||
{
|
||||
mConnectionString = $"Data Source={databasePath}";
|
||||
mEncryptionKey = encryptionKey ?? throw new ArgumentNullException(nameof(encryptionKey));
|
||||
mCulture = culture;
|
||||
|
||||
mJpLang = "ja-JP";
|
||||
}
|
||||
|
||||
private bool AlreadyExists(string currency, string name, int? excludeId = null)
|
||||
{
|
||||
using (SqliteConnection conn = new SqliteConnection(mConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
SqliteCommand com = conn.CreateCommand();
|
||||
com.CommandText = @"
|
||||
SELECT COUNT(*) FROM Crypto
|
||||
WHERE UPPER(Currency) = UPPER(@currency) AND UPPER(Name) = UPPER(@name)";
|
||||
com.Parameters.AddWithValue("@currency", currency);
|
||||
com.Parameters.AddWithValue("@name", name);
|
||||
|
||||
if (excludeId.HasValue)
|
||||
{
|
||||
com.CommandText += " AND Id != @excludeId";
|
||||
com.Parameters.AddWithValue("@excludeId", excludeId.Value);
|
||||
}
|
||||
|
||||
return Convert.ToInt32(com.ExecuteScalar()) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddCrypto(string currency, string name, string address, string seed, string viewkey, string spendkey, string height, string password, string note)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(currency) || string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
string err = mCulture == mJpLang
|
||||
? "通貨、ウォレット名及び、住所を御入力下さい。"
|
||||
: "Please fill in the currency, wallet name, and address.";
|
||||
throw new ArgumentException(err);
|
||||
}
|
||||
|
||||
string encryptedPassword = !string.IsNullOrWhiteSpace(password) ? EncryptInfo(password) : "";
|
||||
string encryptedSeed = !string.IsNullOrWhiteSpace(seed) ? EncryptInfo(seed) : "";
|
||||
string encryptedViewkey = !string.IsNullOrWhiteSpace(viewkey) ? EncryptInfo(viewkey) : "";
|
||||
string encryptedSpendkey = !string.IsNullOrWhiteSpace(spendkey) ? EncryptInfo(spendkey) : "";
|
||||
|
||||
if (AlreadyExists(currency, name))
|
||||
{
|
||||
string err = mCulture == mJpLang
|
||||
? $"通貨及びウォレット名「{currency}/{name}」エントリは既に存在します。"
|
||||
: $"An entry with the currency and wallet name for '{currency}/{name}' already exists.";
|
||||
throw new ArgumentException(err);
|
||||
}
|
||||
|
||||
using (SqliteConnection conn = new SqliteConnection(mConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
SqliteCommand com = conn.CreateCommand();
|
||||
com.CommandText = @"
|
||||
INSERT INTO Crypto (Currency, Name, Address, Seed, Viewkey, Spendkey, Height, Password, Note)
|
||||
VALUES ($currency, $name, $address, $seed, $viewkey, $spendkey, $height, $password, $note)";
|
||||
com.Parameters.AddWithValue("$currency", currency);
|
||||
com.Parameters.AddWithValue("$name", name);
|
||||
com.Parameters.AddWithValue("$address", address);
|
||||
com.Parameters.AddWithValue("$seed", string.IsNullOrEmpty(seed) ? DBNull.Value : encryptedSeed);
|
||||
com.Parameters.AddWithValue("$viewkey", string.IsNullOrEmpty(viewkey) ? DBNull.Value : encryptedViewkey);
|
||||
com.Parameters.AddWithValue("$spendkey", string.IsNullOrEmpty(spendkey) ? DBNull.Value : encryptedSpendkey);
|
||||
com.Parameters.AddWithValue("$height", string.IsNullOrEmpty(height) ? DBNull.Value : height);
|
||||
com.Parameters.AddWithValue("$password", string.IsNullOrEmpty(password) ? DBNull.Value : encryptedPassword);
|
||||
com.Parameters.AddWithValue("$note", string.IsNullOrEmpty(note) ? DBNull.Value : note);
|
||||
com.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EditCrypto(int id, string currency, string name, string address, string seed, string viewkey, string spendkey, string height, string password, string note)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(currency) || string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
string err = mCulture == mJpLang
|
||||
? "通貨、ウォレット名及び、住所を御入力下さい。"
|
||||
: "Please fill in the currency, wallet name, and address.";
|
||||
throw new ArgumentException(err);
|
||||
}
|
||||
|
||||
string encryptedPassword = string.IsNullOrEmpty(password) ? string.Empty : EncryptInfo(password);
|
||||
string encryptedSeed = string.IsNullOrEmpty(seed) ? string.Empty : EncryptInfo(seed);
|
||||
string encryptedViewkey = string.IsNullOrEmpty(viewkey) ? string.Empty : EncryptInfo(viewkey);
|
||||
string encryptedSpendkey = string.IsNullOrEmpty(spendkey) ? string.Empty : EncryptInfo(spendkey);
|
||||
|
||||
using (SqliteConnection conn = new SqliteConnection(mConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
SqliteCommand com = conn.CreateCommand();
|
||||
com.CommandText = @"
|
||||
UPDATE Crypto
|
||||
SET Currency = $currency, Name = $name, Address = $address, Seed = $seed, Viewkey = $viewkey, Spendkey = $spendkey, Height = $height, Password = $password, Note = $note
|
||||
WHERE Id = $id";
|
||||
com.Parameters.AddWithValue("$id", id);
|
||||
com.Parameters.AddWithValue("$currency", currency);
|
||||
com.Parameters.AddWithValue("$name", name);
|
||||
com.Parameters.AddWithValue("$address", address);
|
||||
com.Parameters.AddWithValue("$seed", string.IsNullOrEmpty(seed) ? DBNull.Value : encryptedSeed);
|
||||
com.Parameters.AddWithValue("$viewkey", string.IsNullOrEmpty(viewkey) ? DBNull.Value : encryptedViewkey);
|
||||
com.Parameters.AddWithValue("$spendkey", string.IsNullOrEmpty(spendkey) ? DBNull.Value : encryptedSpendkey);
|
||||
com.Parameters.AddWithValue("$height", string.IsNullOrEmpty(height) ? DBNull.Value : height);
|
||||
com.Parameters.AddWithValue("$password", string.IsNullOrEmpty(password) ? DBNull.Value : encryptedPassword);
|
||||
com.Parameters.AddWithValue("$note", string.IsNullOrEmpty(note) ? DBNull.Value : note);
|
||||
return com.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool DeleteCrypto(int id)
|
||||
{
|
||||
using (SqliteConnection conn = new SqliteConnection(mConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
SqliteCommand com = conn.CreateCommand();
|
||||
com.CommandText = "DELETE FROM Crypto WHERE Id = $id";
|
||||
com.Parameters.AddWithValue("$id", id);
|
||||
return com.ExecuteNonQuery() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public List<(int Id, string Currency, string Name, string Address, string Seed, string Viewkey, string Spendkey, string Height, string Password, string Note)> GetAll(string keyword = "")
|
||||
{
|
||||
var cryptos = new List<(int, string, string, string, string, string, string, string, string, string)>();
|
||||
using (SqliteConnection conn = new SqliteConnection(mConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
SqliteCommand com = conn.CreateCommand();
|
||||
if (string.IsNullOrWhiteSpace(keyword))
|
||||
{
|
||||
com.CommandText = @"
|
||||
SELECT Id, Currency, Name, Address, Seed, Viewkey, Spendkey, Height, Password, Note FROM Crypto
|
||||
ORDER BY Currency DESC";
|
||||
}
|
||||
else
|
||||
{
|
||||
com.CommandText = @"
|
||||
SELECT Id, Currency, Name, Address, Seed, Viewkey, Spendkey, Height, Password, Note FROM Crypto
|
||||
WHERE Currency LIKE @keyword OR Name LIKE @keyword
|
||||
ORDER BY Currency DESC";
|
||||
com.Parameters.AddWithValue("@keyword", $"%{keyword}%");
|
||||
}
|
||||
|
||||
using (SqliteDataReader reader = com.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
string decryptedSeed = DecryptInfo(reader.GetString(4));
|
||||
string decryptedViewkey = reader.IsDBNull(5) ? string.Empty : DecryptInfo(reader.GetString(5));
|
||||
string decryptedSpendkey = reader.IsDBNull(6) ? string.Empty : DecryptInfo(reader.GetString(6));
|
||||
string decryptedPassword = reader.IsDBNull(8) ? string.Empty : DecryptInfo(reader.GetString(8));
|
||||
|
||||
cryptos.Add((
|
||||
reader.GetInt32(0),
|
||||
reader.GetString(1),
|
||||
reader.GetString(2),
|
||||
reader.GetString(3),
|
||||
decryptedSeed,
|
||||
reader.IsDBNull(5) ? string.Empty : decryptedViewkey,
|
||||
reader.IsDBNull(6) ? string.Empty : decryptedSpendkey,
|
||||
reader.IsDBNull(7) ? string.Empty : reader.GetString(7),
|
||||
reader.IsDBNull(8) ? string.Empty : decryptedPassword,
|
||||
reader.IsDBNull(9) ? string.Empty : reader.GetString(9)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cryptos;
|
||||
}
|
||||
|
||||
private string EncryptInfo(string answer)
|
||||
{
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Key = mEncryptionKey;
|
||||
aes.GenerateIV();
|
||||
byte[] iv = aes.IV;
|
||||
|
||||
using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, iv))
|
||||
{
|
||||
byte[] plainBytes = Encoding.UTF8.GetBytes(answer);
|
||||
byte[] encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
|
||||
byte[] result = new byte[iv.Length + encryptedBytes.Length];
|
||||
|
||||
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
|
||||
Buffer.BlockCopy(encryptedBytes, 0, result, iv.Length, encryptedBytes.Length);
|
||||
|
||||
return Convert.ToBase64String(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string DecryptInfo(string encryptedAnswer)
|
||||
{
|
||||
byte[] combined = Convert.FromBase64String(encryptedAnswer);
|
||||
byte[] iv = new byte[16];
|
||||
byte[] encryptedBytes = new byte[combined.Length - iv.Length];
|
||||
Buffer.BlockCopy(combined, 0, iv, 0, iv.Length);
|
||||
Buffer.BlockCopy(combined, iv.Length, encryptedBytes, 0, encryptedBytes.Length);
|
||||
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Key = mEncryptionKey;
|
||||
aes.IV = iv;
|
||||
|
||||
using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
|
||||
{
|
||||
byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
|
||||
return Encoding.UTF8.GetString(decryptedBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user