我喜歡確保在應用程序中正確使用了加密部分。我打算開源這個代碼。您可以在https://gist.github.com/lameguy7quick/1e998aad673354d2661b處獲得兩個相關文件。我是否正確使用RSA加密和簽名?
我犯過什麼錯誤嗎?我知道我在撰寫本文時不瞭解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;
}
應該已經遷移到代碼審查。 –
你有沒有理由不能只使用TLS? – ntoskrnl