Widok nocą na miejscowość Rijeka w Chorwacji

Visual Studio Tips: Podpisujemy bibliotekę

Visual Studio umożliwia w bardzo prosty sposób podpisywanie bibliotek, które rozwijamy w ramach solucji. Dzięki takiemu podpisowi możemy potwierdzać nie tylko ich autentyczność, ale także zapewnić, że w żadnej aplikacji, która ich używa, nie zostaną złośliwie podmienione. Dlaczego mielibyśmy się w ten sposób zabezpieczać? Przekonajmy się 🙂

Make me a coffee

Wyobraźmy sobie scenariusz, w którym jesteśmy posiadaczami inteligentnego domu, zaś w naszej kuchni stoi nowoczesny automat do kawy. Automat ten pozwala na zdalne uruchomienie procedury przygotowywania kawy – przydatna cecha w sytuacji, gdy wstając rano do pracy chcemy mieć ją już zaparzoną. Spróbujmy zasymulować ten świat jako solucję w Visual Studio. Solucją w tym przypadku byłby nasz inteligentny dom, zaś jednym z projektów maszyna do kawy:

Przykładowa reprezentacja inteligentnego domu w Solution Explorer
Przykładowa reprezentacja inteligentnego domu w Solution Explorer

Drugim projektem, o takiej samej nazwie co solucja, jest aplikacja konsolowa reprezentująca centrum sterowania domem. Wynik jej uruchomienia o określonej godzinie z zamiarem zrobienia kawy mógłby wyglądać następująco:

Smart Home przygotowuje kawę
Smart Home przygotowuje kawę

Kod odpowiedzialny za wywołanie procedury parzenia kawy mógłby zostać zaprojektowany jak niżej:

using System;

namespace SmartHome
{
  class Program
  {
    static void Main()
    {
      var scheduledTime = 
      new DateTime(2016, 02, 11, 07, 00, 00);

      if (DateTime.Now.Equals(scheduledTime))
      {
        CoffeeMachine.CoffeeModule.MakeACoffee();
      }           
    }
  }
}

What? Make it yourself

Idąc dalej obraną ścieżką, wyobraźmy sobie, że podczas naszej nieobecności w domu pojawia się intruz, który podmienia automat do kawy na wyglądający identycznie, lecz o nieco innej funkcjonalności. W analogii do naszej aplikacji sprowadziłoby się to do wyprodukowania assembly o takiej samej nazwie jak reprezentująca ekspres do kawy oraz zaimplementowania w niej metody używanej przez centrum sterowania domem. Solucja intruza mogłaby wyglądać następująco:

Przykładowa reprezentacja planu intruza w Solution Explorer
Przykładowa reprezentacja planu intruza w Solution Explorer

Podczas gdy wynik kompilacji aplikacji do obsługi inteligentnego domu wygląda następująco:

Wynik kompilacji aplikacji Smart Home
Wynik kompilacji aplikacji Smart Home

Wystarczy, że intruz podmieni automat do kawy – w tym przypadku plik dll – a zamiast napoju możemy otrzymać:

Bart Simpson wie jak narozrabiać
Bart Simpson wie jak narozrabiać

sudo Make me a coffee

Łatwo sobie wyobrazić sytuację, w której nasza aplikacja wymaga do uruchomienia uprawnień administratora. Daje to możliwość wykonania dowolnego kodu w podmienionej assembly, o ile oczywiście ktoś jest nam w stanie taką bibliotekę dostarczyć bez naszej wiedzy. Na szczęście Visual Studio pozwala na zapobieganie tego typu sytuacjom dzięki możliwości podpisania bibliotek wskazanym kluczem prywatnym. Dzięki temu zabiegowi aplikacja pozwoli na załadowanie jedynie tych bibliotek, które były dołączone do niej podczas kompilacji.

Aby podpisać bibliotekę, wystarczy w widoku solucji wybrać jej właściwości, następnie w zakładce „Signing” zaznaczyć, że chcemy, aby assembly została podpisana. Teraz pozostaje nam tylko wygenerować swoją parę kluczy przy pomocy opcji „New…” z listy rozwijanej lub – jeśli taką już posiadamy – wskazać miejsce na dysku, w którym się ona znajduje:

Podpisywanie biblioteki w Visual Studio
Podpisywanie biblioteki w Visual Studio

Poniżej listy znajduje się także opcja „Delay sign only”. Przydatna jest ona wtedy, gdy klucz prywatny stanowi tajemnicę firmy i nie jest udostępniany deweloperom. W takim przypadku dostarcza się jedynie klucz publiczny, zaś podpisywanie bilbiotek kluczem prywatnym dokonuje się w późniejszym etapie.

Dzięki temu prostemu zabiegowi, próba uruchomienia aplikacji z podmienioną biblioteką zakończy się komunikatem:

Po podpisaniu, aplikacja pozwala na załadowanie tylko biblioteki użytej podczas kompilacji
Po podpisaniu, aplikacja pozwala na załadowanie tylko biblioteki użytej podczas kompilacji

My zaś zyskamy pewność, że odbiorca uruchamiający naszą aplikację zobaczy dokładnie to, co zaprojektowaliśmy.


Źródła ASCII Art wykorzystanych w niniejszym wpisie:
1. http://www.retrojunkie.com/asciiart/food/coffee.htm
2. http://www.chris.com/ascii/index.php?art=cartoons/simpsons

  • eN

    SNK nie służy ani do zapewnienia autentyczność, ani nie zabezpiecza przed podmienieniem! SNK służy do identyfikacji assembly (głównie na potrzeby GAC) i można je podrobić! SNK to nie to samo co podpisanie assembly certyfikatem!

    • „Zapewnienie autentyczności” w kontekście niniejszego wpisu zostało użyte z małym uproszczeniem. Podpisanie assembly certyfikatem pozwala na jednoznaczne zweryfikowanie autora biblioteki oraz zapewnienie, że nikt w międzyczasie nie zmienił jej zawartości. Biblioteka podpisana jedynie przy pomocy Strong Name Key takiej pewności nie daje oraz – tak jak wspomniałeś – można bezproblemowo taki podpis podmienić. Jednak dopóki nie jesteśmy w posiadaniu prywatnego klucza użytego do podpisania assembly, nie jesteśmy w stanie (oczywiście w rozsądnym czasie) podszyć się pod autora, który tę bibliotekę podpisał wcześniej. Tym bardziej nie jesteśmy w stanie zmienić jej zawartości w taki sposób, aby inna biblioteka, która ma do niej referencję, uwierzyła, że zmiana została dokonana przez tego samego autora, który był nim podczas kompilacji.