Encryption/Decryption problem
-
Hi! I'm working on a P2P app, with security built in, it's going to be released as open source as soon as I have a working prototype... I've gotten as far as exchanging messages, encrypting username password with RSA and exchanging a common symmetric key. But when I try to decrypt messages encrypted with the sym-key I get an error: Binary stream does not contain a valid BinaryHeader, 95 possible causes... I have the following code:
public byte[] SecureSerialize(byte[] key, byte[] iv) { if (encrypted == Encryption.NotEncrypted) throw new Exception("Message type should be serialized with Serialize()"); byte[] streamBuffer = new byte[BufferSize]; streamBuffer[0] = (byte)msgType; streamBuffer[1] = (byte)encrypted; MemoryStream ms = new MemoryStream(streamBuffer, sizeOffset, BufferSize - sizeOffset); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateEncryptor(key, iv), CryptoStreamMode.Write); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(cs, this); cs.Flush(); ms.Flush(); SHA1Managed hashAlg = new SHA1Managed(); byte[] hash = hashAlg.ComputeHash(streamBuffer, 0, (int)ms.Position + sizeOffset); bf.Serialize(ms, hash); byte[] returnBuffer = new byte[(int)ms.Position + sizeOffset]; Array.Copy(streamBuffer, 0, returnBuffer, 0, (int)ms.Position + sizeOffset); return returnBuffer; } public static UdpMessage SecureDeserialize(byte[] msg, byte[] key, byte[] iv) { if ((Encryption)msg[1] == Encryption.NotEncrypted) throw new Exception("Message type should be deserialized with Deserialize()"); byte[] decryptedBuffer = msg; MemoryStream ms = new MemoryStream(decryptedBuffer, sizeOffset, decryptedBuffer.Length - sizeOffset); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateDecryptor(key, iv), CryptoStreamMode.Read); BinaryFormatter bf = new BinaryFormatter(); UdpMessage message = (UdpMessage)bf.Deserialize(cs); cs.Flush(); ms.Flush(); message.msgType = (MessageType)msg[0]; message.encrypted = (Encryption)msg[1]; SHA1Managed hashAlg = new SHA1Managed(); byte[] calculatedHash = hashAlg.ComputeHash(decryptedBuffer, 0, (int)ms.Position + sizeOffset); byte[] msgHash = (byte[])bf.Deserialize(ms); for (int i = 0 ; i < calculatedHash.Length ; i++) if (calculatedHash[i] != msgHash[i]) throw new CryptographicException("Hash missmatch"); return message; }
The same code without the encryption stuff work -
Hi! I'm working on a P2P app, with security built in, it's going to be released as open source as soon as I have a working prototype... I've gotten as far as exchanging messages, encrypting username password with RSA and exchanging a common symmetric key. But when I try to decrypt messages encrypted with the sym-key I get an error: Binary stream does not contain a valid BinaryHeader, 95 possible causes... I have the following code:
public byte[] SecureSerialize(byte[] key, byte[] iv) { if (encrypted == Encryption.NotEncrypted) throw new Exception("Message type should be serialized with Serialize()"); byte[] streamBuffer = new byte[BufferSize]; streamBuffer[0] = (byte)msgType; streamBuffer[1] = (byte)encrypted; MemoryStream ms = new MemoryStream(streamBuffer, sizeOffset, BufferSize - sizeOffset); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateEncryptor(key, iv), CryptoStreamMode.Write); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(cs, this); cs.Flush(); ms.Flush(); SHA1Managed hashAlg = new SHA1Managed(); byte[] hash = hashAlg.ComputeHash(streamBuffer, 0, (int)ms.Position + sizeOffset); bf.Serialize(ms, hash); byte[] returnBuffer = new byte[(int)ms.Position + sizeOffset]; Array.Copy(streamBuffer, 0, returnBuffer, 0, (int)ms.Position + sizeOffset); return returnBuffer; } public static UdpMessage SecureDeserialize(byte[] msg, byte[] key, byte[] iv) { if ((Encryption)msg[1] == Encryption.NotEncrypted) throw new Exception("Message type should be deserialized with Deserialize()"); byte[] decryptedBuffer = msg; MemoryStream ms = new MemoryStream(decryptedBuffer, sizeOffset, decryptedBuffer.Length - sizeOffset); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateDecryptor(key, iv), CryptoStreamMode.Read); BinaryFormatter bf = new BinaryFormatter(); UdpMessage message = (UdpMessage)bf.Deserialize(cs); cs.Flush(); ms.Flush(); message.msgType = (MessageType)msg[0]; message.encrypted = (Encryption)msg[1]; SHA1Managed hashAlg = new SHA1Managed(); byte[] calculatedHash = hashAlg.ComputeHash(decryptedBuffer, 0, (int)ms.Position + sizeOffset); byte[] msgHash = (byte[])bf.Deserialize(ms); for (int i = 0 ; i < calculatedHash.Length ; i++) if (calculatedHash[i] != msgHash[i]) throw new CryptographicException("Hash missmatch"); return message; }
The same code without the encryption stuff workJust a quick reply to your final question (I'm afraid I don't have time at the moment to figure out your code): SSL was designed to protect against man-in-the-middle attacks. Check out the specification of SSL to understand how it works (it involves the exchange of certificates for example). Cheers, Julian Program Manager, C# This posting is provided "AS IS" with no warranties, and confers no rights.
-
Just a quick reply to your final question (I'm afraid I don't have time at the moment to figure out your code): SSL was designed to protect against man-in-the-middle attacks. Check out the specification of SSL to understand how it works (it involves the exchange of certificates for example). Cheers, Julian Program Manager, C# This posting is provided "AS IS" with no warranties, and confers no rights.
What I've gathered so far is that it all comes down to having some trusted site to sign a certificate for you. I guess using that service will cost money and will not be that interesting for this type of friend2friend communication application. I think I'll settle for a hash of the public key encoded in base64. This could be calculated on the client side too and then compared by using the telephone or something if MITM-attack is suspected. I guess MITM-attack of voice communication still is very hard to do :) I guess problems like this will have to be solved by people that really knows security when the app is available to the public. Thanx for the help. I now realize how much more complex this is than exchanging public keys.
-
Hi! I'm working on a P2P app, with security built in, it's going to be released as open source as soon as I have a working prototype... I've gotten as far as exchanging messages, encrypting username password with RSA and exchanging a common symmetric key. But when I try to decrypt messages encrypted with the sym-key I get an error: Binary stream does not contain a valid BinaryHeader, 95 possible causes... I have the following code:
public byte[] SecureSerialize(byte[] key, byte[] iv) { if (encrypted == Encryption.NotEncrypted) throw new Exception("Message type should be serialized with Serialize()"); byte[] streamBuffer = new byte[BufferSize]; streamBuffer[0] = (byte)msgType; streamBuffer[1] = (byte)encrypted; MemoryStream ms = new MemoryStream(streamBuffer, sizeOffset, BufferSize - sizeOffset); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateEncryptor(key, iv), CryptoStreamMode.Write); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(cs, this); cs.Flush(); ms.Flush(); SHA1Managed hashAlg = new SHA1Managed(); byte[] hash = hashAlg.ComputeHash(streamBuffer, 0, (int)ms.Position + sizeOffset); bf.Serialize(ms, hash); byte[] returnBuffer = new byte[(int)ms.Position + sizeOffset]; Array.Copy(streamBuffer, 0, returnBuffer, 0, (int)ms.Position + sizeOffset); return returnBuffer; } public static UdpMessage SecureDeserialize(byte[] msg, byte[] key, byte[] iv) { if ((Encryption)msg[1] == Encryption.NotEncrypted) throw new Exception("Message type should be deserialized with Deserialize()"); byte[] decryptedBuffer = msg; MemoryStream ms = new MemoryStream(decryptedBuffer, sizeOffset, decryptedBuffer.Length - sizeOffset); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateDecryptor(key, iv), CryptoStreamMode.Read); BinaryFormatter bf = new BinaryFormatter(); UdpMessage message = (UdpMessage)bf.Deserialize(cs); cs.Flush(); ms.Flush(); message.msgType = (MessageType)msg[0]; message.encrypted = (Encryption)msg[1]; SHA1Managed hashAlg = new SHA1Managed(); byte[] calculatedHash = hashAlg.ComputeHash(decryptedBuffer, 0, (int)ms.Position + sizeOffset); byte[] msgHash = (byte[])bf.Deserialize(ms); for (int i = 0 ; i < calculatedHash.Length ; i++) if (calculatedHash[i] != msgHash[i]) throw new CryptographicException("Hash missmatch"); return message; }
The same code without the encryption stuff workI've written code a little easier to understand, and hope it will give some response... Key and iv are double checked and correct data is received as it was sent.
public byte[] SecureSerialize(byte[] key, byte[] iv) { byte[] streamBuffer = new byte[BufferSize]; MemoryStream ms = new MemoryStream(streamBuffer); ms.WriteByte((byte)encrypted); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateEncryptor(key, iv), CryptoStreamMode.Write); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(cs, this); SHA1Managed hashAlg = new SHA1Managed(); byte[] hash = hashAlg.ComputeHash(streamBuffer, 0, (int)ms.Position); bf.Serialize(ms, hash); byte[] returnBuffer = new byte[(int)ms.Position]; Array.Copy(streamBuffer, 0, returnBuffer, 0, (int)ms.Position); return returnBuffer; } public static UdpMessage SecureDeserialize(byte[] msg, byte[] key, byte[] iv) { MemoryStream ms = new MemoryStream(msg); byte enc = (byte)ms.ReadByte(); RijndaelManaged rij = new RijndaelManaged(); CryptoStream cs = new CryptoStream(ms, rij.CreateDecryptor(key, iv), CryptoStreamMode.Read); BinaryFormatter bf = new BinaryFormatter(); UdpMessage message = (UdpMessage)bf.Deserialize(cs); // <<<----This fails message.encrypted = (Encryption)enc; SHA1Managed hashAlg = new SHA1Managed(); byte[] calculatedHash = hashAlg.ComputeHash(msg, 0, (int)ms.Position); byte[] msgHash = (byte[])bf.Deserialize(ms); for (int i = 0 ; i < calculatedHash.Length ; i++) if (calculatedHash[i] != msgHash[i]) throw new CryptographicException("Hash missmatch"); return message; }
Regards 3ddA