private static String CryptRequestParser(String data, NskdSession session) { String response = null; // дешифрование запроса Byte[] encryptedBytes = Convert.FromBase64String(data); Byte[] plainBytes = session.Decrypt(encryptedBytes); String package = Encoding.UTF8.GetString(plainBytes); // разбор запроса try { // пока не разбор запроса, а только выполнение входа и регистрация пользователя RequestPackage p = new RequestPackage(package); String userToken = (string)p.GetParameterValueByName("userId"); session.Update(userToken); } catch (Exception ex) { Console.WriteLine(ex.Message); } if (response != null) { // шифрование ответа plainBytes = Encoding.UTF8.GetBytes(response); encryptedBytes = session.Encrypt(plainBytes); data = Convert.ToBase64String(encryptedBytes); } return(package); }
private static HttpWebResponse ProcessIncomingRequestToProtectedSite(HttpListenerContext context, SiteInf siteInf) { HttpListenerRequest incomingRequest = context.Request; HttpWebResponse incomingResponse = null; // GET - create session, or POST - download session if (incomingRequest.HttpMethod == "GET") // ! разобраться с HEAD { // Запросы типа GET могут быть к защищённому сайту (за ccs или js) // или могут быть к странице Login. Те которые к Login перехватываем // и отправляем ответ прямо из файлов которые есть на прокси. Кроме того, если // запрос без адреса или к странице Login, то создаём и регистрируем новую сессию. String userAddress = null; NskdSession session = null; switch (incomingRequest.Url.AbsolutePath) { case "/": case "/login/login.html": userAddress = context.Request.RemoteEndPoint.Address.ToString(); session = new NskdSession(userAddress); RsaParameters ps = session.Rsa.ExportParameters(); String sessionId = session.SessionId; String rsaModule = Convert.ToBase64String(ps.Module); String rsaExponent = Convert.ToBase64String(ps.Exponent); server.SendLoginPage(context, sessionId, rsaModule, rsaExponent); break; case "/login/login.css": server.SendFile(context, @"Login\Login.css"); break; case "/login/login.js": server.SendFile(context, @"Login\Login.js"); break; case "/scripts/cryptico/cryptico.min.js": server.SendFile(context, @"Scripts\Cryptico\cryptico.min.js"); break; case "/scripts/nskd/nskd.js": server.SendFile(context, @"Scripts\Nskd\Nskd.js"); break; default: // если запрос типа GET не перехвачен, то перенаправляем его клиенту incomingResponse = siteInf.Client.GetResponse(context); break; } } else if (incomingRequest.HttpMethod == "POST") { incomingResponse = ProcessPost(incomingRequest, context, siteInf); } else // все остальные кроме GET и POST. ! разобраться с HEAD { incomingResponse = siteInf.Client.GetResponse(context); } return(incomingResponse); }
public static NskdSession GetById(String sessionId) { NskdSession session = new NskdSession(); session.SessionId = sessionId; // загружаем данные сессии DataSet sessionDataSet = Data.Db.Session.Get(sessionId); //Console.WriteLine(sessionDataSet.Tables.Count.ToString()); session.Csp = new CryptServiceProvider(); if (sessionDataSet.Tables.Count > 0) { DataTable dt0 = sessionDataSet.Tables[0]; if (dt0.Rows.Count > 0) { DataRow dr = dt0.Rows[0]; session.UserId = (dr["user_id"] != DBNull.Value) ? (Int32)dr["user_id"] : 0; if (dr["crypt_key"] != DBNull.Value) { session.CryptKey = Convert.FromBase64String((String)dr["crypt_key"]); } else // Это первый запрос с зашифрованным ключом. Надо восстановить параметры RSA. { if (sessionDataSet.Tables.Count > 1) { DataTable dt1 = sessionDataSet.Tables[1]; if (dt1.Rows.Count > 0) { dr = dt1.Rows[0]; RsaParameters ps = new RsaParameters(); ps.P = Convert.FromBase64String(dr["p"] as String); ps.Q = Convert.FromBase64String(dr["q"] as String); ps.Module = Convert.FromBase64String(dr["module"] as String); ps.Exponent = Convert.FromBase64String(dr["exponent"] as String); ps.D = Convert.FromBase64String(dr["d"] as String); session.Rsa = new Rsa(); session.Rsa.ImportParameters(ps); } } } } } return(session); }
private static Int32 LoadCryptKeyFromRequestDataToSession(String data, Int32 readerPointer, NskdSession session) { int b64EncryptedKeyMessageLength = data.IndexOf("\r\n", readerPointer) - readerPointer; if (b64EncryptedKeyMessageLength > 0) { // есть только первый раз String b64EncryptedKeyMessage = data.Substring(readerPointer, b64EncryptedKeyMessageLength); Byte[] encryptedKeyMessage = Convert.FromBase64String(b64EncryptedKeyMessage); session.CryptKey = session.Rsa.DecryptMessage(encryptedKeyMessage, true); } return(b64EncryptedKeyMessageLength); }
private static HttpWebResponse ProcessPost(HttpListenerRequest incomingRequest, HttpListenerContext context, SiteInf siteInf) { HttpWebResponse incomingResponse = null; String response = null; // Если запросы типа POST, то все их перенаправляем клиенту. // Здесь надо поймать первый запрос с общим ключём для шифрования. switch (incomingRequest.Url.AbsolutePath) { case "/": // это запрос от страницы Login - надо потом добавить проверку // сессия уже есть, в потоке зашифрованный запрос NskdSession session = null; String data = null; MemoryStream ms1 = new MemoryStream(); MemoryStream ms2 = new MemoryStream(); incomingRequest.InputStream.CopyTo(ms1); ms1.Position = 0; ms1.CopyTo(ms2); ms1.Position = 0; ms2.Position = 0; using (var sr = new StreamReader(ms1, Encoding.UTF8)) { data = sr.ReadToEnd(); } if (!String.IsNullOrWhiteSpace(data)) // поток не пустой - расшифровка { //Console.WriteLine("ProcessPost(): поток не пустой - расшифровка"); // возможно два варианта: // 1. Это первый запрос после GET. // В нем есть <sessionId + \r\n + зашифрованный_rsa_common_key + \r\n + data> // 2. Это не первый запрос после GET. // В нем <sessionId + \r\n + data> // Отличить можно по наличю общего ключа. Int32 sessionIdLength = data.IndexOf("\r\n"); if (sessionIdLength > 0) { Int32 readerPointer = 0; String sessionId = data.Substring(readerPointer, sessionIdLength); readerPointer += sessionIdLength; readerPointer += 2; // 0d 0a session = NskdSession.GetById(sessionId); //Console.WriteLine("ProcessPost(): session.SessionId " + session.SessionId); // проверяем общий ключ if (session.CryptKey == null) { // Общего ключа ещё нет. Значит он должен быть в запросе, зашифрованный RSA. readerPointer += LoadCryptKeyFromRequestDataToSession(data, readerPointer, session); readerPointer += 2; // \r\n } if (session.CryptKey != null) // или загрузился из базы или только что создан из запроса { data = data.Substring(readerPointer); response = CryptRequestParser(data, session); if (response.Length > 0) { ms2 = new MemoryStream(); //Byte[] buff = Encoding.UTF8.GetBytes(response); //ms2.Write(buff, 0, buff.Length); } } } } incomingResponse = siteInf.Client.GetResponse(context, session.SessionId, ms2); break; default: incomingResponse = siteInf.Client.GetResponse(context); break; } return(incomingResponse); }