Strong named assemblies in C#

  1. Inleiding
  2. dynamic link library
  3. executable
  4. strong named
  5. key file
  6. public key
  7. andere eigenschappen
  8. csc.exe – dll maken
  9. csc.exe – executable maken
  10. Slot

Inleiding

In een eerdere post over assemblies hebben we laten zien hoe een dynamic link library (.dll) gemaakt kan worden. Helaas moeten we rekening houden met de mogelijkheid dat een .dll door een kwaadaardige entiteit gehackt kan worden en dat onverlaten de .dll kunnen transformeren tot een kwaadaardig stuk software. Gelukkig kunnen we daar iets tegen doen door de assemblies strong named te maken zodat het voor hackers wat lastiger wordt om assemblies te infecteren.

up | down

dynamic link library

We gaan het één en ander toelichten aan de hand van het voorbeeld hieronder. Het is een eenvoudige methode met een input parameter. Methode Geslacht.Bepaal() heeft één input parameter (‘M’ of ‘V’ of ‘T’) en het zal de tekst ‘Man’, ‘Vrouw’ of ‘Transgender’ retourneren . De waarde van de input parameter bepaalt welke waarde precies wordt geretourneerd. We gaan een dynamic link link library maken dat deze methode zal bevatten.

using System.Reflection;
namespace bibliotheek
{
 public static class Geslacht
 {
  public static string Bepaal(char code)
  {
   switch (code)
   {
    case 'M': return "Man";
    case 'V': return "Vrouw";
    case 'T': return "Transgender";
    default: return "Onbekend";
   }
  }
 }     
}

up | down

executable

Methode Geslacht.Bepaal() wordt aangeroepen door een Hoofdprogramma. Het hoofdprogramma gebruikt daarvoor een assembly met de naam bibliotheek en methode Geslacht.Bepaal() bevindt zich in die assembly. Van het hoofdprogramma gaan we een executable maken.

using System;
using bibliotheek;
namespace Hoofdprogramma
{
 class Klasse
 {
   public static void Main()
   {
     Console.WriteLine(
     "Over jou:");

     Console.WriteLine(
     "Je bent een {0}",
 
     Geslacht.Bepaal('V'));
     Console.WriteLine(

     "Druk op een willekeurige toets om verder te gaan...");
     Console.ReadKey();
   }
 }    
}

Dit wordt het uiteindelijke resultaat omdat methode Geslacht.Bepaal() wordt aangeroepen met de ‘V’ als input parameter:

up | down

strong named

De dynamic link library maken we strong named door aan de assembly eigenschappen toe te kennen en (unieke) waarden in te vullen voor die eigenschappen. Het gaat daarbij om de volgende eigenschappen:

  • de public key (de belangrijkste eigenschap voor het strong named maken van de assembly)
  • de naam
  • het versienummer
  • een culture (facultatief)

up | down

key file

Het genereren van een private en public key begint met een key file. Een key file maken we met sn.exe (de strong name tool). sn.exe is één van de tools die inbegrepen zijn bij de Microsoft .NET Framework Software Development Kit (SDK) en je krijgt de tool als je bijvoorbeeld Visual Studio installeert, maar misschien dat het al standaard bij Windows zit. Je weet het snel genoeg door op je computer een scan te doen naar sn.exe. We maken als volgt een key file met sn.exe:

sn -k  SleutelBestand.snk

De key file bevat de private key waarmee je de public key en in feite de handtekening van de assembly genereert. Laat de key file niet in handen vallen van onbevoegden want ten slotte hoor jij de enige te zijn die met die key file een assembly signeert. Het laatste wat je zou willen is dat een kwaadaardige entiteit een schadelijke assembly distribueert waarbij die assembly jouw digitale handtekening heeft.

De naam van de assembly hoeft dankzij de public key geen problemen te geven als een andere publisher een assembly heeft met een naam dat gelijk is aan de naam van jouw assembly. De andere publisher zal zijn eigen private key gebruiken voor het genereren van de public key waardoor de assembly van de andere publisher een signatuur heeft dat verschilt van de signatuur van jouw assembly. Het operating system ziet dat ook en het zal aan de hand van de signatuur ervoor zorgen dat de juiste assembly klaargezet wordt.

De herkomst van de assembly wordt op die manier ook enigszins gewaarborgd. Een aanroepend programma is bekend met de signatuur van de te gebruiken assemblies. Het aanroepende programma zal dat zien als de signatuur van een gevonden assembly afwijkt van de signatuur dat bij het aanroepend programma bekend is. Het aanroepende programma zal dan besluiten niet gebruik te maken van die dubieuze assembly en zal zelfs niet eens starten.

up | down

public key

De key file heeft een public key en een public key token. sn.exe hebben we gebruikt om een key file te maken en met diezelfde sn.exe krijg je als volgt de public key en de public key token te zien:

sn –p SleutelBestand.snk SleutelBestand.pubKey
sn –tp SleutelBestand.pubKey > SleutelBestand.txt

