using Chaos.NaCl;
using System;
using System.IO;
using System.Security.Cryptography;
using Console = Colorful.Console;
namespace NetSparkleUpdater.AppCastGenerator
{
public class SignatureManager
{
public KeysProvider KeysProvider { get; }
public SignatureManager(KeysProvider keysProvider)
{
KeysProvider = keysProvider;
}
public bool Generate(bool force = false)
{
if (KeysProvider.KeysExist() && !force)
{
Console.WriteLine("Keys already exist, use --force to force regeneration");
return false;
}
Console.WriteLine("Generating key pair...");
var seed = RandomNumberGenerator.GetBytes(32);
var publicKey = Ed25519.PublicKeyFromSeed(seed);
var pubKeyBase64 = Convert.ToBase64String(publicKey);
var privKeyBase64 = Convert.ToBase64String(seed);
FileKeysProvider fileKeysProvider = KeysProvider.GetRequiredProvider<FileKeysProvider>();
fileKeysProvider.SetPrivateKey(privKeyBase64);
fileKeysProvider.SetPublicKey(pubKeyBase64);
Console.WriteLine("Storing public/private keys to " + fileKeysProvider.GetStorageDirectory());
return true;
}
public bool VerifySignature(string filePath, string signature)
{
return VerifySignature(new FileInfo(filePath), signature);
}
public bool VerifySignature(FileInfo file, string signature)
{
if (!KeysProvider.KeysExist())
{
Console.WriteLine("Keys do not exist");
return false;
}
if (signature == null)
{
Console.WriteLine("Signature at path {0} is null", file.FullName);
return false;
}
byte[] bHash = Convert.FromBase64String(signature);
const int chunkSize = 1024 * 1024 * 25;
using FileStream inputStream = File.OpenRead(file.FullName);
var validator = new Ed25519Signer();
validator.InitWithNonExpandedPrivateKey(KeysProvider.GetPublicKey(), KeysProvider.GetPrivateKey());
byte[] buffer = new byte[chunkSize];
int bytesRead;
while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
validator.AddToBuffer(buffer, 0, bytesRead);
}
return validator.VerifySignature(Convert.FromBase64String(signature));
}
public string? GetSignatureForFile(string filePath)
{
return GetSignatureForFile(new FileInfo(filePath));
}
public string? GetSignatureForFile(FileInfo file)
{
if (!KeysProvider.KeysExist())
{
Console.WriteLine("Keys do not exist");
return null;
}
if (!file.Exists)
{
Console.Error.WriteLine("Target binary " + file.FullName + " does not exist");
return null;
}
using FileStream inputStream = File.OpenRead(file.FullName);
var validator = new Ed25519Signer();
validator.InitWithNonExpandedPrivateKey(KeysProvider.GetPublicKey(), KeysProvider.GetPrivateKey());
const int chunkSize = 1024 * 1024 * 25;
byte[] buffer = new byte[chunkSize];
int bytesRead;
while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
validator.AddToBuffer(buffer, 0, bytesRead);
}
return Convert.ToBase64String(validator.GenerateSignature());
}
public string GetSignatureForData(byte[] data)
{
var signer = new Ed25519Signer();
signer.InitWithNonExpandedPrivateKey(KeysProvider.GetPublicKey(), KeysProvider.GetPrivateKey());
signer.AddToBuffer(data, 0, data.Length);
return Convert.ToBase64String(signer.GenerateSignature());
}
}
}