4 using System
.Net
.Sockets
;
6 using System
.Threading
;
8 using System
.Security
.Cryptography
;
10 using System
.Xml
.Serialization
;
12 namespace energimaaling
14 public class TCPKomm
{
15 /* Protokoll spesifikasjon:
17 * All kommunikasjon foregår ved å sende ei TCPMelding struct
18 * Typen vil avgjere korleis ein kan tolke medlemmet 'data'.
20 * 'data' vil være kryptert.
24 /* Sentral skal lytte på denne porten for tilkobling frå Hus */
25 public const int SENTRALHUSPORT
= 3000;
27 /* Sentral skal lytte på denne porten for tilkobling frå PDA */
28 public const int SENTRALPDAPORT
= 3001;
37 public enum Type { AuthQuery, AuthResponse, HusData, HusQuery, Error, Close, PdaData, PdaQuery, DEBUG }
;
41 public struct AuthQuery
{
42 public String kundenr
;
43 public String passord
;
47 public struct AuthResponse
{
52 public struct HusData
{
56 /* Hus data sendt til PDA */
58 public struct PdaData
{
63 public string adresse
;
68 public struct HusQuery
{
78 public enum ErrorType { UnexpectedData }
;
87 public struct PdaQuery
{
90 /* Sendast for å avslutte ei tilkobling skikkelig */
97 public struct TCPMelding
102 /* Struct tilsvarande type */
106 /* Kryptering og sending
108 * Bruk TCPKomm.SendMelding og TCPKomm.MottaMelding, desse krypterer objektet - serialiserer det og
109 * sender det på nettverksstrømmen som du gir.
111 * Du må lage ei TCPMelding og ein TCPMelding type; bruk Serialiser.Serialize () på det og lagre
112 * det i TCPMelding.data.
114 * Du kan få det ut på samme måte, ved å lage ei TCPMelding type og bruke
115 * Serialiser.Deserialize (TCPMelding.data, typeof (TCPMelding typen)).
119 // Lag autentiseringsmelding
120 TCPKomm.TCPMelding tm;
121 tm.type = TCPKomm.Type.AuthQuery;
126 * Serialiser AuthQuery og lagre i tm.data:
128 tm.data = Serialiser.Serialize (a);
130 * Send på NetworkStream ns:
132 TCPKomm.SendMelding (ns, tm);
137 TCPKomm.TCPMelding res = TCPKomm.MottaMelding (ns);
139 * For ei AuthQuery melding, gjer:
141 TCPKomm.AuthQuery aq = (TCPKomm.AuthQuery)Serialiser.Deserialize(tm.data, typeof(TCPKomm.AuthQuery));
143 * Du kan no bruke aq.kundenr og aq.passord.
146 * Hugs å laste nøkkel først i kvar prosess (biblioteket har ein instans for kvar) før du begynner.
150 * Nøkkel kan lagast med 'kg' på Sentral; legg key.bin og iv.bin i samme mappe som programma skal køyre
151 * (Sentral, Hus, Pda).
156 public static void SendMelding(NetworkStream ns
, TCPKomm
.TCPMelding tm
)
158 // krypterer (her blir TCPMelding serialisert)
159 CryptObject c
= Encrypt(tm
);
161 // Serialiserer CryptObjekt
162 byte[] ser
= Serialiser
.Serialize(c
);
164 byte[] size
= Serialiser
.IntToSize(ser
.Length
);
168 ns
.Write(size
, 0, 2);
171 Console.WriteLine("SendMelding sender: " + ser.Length.ToString());
172 Console.WriteLine("Byte: " + size.ToString());
176 ns
.Write(ser
, 0, ser
.Length
);
180 public static TCPMelding
MottaMelding(NetworkStream ns
)
183 // while (!ns.DataAvailable) Thread.Sleep(50);
186 byte[] size
= new byte[2];
190 int sizei
= Serialiser
.SizeToInt(size
);
193 byte[] ser
= new byte[sizei
];
194 int r
= ns
.Read(ser
, 0, sizei
);
197 Console.WriteLine("MottaMelding; fikk: " + r.ToString() + " av " + sizei.ToString());
198 Console.WriteLine("Byte: " + size.ToString());
201 // deserialiserer cryptobjekt
202 CryptObject c
= (CryptObject
)Serialiser
.Deserialize(ser
, typeof(CryptObject
));
205 TCPMelding tm
= Decrypt(c
);
210 public struct CryptObject
213 public byte[] encrypted
;
216 public static CryptObject
Encrypt (TCPMelding tm
)
218 if (!keyloaded
) throw new Exception ("Ingen key er lasta.");
219 CryptObject c
= new CryptObject ();
221 MemoryStream enc
= new MemoryStream ();
222 CryptoStream cStreamW
= new CryptoStream (enc
, ralg
.CreateEncryptor (), CryptoStreamMode
.Write
);
224 byte[] ser
= Serialiser
.Serialize(tm
);
226 c
.length
= (int) ser
.Length
;
228 cStreamW
.Write (ser
, 0, (int) ser
.Length
);
229 cStreamW
.FlushFinalBlock (); // also .Close ()'es
231 enc
.Position
= 0; // Rewind
232 c
.encrypted
= (byte[]) enc
.ToArray ();
236 public static TCPMelding
Decrypt (CryptObject c
)
238 if (!keyloaded
) throw new Exception ("Ingen key er lasta.");
239 MemoryStream benc
= new MemoryStream (c
.encrypted
);
241 CryptoStream cStreamR
= new CryptoStream (benc
, ralg
.CreateDecryptor (), CryptoStreamMode
.Read
);
243 byte [] buenc
= new byte[c
.length
];
244 cStreamR
.Read (buenc
, 0, c
.length
);
246 TCPMelding tm
= (TCPMelding
)Serialiser
.Deserialize(buenc
, typeof(TCPMelding
));
252 private static bool keyloaded
= false;
253 private static byte[] IV
;
254 private static byte[] KEY
;
255 public static Rijndael ralg
;
257 public static void loadkeys () {
258 log ("Laster Rijndaelll nøkkel..");
261 * PDA har tydeligvis problem med å laste fra fil so vi legg den inn manuelt foreløpig.
263 * Det betyr at genkeys har ingen funksjon no; og du treng ikkje key.bin og iv.bin
267 byte[] key
= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }
;
268 byte[] iv
= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
;
269 ralg
= Rijndael
.Create();
272 ralg
.Padding
= PaddingMode
.PKCS7
;
277 log ("FEIL! Kunne ikkje laste nøkkel.");
282 public static void genkeys () {
283 log ("Lager Rijndael nøkkel..");
284 ralg
= Rijndael
.Create ();
285 ralg
.Padding
= PaddingMode
.PKCS7
;
293 FileStream fiv
= File
.OpenWrite ("iv.bin");
294 FileStream fkey
= File
.OpenWrite ("key.bin");
296 BinaryWriter b
= new BinaryWriter (fiv
);
299 b
= new BinaryWriter (fkey
);
311 private static void log (String s
) {
312 Console
.WriteLine ("[TcpMelding] " + s
);