in dit voorbeeld hebben we de output van sn –tp naar bestand SleutelBestand.txt gestuurd en in dat bestand zien we de waarden voor de public key en de public key token.

up | down

andere eigenschappen

We hebben het hiervoor gehad over de public key assembly eigenschap, zijnde de belangrijkste eigenschap voor het strong named kunnen maken van een assembly.

Voorzie de overige assembly eigenschappen ook van een waarde om de assembly as strong named as possible te maken. De overige assembly eigenschappen kunnen we van een waarde voorzien door deze als attribuut (AssemblyTitle, AssemblyVersion, AssemblyProduct, AssemblyFileVersion, AssemblyCopyright en AssemblyDescription) op te nemen in de code.

De key file kunnen we ook opgeven bij de assembly attribuut, bijvoorbeeld: [assembly: AssemblyKeyFile(C:\\SleutelBestand.snk”)] (let op de dubbele \). We maken in dit voorbeeld voor de key file geen gebruik van een attribuut. In plaats daarvan geven we bij het compileren met csc.exe aan dat we een key file gebruiken.

using System.Reflection;
[assembly: AssemblyTitle("geslacht")]
[assembly: AssemblyVersion("1.0.0.1")]
[assembly: AssemblyProduct("Library Bepaal Geslacht")]
[assembly: AssemblyFileVersion("1.0.0.1")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyDescription("Library om het geslacht te bepalen")]
namespace bibliotheek
{
 public static class Geslacht
 {
  public static string Bepaal(char code)
  {
    .
    .
    .

up | down

csc.exe – dll maken

We hebben alle relevante eigenschappen van de assembly van een waarde voorzien en we hebben een key file. We gaan nu met csc.exe (de csharpcommandline compiler) bestand geslacht.cs compileren naar een dynamic link library (.dll). We geven bij het compileren aan dat key file SleutelBestand.snk gebruikt moet worden. De assembly wordt dan gesigneerd met een public key:

csc /t:library /out:geslacht.dll 
/keyfile:SleutelBestand.snk 
geslacht.cs

Als we assembly geslacht.dll met ildasm.exe bekijken dan zien we in de manifest van de assembly de public key. We zien dat de waarde van de publickey gelijk is aan de waarden in bestand SleutelBestand.txt:

Als we na het compileren geslacht.dll met de File Explorer bekijken dan zien we bij de eigenschappen van de .dll de waarden welke we in de code bij de attributen hebben opgegeven:

up | down

csc.exe – executable maken

We gaan nu het hoofdprogramma met csc.exe compileren en we geven op dat geslacht.dll gebruikt moet worden. geslacht.dll is inmiddels een gesigneerde assembly:

csc main.cs /t:exe /r:geslacht.dll /out:programma.exe

Als we de .exe met ildasm.exe bekijken dan zien we in het manifest dat een library wordt gebruikt met public key token 1a aa aa 11 11 a1 11 11 en die token vinden we ook terug in de key file waarmee we de assembly hebben gesigneerd. We zien in het manifest van de .exe ook het versienummer van de te gebruiken library.

Het aanroepende programma zal vaak niet eens starten als het programma de library vindt, maar ziet dat de library een andere public key / public key token (signatuur) heeft. Als de signatuur afwijkt dan kan dat erop duiden dat de .dll misschien is geïnfecteerd (door een virus?).

up | down

Slot

In deze post heb ik laten zien hoe een dynamic link library (.dll) gesigneerd kan worden. Alleen de publisher kan de assembly signeren met een public key waardoor verondersteld kan worden dat de assembly inderdaad ook van die publisher afkomstig is. Voorwaarde om deze maatregel te doen slagen is dat de private key waarmee de public key genereerd wordt geheim blijft waardoor de desbetreffende publisher als enige de digitale handtekening kan zetten.

Bij het compileren krijgt het aanroepende programma de signatuur mee van de te gebruiken libraries. Het aanroepende programma kan op die manier detecteren of er afwijkingen zijn voor wat betreft de te gebruiken libraries. “Bij twijfel niet inhalen” en dat geldt ook voor een aanroepend programma. Als de signaturen van de te gebruiken libraries afwijken dan zijn de libraries misschien wel geïnfecteerd. Het aanroepend programma zal dan niet eens opstarten.

Als we een assembly distribueren dan kan het voorkomen dat versies elkaar “bijten” omdat de aanroepende programmatuur nog gebruik maakt van een oude versie. We hebben vaak geen grip op het aanroepende programma omdat in de meeste gevallen een andere partij het aanroepende programma geschreven heeft. Het in goede banen leiden van de verschillende versies van een assembly kunnen we regelen met de Global Assembly Cache (GAC). Voorwaarde voor het doen opnemen van een assembly in de GAC is dat de assembly strong named moet wezen. Meer over de GAC in deze post.

Hopelijk ben je met deze posting weer wat wijzer geworden en ik hoop je weer terug te zien in één van mijn volgende blog posts. Wil je weten wat ik nog meer over C# heb geschreven? Hit the C# button…

up


Laat een reactie achter

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *