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); }