public static EncryptedMessage GenerateMessage(string Sender, object message, RSACryptoServiceProvider receiver_rsa, string token) { RijndaelManaged RMCrypto = new RijndaelManaged(); RMCrypto.GenerateIV(); RMCrypto.GenerateKey(); byte[] result_message = RMCrypto.getGlobalObject <IMysteryJsonConverter>().getJson(message).getBytes(); var ms = new MemoryStream(); CryptoStream CryptStream = new CryptoStream(ms, RMCrypto.CreateEncryptor(RMCrypto.Key, RMCrypto.IV), CryptoStreamMode.Write); CryptStream.Write(result_message, 0, result_message.Length); CryptStream.FlushFinalBlock(); byte[] message_id_bytes = Guid.NewGuid().ToString().getBytes(); RSACryptoServiceProvider my_rsa = CryptStream.getGlobalObject <IMyRsaProvider>().getMySra(); EncryptedMessage answer = new EncryptedMessage { Sender = Sender, IV = receiver_rsa.Encrypt(RMCrypto.IV, false), Key = receiver_rsa.Encrypt(RMCrypto.Key, false), Message = ms.ToArray(), Signature = my_rsa.SignData(result_message, new SHA1CryptoServiceProvider()), Token = receiver_rsa.Encrypt(token.getBytes(), false), MessageID = receiver_rsa.Encrypt(message_id_bytes, false), MessageIDSignaure = my_rsa.SignData(message_id_bytes, new SHA1CryptoServiceProvider()) }; return(answer); }
public static BodyType readMessage <BodyType>(EncryptedMessage message, RSACryptoServiceProvider sender_rsa) { //VUNERABILTY //IN CASE OF client restart the fake server can resend the message, the token is still valid //sol: on boot reset all client token //this solve also reply attack as the message would all change token, so I need only 1 session message id //if the message id buffer if full receiver shall send an authenticate request along with the correct answer (to avoid answer to be to different from normal message) if (message == null) { return(default(BodyType)); } byte[] signature = message.Signature; RSACryptoServiceProvider my_rsa = message.getGlobalObject <IMyRsaProvider>().getMySra(); //checking unique id byte[] message_id_bytes = my_rsa.Decrypt(message.MessageID, false); if (!sender_rsa.VerifyData(message_id_bytes, new SHA1CryptoServiceProvider(), message.MessageIDSignaure)) { return(default(BodyType)); } string message_id = message_id_bytes.getString(); if (message_ids.Contains(message_id)) { return(default(BodyType)); } //replay attack!!! if (message_ids.Count > replay_store_size) { message_ids = new HashSet <string>(); } message_ids.Add(message_id); byte[] Key = my_rsa.Decrypt(message.Key, false); byte[] IV = my_rsa.Decrypt(message.IV, false); //Create a new instance of the RijndaelManaged class //and decrypt the stream. RijndaelManaged RMCrypto = new RijndaelManaged(); //Create an instance of the CryptoStream class, pass it the NetworkStream, and decrypt //it with the Rijndael class using the key and IV. MemoryStream ms = new MemoryStream(message.Message); CryptoStream CryptStream = new CryptoStream(ms, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Read); MemoryStream output = new MemoryStream(); byte[] buffer = new byte[1024]; int read = CryptStream.Read(buffer, 0, buffer.Length); while (read > 0) { output.Write(buffer, 0, read); read = CryptStream.Read(buffer, 0, buffer.Length); } CryptStream.Flush(); CryptStream.Dispose(); ms.Dispose(); byte[] received_message = output.ToArray(); if (!sender_rsa.VerifyData(received_message, new SHA1CryptoServiceProvider(), signature)) { return(default(BodyType)); } //OK message certificated and decrypted! BodyType message_object = sender_rsa.getGlobalObject <IMysteryJsonConverter>().readJson <BodyType>(received_message.getString()); return(message_object); }