public static ClientRequest EncodeRequestData(object DataObject) { ClientRequest res = new ClientRequest(); try { var xs = new XmlSerializer(DataObject.GetType()); var xml = new Utf8StringWriter(); xs.Serialize(xml, DataObject); byte[] xmlbytes = Encoding.UTF8.GetBytes(xml.ToString()); //инициализируем криптодвижок для подписи string RSAProvName = AsymmetricAlgorithmNames.RsaPkcs1; string AESProvName = SymmetricAlgorithmNames.AesCbcPkcs7; SymmetricKeyAlgorithmProvider AESProv = SymmetricKeyAlgorithmProvider.OpenAlgorithm(AESProvName); IBuffer keyMaterial = CryptographicBuffer.GenerateRandom(32); CryptographicKey AESkey = AESProv.CreateSymmetricKey(keyMaterial); IBuffer iv = CryptographicBuffer.GenerateRandom(16); byte[] encrypteddatabytes = CryptographicEngine.Encrypt(AESkey, xmlbytes.AsBuffer(), iv).ToArray(); AsymmetricKeyAlgorithmProvider RSAEncryptProv = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(RSAProvName); CryptographicKey ServerPublicKey = RSAEncryptProv.ImportPublicKey(Convert.FromBase64String(GlobalVars.ServerPublicKey).AsBuffer(), CryptographicPublicKeyBlobType.Capi1PublicKey); byte[] encryptedkeybytes = CryptographicEngine.Encrypt(ServerPublicKey, keyMaterial, null).ToArray(); byte[] encryptedivbytes = CryptographicEngine.Encrypt(ServerPublicKey, iv, null).ToArray(); string strAlgName = HashAlgorithmNames.Sha512; HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName); CryptographicHash objHash = objAlgProv.CreateHash(); objHash.Append(xmlbytes.AsBuffer()); IBuffer xmlbyteshash = objHash.GetValueAndReset(); byte[] tmpsignature = CryptographicEngine.SignHashedData(GlobalVars.ClientKeyPair, xmlbyteshash).ToArray(); res.Request = Convert.ToBase64String(encrypteddatabytes); res.Signature = Convert.ToBase64String(tmpsignature); res.AData = Convert.ToBase64String(encryptedkeybytes); res.BData = Convert.ToBase64String(encryptedivbytes); } catch /*(Exception ex)*/ { res = null; } return(res); }
/// <summary> /// Указываем файл лицензии /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void DoRegister() { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = Searching; }); var removableDevices = KnownFolders.RemovableDevices; var externalDrives = await removableDevices.GetFoldersAsync(); foreach (var drive in externalDrives) { try { StorageFile licfile = null; licfile = await drive.GetFileAsync("wvlicense.lic"); if (licfile != null) { //файл выбран, выводим картинку что все в процессе await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = loading; }); //инициализируем криптодвижок для проверки файла лицензии string RSAProvName = AsymmetricAlgorithmNames.RsaPkcs1; StreamReader LicenseFile = File.OpenText(licfile.Path); string LicenseXML = LicenseFile.ReadToEnd(); LicenseFile.Dispose(); AccLicense tmplic = Deserialize <AccLicense>(LicenseXML); if (tmplic.IsLicenseValid()) { //лицензия корректна //выводим пользователю данные лицензии await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { userid.Foreground = new SolidColorBrush(Colors.Green); userid.Text = tmplic.UserID; regdatetime.Foreground = new SolidColorBrush(Colors.Green); regdatetime.Text = tmplic.RegistrationDateTimeStr; devcountlimit.Foreground = new SolidColorBrush(Colors.Green); devcountlimit.Text = tmplic.DeviceCountLimit.ToString(); statustext.Text = "запрос регистрации..."; }); //данные для регистрации переводим в массив байт byte[] tmphwidbytes = Encoding.UTF8.GetBytes(GlobalVars.HardWareID); byte[] tmpuidbytes = Encoding.UTF8.GetBytes(tmplic.UserID); byte[] tmpsplitbytes = new byte[3] { 254, 11, 254 }; byte[] tmpauthstrbytes = new byte[tmphwidbytes.Length + tmpuidbytes.Length + 3]; Array.Copy(tmphwidbytes, 0, tmpauthstrbytes, 0, tmphwidbytes.Length); Array.Copy(tmpsplitbytes, 0, tmpauthstrbytes, tmphwidbytes.Length, tmpsplitbytes.Length); Array.Copy(tmpuidbytes, 0, tmpauthstrbytes, tmphwidbytes.Length + tmpsplitbytes.Length, tmpuidbytes.Length); //инициализируем криптодвижок для подписи и шифрования запроса AsymmetricKeyAlgorithmProvider RSAEncryptProv = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(RSAProvName); CryptographicKey ServerPublicKey = RSAEncryptProv.ImportPublicKey(Convert.FromBase64String(GlobalVars.ServerPublicKey).AsBuffer(), CryptographicPublicKeyBlobType.Capi1PublicKey); string strAlgName = HashAlgorithmNames.Sha512; HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName); CryptographicHash objHash = objAlgProv.CreateHash(); objHash.Append(tmpauthstrbytes.AsBuffer()); IBuffer authstringhash = objHash.GetValueAndReset(); byte[] haashbytes = authstringhash.ToArray(); //подписываем byte[] tmpsignature = CryptographicEngine.SignHashedData(GlobalVars.ClientKeyPair, authstringhash).ToArray(); //шифруем byte[] tmpauthstring = CryptographicEngine.Encrypt(ServerPublicKey, tmpauthstrbytes.AsBuffer(), null).ToArray(); //создаем объект запроса WaterDeviceRegistrationRequest tmpreq = new WaterDeviceRegistrationRequest(); tmpreq.PublicKey = GlobalVars.ClientKeyPair.ExportPublicKey(CryptographicPublicKeyBlobType.Capi1PublicKey).ToArray(); tmpreq.AuthorizationString = tmpauthstring; tmpreq.AuthSignature = tmpsignature; //сериализуем в XML var xs = new XmlSerializer(tmpreq.GetType()); var xml = new Utf8StringWriter(); xs.Serialize(xml, tmpreq); //переводим в строку Base64 byte[] xmlbytes = Encoding.UTF8.GetBytes(xml.ToString()); string xmlbytesbase64 = Convert.ToBase64String(xmlbytes); //формируем запрос Dictionary <string, string> data = new Dictionary <string, string> { { "RegistrationRequest", xmlbytesbase64 } }; HttpFormUrlEncodedContent content = new HttpFormUrlEncodedContent(data); while (true) { bool httpsuccess = false; HttpResponseMessage httpResponse = new HttpResponseMessage(); //пробуем достучаться до сервера пока не опухнем while (!httpsuccess) { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = loading; statustext.Text = "соединение с сервером..."; }); HttpClient httpClient = new HttpClient(); Uri requestUri = new Uri("https://" + tmplic.ServerEndPoint + GlobalVars.REGISTRATION_PATH); //отправляем на сервер httpResponse = await httpClient.PostAsync(requestUri, content); int delayvalue; try { //все нормально httpResponse.EnsureSuccessStatusCode(); httpsuccess = true; } catch { //ошибка, пауза 1 минута, потом новая попытка await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = Waiting; statustext.Text = "Ошибка соединения, следующая попытка через 01:00"; }); delayvalue = 60; while (delayvalue > 0) { Task.Delay(1000).Wait(); delayvalue--; await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = Waiting; statustext.Text = "Ошибка соединения, следующая попытка через " + (delayvalue / 60).ToString().PadLeft(2, '0') + ":" + (delayvalue % 60).ToString().PadLeft(2, '0'); }); } } } //обрабатываем ответ от сервера string resp = httpResponse.Content.ReadAsStringAsync().GetResults(); byte[] respbytes = Convert.FromBase64String(resp); string respxml = Encoding.UTF8.GetString(respbytes); //создаем объект ответа WaterDeviceRegistrationResponse regresp = Deserialize <WaterDeviceRegistrationResponse>(respxml); //выводим пользователю сообщение от сервера await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { regresponse.Text = regresp.AuthResponse; }); if (regresp.AuthResponse.StartsWith("SUCCESS")) { //вычисляем хеш открытого ключа клиента для проверки подписи strAlgName = HashAlgorithmNames.Sha512; objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName); objHash = objAlgProv.CreateHash(); objHash.Append(tmpreq.PublicKey.AsBuffer()); IBuffer ClientPublicKeyHashBuffer = objHash.GetValueAndReset(); //подпись лицензии byte[] SignatureBytes = Convert.FromBase64String(regresp.Signature); IBuffer SignatureBuffer = SignatureBytes.AsBuffer(); AsymmetricKeyAlgorithmProvider RSAVerifyProv = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaSignPkcs1Sha512); ServerPublicKey = RSAVerifyProv.ImportPublicKey(Convert.FromBase64String(GlobalVars.ServerPublicKey).AsBuffer(), CryptographicPublicKeyBlobType.Capi1PublicKey); bool res = CryptographicEngine.VerifySignatureWithHashInput(ServerPublicKey, ClientPublicKeyHashBuffer, SignatureBuffer); if (res) { //подпись корректна, сохраняем ее в файл string signfilename = ApplicationData.Current.LocalFolder.Path + "\\" + GlobalVars.HardWareID + ".002"; File.WriteAllBytes(signfilename, respbytes); //показываем пользователю, что все ОК await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = OK; statustext.Text = "OK"; }); return; } else { //подпись некорректна await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = Error; statustext.Text = "Регистрация закончилась неудачно"; }); return; } } if (regresp.AuthResponse == "OK_PENDING") { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = Waiting; statustext.Text = "Подтверждение, проверка через 05:00"; }); int delayvalue = 300; while (delayvalue > 0) { Task.Delay(1000).Wait(); delayvalue--; await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { statustext.Text = "Подтверждение, проверка через " + (delayvalue / 60).ToString().PadLeft(2, '0') + ":" + (delayvalue % 60).ToString().PadLeft(2, '0'); }); } } } } else { //Лицензия недействительна либо файл поврежден await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = Error; statustext.Text = "Лицензия недействительна"; }); return; } } } catch /*(DirectoryNotFoundException ex)*/ { } //catch (FileNotFoundException ex) //{ //} } await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { pic.Source = Error; statustext.Text = "Ошибка: файл лицензии не найден"; }); }