Zrobiłem to z powodzeniem. Nie jest to zbyt trudne i działa dobrze. Używam go do aktywacji licencji na produkt. Najważniejszą rzeczą jest to, że naprawdę kontrolujesz klienta i serwer - nikt nie może wyodrębnić twojego klucza prywatnego z twojego kodu na kliencie.
Krok 1: Utwórz metody działania kontroler MVC, która pobiera żadnych argumentów:
[HttpPost] public ActionResult Activate() { ... }
Krok 2: W kontrolerze wystarczy użyć HttpRequest.InputStream dostać Ahold bajtów wysłanych od klienta .
var strumień = this.HttpContext.Request.InputStream;
Krok 3: Utwórz strumień kryptograficzny do deserializacji.
Załączam tutaj tworzenie przykładów szyfrowania i odszyfrowywania. SharedSecret to bajt [] o wystarczającej długości (512 bajtów) losowych bajtów - to jest to, co chronisz!
public CryptoStream CreateEncryptionStream(Stream writeStream)
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);
CryptoStream cryptoStream = new CryptoStream(writeStream, cryptoProvider.CreateEncryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Write);
return cryptoStream;
}
public CryptoStream CreateDecryptionStream(Stream readStream)
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);
CryptoStream cryptoStream = new CryptoStream(readStream, cryptoProvider.CreateDecryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Read);
return cryptoStream;
}
Krok 4: Użyj CryptoStream inny czytnik strumienia do odszyfrowania.
Używam XmlReader tak, że cały mój istniejący kod serializacji może działać w czystej formie (podczas odczytu/zapisu na dysku lub w bazie danych na serwerze) lub w postaci zaszyfrowanej (podczas przesyłania).
using (var reader = XmlReader.Create(decryptionStream, settings)) { ... }
Krok 5: Sformułuj bezpieczną odpowiedź w kontrolerze.
Wykonuje to w odwrotnej kolejności z kroków 1-4, aby zaszyfrować obiekt odpowiedzi. Następnie po prostu zapisz zaszyfrowaną odpowiedź do strumienia pamięci i zwróć ją jako wynik pliku. Poniżej pokazałem, jak to zrobić dla mojego obiektu odpowiedzi na licencję.
var responseBytes = GetLicenseResponseBytes(licenseResponse);
return File(responseBytes, "application/octet-stream");
private byte[] GetLicenseResponseBytes(LicenseResponse licenseResponse)
{
if (licenseResponse != null)
{
using (MemoryStream memoryStream = new MemoryStream())
{
this._licenseResponseSerializer.Write(memoryStream, licenseResponse);
return memoryStream.ToArray();
}
}
return null;
}
Krok 6: Wprowadź odpowiedź na żądanie klienta.
Możesz użyć HttpWebRequest lub klas WebClient do sformułowania żądania. Oto kilka przykładów z kodu, którego używam.
byte[] postBytes = GetLicenseRequestBytes(licenseRequest);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(licenseServerUrl);
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.Proxy = WebRequest.DefaultWebProxy;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(postBytes, 0, postBytes.Length);
}
return request;
private LicenseResponse ProcessHttpResponse(HttpWebResponse response)
{
if ((response.StatusCode == HttpStatusCode.OK) && response.ContentType.Contains("application/octet-stream"))
{
var stream = response.GetResponseStream();
if (stream != null)
{
var licenseResponse = this._licenseResponseSerializer.Read(stream);
return licenseResponse;
}
}
return new LicenseResponse(LicensingResult.Error);
}
Podsumowanie i Wskazówki
- pomocą strumieni we wniosku/odpowiedzi na klienta i serwera do komunikowania danych binarnych oktet-strumieniowych
- Używaj CryptoStream wraz z algorytmu szyfrowania (rozważyć przy użyciu najsilniejszego możliwego szyfrowania) i dobry klucz prywatny do szyfrowania danych podczas serializacji/deserializacji.
- Pamiętaj, aby sprawdzić rozmiar i format wszystkich przychodzących danych do klienta i serwera (uniknij przepełnienia bufora i wyrzuć wyjątki wcześniej)
- Chroń swój prywatny klucz na kliencie za pomocą zaciemniania, jeśli to możliwe (spójrz na oblepiciela DeepSea)
Ponowne wynalezienie SSL/TLS ?? – Aliostad
Problem polega na tym, jak łatwo człowiek w środkowych atakach używa narzędzi takich jak Skrzypek. – DannyT