Znate da .NET omogućava da digitalno potpišete svoj kôd?

Zašto potpisujemo dll-ove?

Želimo da onemogućimo izmenu asemblija, npr. izmenu naziva ili verzije, ili izmeni samog kôda.

U nekim slučajevima je bitno da identifikujemo da je dll koji koristimo baš taj koji očekujemo. Ukoliko je biblioteka koja proverava da li je validna licenca našeg softvera u posebnom dll-u, relativno je lako podmetnuti drugi dll sa istim potpisom (klasama, metodama…) koji bi uvek vraćao da je licenca validna.

Digitalni potpis

Ideja digitalnog potpisa je da omogući primaocu proveru integriteta podataka koji potiču od pošiljaoca. Pošiljaoc, koji je i potpisnik podataka, ima par kriptografskih ključeva, javni ključ i privatni ključ. Primaocu je dostupan samo javni ključ, što je dovoljno da potvrdi da je poruku, tj. podatke koje je poslao pošiljaoc primio u izvornom obliku. Postoje različiti načini da se implementira digitalno potpisivanje, implementacija Strong name .NET Framwork-a se oslanja na RSA algoritam za enkripciju/dekripciju i SHA-1 heš funkciju.

Kako?

Neka naš solution  sadrži dva projekta biblioteku (Class Library) LicenceLibrary i konzolnu aplikaciju koja je koristi SignedAssemblySample, koristiću c# i Visual Studio 2010, priča je ista i za verziju 2005 ili 2008, solution možete skinuti sa ove adrese. Biblioteka LicenceLibrary, kao što joj ime kaže se brine za proveru licence naše aplikacije, tako što proverava da li je validan ključ, sadrži jednu klasu Licence (Licence.cs) sa metodom Validate:

[csharp]
public class Licence
{
public bool Validate(string key)
{
return key == "valid key";
}
}
[/csharp]

Ukoliko neko želi da krekuje našu aplikaciju, dovoljno je da napravi asembly sa istim nazivom koji ima ovakvu klasu:

[csharp]
public class Licence
{
public bool Validate(string key)
{
return true;
}
}
[/csharp]

I naša aplikacija bi uvek dobijala odgovor da je ključ validan.

Da bi zaštitili našu aplikaciju od ovakve zloupotrebe, uradićemo digitalno potpisivanje naše biblioteke LicenceLibrary.

Kreirajte solution sa dva projekta, konzolna aplikacija SignedAssemblySample i biblioteka LicenceLibrary. U Solution Explorer-u selektujte LicenceLibrary i kliknite <Alt> + <Enter> (ili desni klik pa properties) videćete properties dialog projekta. Izaberite poslednji tab Signing, označite Sign the assembly.

Project Properties

Sad name treba ključ kojim bi potpisali naš asembli, ukoliko imamo postojeći dovoljno je da ga lociramo, znači <Browse…> nađemo fajl, unesemo password ako postoji.

Strong name key file

Stara škola koristi Strong Name Tool (Sn.exe) iz komandne linije, a možemo i da izaberemo <New…> i pojaviće se dialog kao na slici.

Strong name key file dialog

Unesemo naziv fajla u kome će biti naš ključ, ako želimo možemo da zaštitimo ključ lozinkom i kliknemo OK.

To je to, čim bildujemo naš asembli biće potpisan. Kada dodamo referencu iz drugog projekta na našu biblioteku LicenceLibrary u properties ćemo videti ovako nešto:

Reference Properties

Napravićemo malu konzolnu aplikaciju, koja će nam poslužiti za testiranje, neka se zove  SignedAssemblySample. U aplikaciji referenciramo biblioteku LicenceLibrary i u Main metodi koristimo Licence objekat:

[csharp]
Licence licence = new Licence();
Console.WriteLine("First attempt, result: {0}",
licence.Validate("invalid key"));
Console.WriteLine("Second attempt, result: {0}",
licence.Validate("valid key"));
[/csharp]

Pri referenciranju strong named asemblija, asembli

Kada startujemo aplikaciju dobijamo ovakav izlaz:

[csharp]
First attempt, result: False
Second attempt, result: True
[/csharp]

Pokušaćemo da prevarimo aplikaciju, tj. da podmetnemo lažni asembli, koji bi vraćao True i kada prosleđeni ključ nije ispravan. Znači pravimo asembli koji ima analognu funkcionalnost kao LicenceLibrary, s tim što nije digitalno potpisan našim ključem i kopiramo ga preko izvorne biblioteke, kada pokrenemo SignedAssemblySample dobićemo exception:

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly ‘LicenceLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7043f5e70e5d29cc’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)   at SignedAssemblySample.Program.Main(String[] args)

Krekovanje nije uspelo 🙂

Tips & Tricks

Delay Signing

Ukoliko ne želite da svojim programerima date pristup ključu, možete koristiti Delay sign. Potrebno je izdvojiti javni deo ključa (malo komand prompta i Strong Name Tool sn.exe). Javni ključ koristiti tokom razvoja uz označenu opciju  Delay sign only na dialogu Properties tab Signing. Kada odlučite da isporučite asemblije, iskoristite privatni ključ za kreiranje strong name potpisa.  Za više detalja pravac MSDN Magazine.

Authenticode

Strong names potpise ne možete da proglasite nevažećim, tj. ne postoji revocation mehanizam. Ako neko (zlo)nameran dođe do vašeg privatnog ključa nemate načina da proglasite taj ključ za nevažeći i tako sprečite eventualne zloupotrebe. Ukoliko vam je potreban veći stepen sigurnosti i revocation mehanizam ključna reč je Authenticode, osnovna razlika je da sertifikat koji je obezbedio tzv. CA (certification authority).

Reenter password

Ukoliko postavite lozinku pri kreiranju strong name ključa, ona se pamti na tom računaru na kom radite (cryptographic storage). Što znači da kad bildujete projekat na drugom računaru morate da unesete password ponovo, Visual Studio se neće snaći u toj situaciji, počastiće vas greškom. Potrebno je da odete u Properties tab Signing i iz liste Choose a strong name key file izaberete isti ključ ponovo.

Da ponovim link na solution koji smo napravili (Visual Studio 2010).

Leave a Reply