Sviluppo TradingBot
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace DesktopBot.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Gestisce il salvataggio e il caricamento sicuro delle credenziali Alpaca.
|
||||
/// Cifra con AES-256 usando una chiave derivata da MachineName + UserName.
|
||||
/// </summary>
|
||||
public static class CredentialService
|
||||
{
|
||||
private static readonly string SettingsFolder =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "TradingBot");
|
||||
|
||||
private static readonly string CredentialsFile =
|
||||
Path.Combine(SettingsFolder, "credentials.dat");
|
||||
|
||||
private static byte[] DeriveKey()
|
||||
{
|
||||
var seed = Environment.MachineName + Environment.UserName + "TradingBotSalt_v1";
|
||||
using (var sha = SHA256.Create())
|
||||
return sha.ComputeHash(Encoding.UTF8.GetBytes(seed));
|
||||
}
|
||||
|
||||
public static void SaveCredentials(string apiKey, string apiSecret, bool isPaper)
|
||||
{
|
||||
if (!Directory.Exists(SettingsFolder))
|
||||
Directory.CreateDirectory(SettingsFolder);
|
||||
|
||||
var plainText = apiKey + "|" + apiSecret + "|" + isPaper;
|
||||
var plainBytes = Encoding.UTF8.GetBytes(plainText);
|
||||
var key = DeriveKey();
|
||||
|
||||
using (var aes = Aes.Create())
|
||||
{
|
||||
aes.Key = key;
|
||||
aes.GenerateIV();
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
ms.Write(aes.IV, 0, aes.IV.Length);
|
||||
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
|
||||
cs.Write(plainBytes, 0, plainBytes.Length);
|
||||
File.WriteAllBytes(CredentialsFile, ms.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AlpacaCredentials LoadCredentials()
|
||||
{
|
||||
if (!File.Exists(CredentialsFile))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
var data = File.ReadAllBytes(CredentialsFile);
|
||||
var key = DeriveKey();
|
||||
using (var aes = Aes.Create())
|
||||
{
|
||||
aes.Key = key;
|
||||
var iv = new byte[16];
|
||||
Array.Copy(data, 0, iv, 0, 16);
|
||||
aes.IV = iv;
|
||||
using (var ms = new MemoryStream(data, 16, data.Length - 16))
|
||||
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
|
||||
using (var reader = new StreamReader(cs, Encoding.UTF8))
|
||||
{
|
||||
var plain = reader.ReadToEnd();
|
||||
var parts = plain.Split('|');
|
||||
if (parts.Length != 3) return null;
|
||||
return new AlpacaCredentials
|
||||
{
|
||||
ApiKey = parts[0],
|
||||
ApiSecret = parts[1],
|
||||
IsPaper = bool.Parse(parts[2])
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
public static bool HasCredentials() => File.Exists(CredentialsFile);
|
||||
|
||||
public static void DeleteCredentials()
|
||||
{
|
||||
if (File.Exists(CredentialsFile))
|
||||
File.Delete(CredentialsFile);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Modello credenziali Alpaca</summary>
|
||||
public class AlpacaCredentials
|
||||
{
|
||||
public string ApiKey { get; set; }
|
||||
public string ApiSecret { get; set; }
|
||||
public bool IsPaper { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user