我想确保我的应用程序中的加密部分是正确的。我打算开源这个代码。您可以在以下位置获取两个相关文件:https ://gist.github.com/lameguy7quick/1e998aad673354d2661b 。
我犯过什么错误吗?我知道在撰写本文时我不了解 HMAC。
这个想法很简单。我加载收件人公钥。加密随机生成的 AES 密钥。使用所述 AES 对消息进行编码,然后将其填充到 tcp 连接中。我忽略了什么似乎可以正常工作吗?我有一种感觉,也许 aes 应该有一个随机生成的 IV,但密钥本身是随机生成的,所以也许我不需要?
我也使用 SHA1CryptoServiceProvider 我想我应该使用 SHA512CryptoServiceProvider。
我签名正确吗?它说它已签名,但我不确定它是否受到攻击
public byte[] SendMessage(byte[] recipient_pubkey, byte[] replyTo, string txt, byte[] prvkey, byte[] pubkey)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
var msgid = new byte[16];
rng.GetBytes(msgid);
using (var aes = new RijndaelManaged())
{
byte[] rsa_aes_key;
RSAParameters recipient_rsap;
Shared.LoadKey2(Shared.pubToPem(recipient_pubkey), null, out recipient_rsap);
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(recipient_rsap);
rsa_aes_key = rsa.Encrypt(aes.Key, false);
}
var aesmsg = EncodeMessage(recipient_pubkey, msgid, replyTo, txt, prvkey, pubkey, aes.Key, Shared.FixedIV_16bytes);
if (rsa_aes_key.Length + aesmsg.Length > 1024 * 15) throw new Exception();
sw.WriteByte((byte)ClientServerCmd.SendMessage);
sw.WriteShort((short)recipient_pubkey.Length);
sw.Write(recipient_pubkey, 0, recipient_pubkey.Length);
sw.WriteShort(rsa_aes_key.Length + aesmsg.Length);
sw.Write(rsa_aes_key, 0, rsa_aes_key.Length);
sw.Write(aesmsg, 0, aesmsg.Length);
sw.Flush();
var resp = sr.ReadByte();
if (resp != (byte)ClientServerCmd.KeyLenOk)
throw new Exception();
resp = sr.ReadByte();
if (resp == (byte)ClientServerCmd.NotRegistered)
throw new MyException("User you're writing to does not exist");
if (resp != (byte)ClientServerCmd.Success)
throw new Exception();
}
return msgid;
}
byte[] EncodeMessage(byte[] recipient_pubkey, byte[]msgid, byte[] replyTo, string txt, byte[] prvkey, byte[] pubkey, byte[] aes_key, byte[] aes_iv)
{
if (replyTo == null)
{
replyTo = new byte[16];
}
var txtbuf = Encoding.UTF8.GetBytes(txt);
var SignMessage = prvkey != null;
byte[] hash = null;
if (SignMessage)
{
using (var rsa = new RSACryptoServiceProvider())
{
RSAParameters rsap;
Shared.LoadKey2(Shared.prvToPem(prvkey), null, out rsap);
rsa.ImportParameters(rsap);
using (var ms = new MemoryStream()) //sign
{
ms.Write(msgid, 0, msgid.Length);
ms.Write(replyTo, 0, replyTo.Length);
ms.WriteShort((short)txtbuf.Length);
ms.Write(txtbuf, 0, txtbuf.Length);
ms.WriteShort((short)pubkey.Length);
ms.Write(pubkey, 0, pubkey.Length);
ms.WriteShort((short)recipient_pubkey.Length);
ms.Write(recipient_pubkey, 0, recipient_pubkey.Length);
ms.Position = 0;
hash = rsa.SignData(ms, new SHA1CryptoServiceProvider());
}
}
}
byte[] c1;
using (var ms1 = new MemoryStream())
using (var ms = new BZip2OutputStream(ms1))
{
ms.Write(txtbuf, 0, txtbuf.Length);
ms.Close();
c1 = ms1.ToArray();
}
var compressText = c1.Length < txtbuf.Length;
byte[] aesmsg;
byte[] aeskey;
using (var aes = new RijndaelManaged())
{
aeskey = aes.Key;
aes.IV = Shared.FixedIV_16bytes;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (var encryptor = aes.CreateEncryptor(aes_key, aes_iv))
using (CryptoStream sw2 = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
sw2.WriteByte((Byte)((compressText ? 1 : 0) | (SignMessage ? 2 : 0)));
sw2.Write(msgid, 0, msgid.Length);
sw2.Write(replyTo, 0, replyTo.Length);
if (compressText)
{
sw2.WriteShort((short)c1.Length);
sw2.Write(c1, 0, c1.Length);
}
else
{
sw2.WriteShort((short)txtbuf.Length);
sw2.Write(txtbuf, 0, txtbuf.Length);
}
if (SignMessage)
{
sw2.WriteShort((short)pubkey.Length);
sw2.Write(pubkey, 0, pubkey.Length);
sw2.WriteShort((short)hash.Length);
sw2.Write(hash, 0, hash.Length);
}
}
msEncrypt.Flush();
aesmsg = msEncrypt.ToArray();
}
}
return aesmsg;
}