Question secure serialization over tcp/ip network

joedeene

Member
Joined
Aug 1, 2008
Messages
5
Programming Experience
Beginner
hey,

just wondering, i was working with serialization and i serialized data to my local system, then clicked a button and it deserialized the information fine, on my local machine, but when i send it over the tcpclient/listener stream, on my server side where it reads it, it wont deserialize it. and is there a more secure way to either serialize something, or just a secure way to send information through the net? like through my connection.
 
Can you post the pieces of your code that serialize, transmit, recieve, and deserialize the information on the client and server respectivly?

Just thinking back to my first serialization attempts I suspect either your serialization structures (classes, etc.) that you are serializing from and two are out of sync in terms of their versioning and the serialized information doesn't fit into the deserialized container.
 
my code...

ok, well for one, i am using c sharp on one side and visual basic.net 2008 on the other, both .net 3.5 but it really shouldnt matter because they both create the same types of applications, but im not positive if it really matters or not. and i am using microsoft virtual pc 2007, running a windows xp on that, and my main(host) is a windows vista sp1. umm but im running c sharp on my virtual pc, and visual basic 2008 on my vista. but the c-sharp code is this, its in a console application...

vb.net translation, tcplistener)

VB.NET:
'that code part was inside of the main class
'this code is outside of everything
<Serializable()>  _
Public Class employee
    
    Public name As String = Nothing
    
    Public years As Integer = 0
End Class

    
    Public Shared Sub Main(ByVal args() As String)
        Dim mydeserializer As BinaryFormatter = New BinaryFormatter
        Dim listenip As IPAddress = IPAddress.Parse("xxx.xxx.x.xxx")
        Dim listenport As Integer = Integer.Parse("xxxxx")
        Dim locallistener As TcpListener = New TcpListener(listenip, listenport)
        locallistener.Start
        Dim localtcpclient As TcpClient = locallistener.AcceptTcpClient
        Dim mylocalnetstream As NetworkStream = localtcpclient.GetStream
        Dim mynetsendedemployee As employee
        mynetsendedemployee = CType(mydeserializer.Deserialize(mylocalnetstream),employee)
        'line that throws exception listed below
        Console.WriteLine("Employee's Name: {0}", mynetsendedemployee.name)
        Console.WriteLine("Employee's Years: {0}", mynetsendedemployee.years)
        mylocalnetstream.Close
        localtcpclient.Close
        locallistener.Stop
    End Sub


ok thats the code for the tcplistener, im trying to get it to deserialize the class.


but heres the code for the visual basic code for the tcpclient sending the data to the server(tcplistener)


VB.NET:
Module Module1

    Sub Main()
        Dim myemptest As New employee()
        Dim myformatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
        Dim mytcpclient As New Net.Sockets.TcpClient("xxx.xxx.x.xxx", xxxxx)
        Dim mynetstream As Net.Sockets.NetworkStream = mytcpclient.GetStream


        myemptest.name = "Joe"
        myemptest.years = "14"

        myformatter.Serialize(mynetstream, myemptest)

        Threading.Thread.Sleep(10000) ' i do this so the stream doesnt close before the data is read _
or unserialized because i dont know if it would throw an exception if the stream is closed before its read.

        mynetstream.Close()
        mytcpclient.Close()

    End Sub

End Module




<Serializable()> Public Class employee

    Public name As String = vbNull
    Public years As Integer = 0
End Class


and the exception is, (unhandledserializationexception)
' Unable to find assembly 'server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. '

and i know just sending data serialized like that isnt secure enough, but i just want to get the feel of it first, then start securing it, or something. ok plz write back, thanks for your help.
 
Types are Assembly qualified, so both your employee classes are different types that can't be serialized between. You have to create a class library containing the employee class, and reference this by both projects, this will enable serialization between your different applications.
 
uhmmm....how do i...

are you saying i should make some kinda .dll, and reference it to both the applications ?, uhm, well i'll give it a try, could you possibly post some kinda example, and i just used employee as an example. plus, do u have an idea or link for any secure serializations. ok i'll try and work with this, thanks.
 
Yea, what John is saying is what I figured your problem would be.

Basically, both the client had the server have to have an IDENTICAL understanding of the data that is being serialized/deserialized.

This cannot be achived simply by declaring the class identically in both applications, as that classes type is partially identified by the application containing it.

You need to create a second project as a "Class Library". Declare your class in that library just as you have now in your two applications, and build it. This will create for you a .DLL file, which you then reference in both applications.

Everything else will function simliarly, you will be able to access the class through the DLL something like "Dim myThing as ClassLibraryName.ClassName" in both the client and the server and they will be able to have the exact same understanding on the serialized data.

Post if you run into problems!
 
uhmmm, serializing files?...

you said post if i run into problems, well no i didnt i love it, and think its very neat, but i know its not secure, and i will work with that later, but i want to know if its possible to basically serialize a whole file. im pretty sure it can be done, but i dont know how to do. like if i made some kinda byte reader and read the file from a stream converted it to a byte array and then serialized it, could that work ? and i dont think theres a byte reader, unless binaryreader are bytes. well help plz thanks
 
You can use a SslStream to add security by authentication, integrity and confidentiality. Basically you just wrap it around the NetworkStream, call AuthenticateAsServer/AuthenticateAsClient and transmit data through this stream as normal.

For the server you need to use a X509Certificate, this can be a bit tricky but this article has a good step-through to create one: How-to use MakeCert for trusted root certification authority and SSL certificate issuance. Here is a sample to get the certificate instance which is used as parameter for AuthenticateAsServer.
VB.NET:
Private Function getServerCert() As X509Certificate
    Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
    store.Open(OpenFlags.ReadOnly)   
    Return store.Certificates.Find(X509FindType.FindBySubjectName, "jhoward-5160", True)(0)
End Function
The AuthenticateAsClient call use "jhoward-5160" as targetHost parameter.
 
Back
Top