ECIES с Inferno: подписание с ECDSA
Я пытаюсь подписать текстовый файл, зашифрованный ECIES, используя Inferno. Части шифрования и обмена ключами работают хорошо, но у меня осталось несколько вопросов относительно ECDSA.
1. Я полагаю, что подпись ECDSA должна храниться в отправленном файле, чтобы получатель мог использовать ее для проверки целостности данных, верно?
2- Я много раз читал, что подпись должна выполняться на хэшированных данных, но данные, отправленные с помощью ECIES, зашифрованы, а не хэшированы, как получатель может получить их?
3- Где в следующем примере кода должна быть подпись? Текущая попытка не работает, поскольку, хотя подпись принимается при расшифровке, возвращается пустая строка (вместо расшифрованного текста).
internal static void EncryptText(string text, Keyring k, string file, bool forSender)
{
// never mind the Keyring class, it has no methods and only exposes
// a few properties to store the session keys conveniently
SharedEphemeralBundle ephemeralBundle;
if (forSender) ephemeralBundle = k.SenderDHM.GetSharedEphemeralDhmSecret();
else ephemeralBundle = k.ReceiverDHM.GetSharedEphemeralDhmSecret();
var ephemeralPublic = ephemeralBundle.EphemeralDhmPublicKeyBlob;
var ephemeralSymmetric = ephemeralBundle.SharedSecret;
var textBytes = Utils.SafeUTF8.GetBytes(text);
byte[] signature;
using (var ecdsa = new ECDsaCng(k.SenderDSA) { HashAlgorithm = CngAlgorithm.Sha384 })
signature = ecdsa.SignData(textBytes);
using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write))
{
fs.Write(signature, 0, signature.Length);
fs.Write(ephemeralPublic, 0, ephemeralPublic.Length);
EtM_EncryptTransform etm = new EtM_EncryptTransform(ephemeralSymmetric);
using (CryptoStream cs = new CryptoStream(fs, etm, CryptoStreamMode.Write))
cs.Write(textBytes, 0, textBytes.Length);
}
}
internal static string DecryptText(string file, Keyring k)
{
string decrypted = null;
var ephemeralPublic = new byte[104];
var signature = new byte[96];
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
fs.Read(signature, 0, 96);
fs.Read(ephemeralPublic, 0, 104);
var ephemeralSymmetric = k.SenderDHM.GetSharedDhmSecret(ephemeralPublic.ToPublicKeyFromBlob());
EtM_DecryptTransform etm = new EtM_DecryptTransform(ephemeralSymmetric);
using (CryptoStream cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
{
byte[] decrypt = new byte[fs.Length - 200];
cs.Read(decrypt, 0, decrypt.Length);
using (var ecdsa = new ECDsaCng(k.SenderDSA))
{
// signature is accepted but returns an empty string!?
if (ecdsa.VerifyData(decrypt, signature))
decrypted = Utils.SafeUTF8.GetString(decrypt);
}
}
}
return decrypted;
}
1 ответ
Хорошо, не берите в голову, после более тщательного изучения, похоже, в моем сценарии, я могу, к счастью, пойти с одним HMAC
private static bool Authenticate(string file, byte[] key, bool masterKey = false)
{
int position = 104;
if (masterKey) position = 48;
using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
using (var etm = new EtM_DecryptTransform(key, authenticateOnly: true))
{
fs.Position = position;
using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
cs.CopyTo(Stream.Null);
if (!etm.IsComplete) throw new Exception("Some blocks were not authenticated");
}
return true;
}
internal static void EncryptText(string text, Keyring k, string file, bool forSender)
{
SharedEphemeralBundle ephemeralBundle;
if (forSender) ephemeralBundle = k.SenderDHM.GetSharedEphemeralDhmSecret();
else ephemeralBundle = k.ReceiverDHM.GetSharedEphemeralDhmSecret();
var ephemeralPublic = ephemeralBundle.EphemeralDhmPublicKeyBlob;
var ephemeralSymmetric = ephemeralBundle.SharedSecret;
var textBytes = text.ToBytes();
using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
{
fs.Write(ephemeralPublic, 0, ephemeralPublic.Length);
using (var etm = new EtM_EncryptTransform(ephemeralSymmetric))
using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Write))
cs.Write(textBytes, 0, textBytes.Length);
}
}
internal static string DecryptText(string file, Keyring k)
{
string decrypted = null;
var ephemeralPublic = new byte[104];
using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
fs.Read(ephemeralPublic, 0, 104);
var ephemeralSymmetric = k.SenderDHM.GetSharedDhmSecret(ephemeralPublic.ToPublicKeyFromBlob());
if (Authenticate(file, ephemeralSymmetric))
{
using (var etm = new EtM_DecryptTransform(ephemeralSymmetric))
using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
{
var decrypt = new byte[fs.Length - 104];
cs.Read(decrypt, 0, decrypt.Length);
decrypted = decrypt.FromBytes();
}
}
}
return decrypted;
}