Академический Документы
Профессиональный Документы
Культура Документы
Introduction..................................................................................................................................... 3
Prambule ............................................................................................................................... 4
2.2
2.3
2.3.1
2.3.2
2.3.3
2.3.4
2.4
3
3.2
3.3
Authentification..................................................................................................................... 41
4.1.1
4.1.2
4.1.3
4.1.4
4.1.5
4.2
5
Autorisation ........................................................................................................................... 47
5.2
6.2
6.2.1
6.2.2
6.3
6.3.1
RSACryptoServiceProvider ............................................................................................ 64
6.3.2
DSACryptoServiceProvider ............................................................................................ 69
6.4
7
Signatures numriques.......................................................................................................... 70
Conclusion ..................................................................................................................................... 74
Date
1 Introduction
De nos jours, la scurit est un des piliers cl de toutes applications en entreprise. En effet, on
ne pourrait pas imaginer un monde dans lequel toutes les transactions bancaires lectroniques ne
soient pas effectues en utilisant des systmes de protections adapts.
Mme si avec les solutions actuelles, la scurit informatique absolue n'existe pas, il existe de
nombreux moyens permettant de donner du fil retordre aux hackers qui chercheraient exploiter
vos applications industrielles.
Dans ce chapitre, nous aborderons tout d'abord la scurit d'accs aux ressources locales
(propre la CLR). Ensuite, nous verrons comment grer les rgles de scurit d'accs aux ressources
puis nous terminerons le chapitre par les techniques de cryptographie implmentes par le .NET
Framework.
Date
Ce principe de groupes/utilisateurs ayant des rles particulier est appel "Role-based Security"
ou RBS.
Le Framework .NET possde un systme comparable afin de grer la scurit des applications
qui sont excutes via la CLR. Ce systme, en plus des possibilits via le code, est regroup sous le
nom de "Code Access Security" ou CAS en abrg. Les assemblies pourraient tre apparents aux
utilisateurs.
Note : Avant d'aller plus loin, il est impratif d'installer le .NET Framework 2.0 SDK disponible
ici. Ce SDK contient plusieurs outils de gestion du Framework .NET dont un composant enfichable de
la console MMC appel "Configuration du .NET Framework 2.0". Pour lancer l'utilitaire, cliquez le
Date
menu Windows, allez sur "Excuter" (ou directement dans la barre de recherche sous Vista) puis
tapez "mmc". L, faites "FichierAjouter/Supprimer un composant logiciel enfichable" et
slectionnez le composant ".NET Framework 2.0 Configuration".
Important : S'il est possible de grer totalement les possibilits des applications en code
manag, il est impossible d'effectuer les mme oprations sur du code non-manag (Cette notion de
code manag ou non sera vue dans les chapitre suivant). Vous devrez vous baser sur les rles
attribus chacun de vos utilisateurs/groupes pour viter les problmes. Aussi, mme si cela est
contraignant au dbut, n'oubliez jamais qu'une scurit digne de ce nom est celle qui accorde le
moins de privilges possibles aux utilisateurs. Ce principe est bien entendu vrai en ce qui concerne
les applications.
Date
projet Winform dans lequel nous avons gliss une textbox configure en "Multiline = true",
"Scrollbars = Both" et "ReadOnly = true" (Optionnellement vous pouvez ajouter un couteur sur la
fentre principale l'vnement ResizeEnd) :
'VB
Public Sub New()
InitializeComponent()
Dim e As Evidence = AppDomain.CurrentDomain.Evidence
For Each o As Object In e
TextBox1.Text += o.ToString() + vbNewLine
Next
End Sub
Private Sub Partie_1_ResizeEnd(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.ResizeEnd
TextBox1.Size = New System.Drawing.Size(MyBase.Width - 50,
MyBase.Height - 50)
End Sub
Date
//C#
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Evidence e = AppDomain.CurrentDomain.Evidence;
foreach(Object o in e)
textBox1.Text += o.ToString() + "\n";
}
private void Form1_ResizeEnd(object sender, EventArgs e)
{
textBox1.Size = new System.Drawing.Size(base.Width - 50,
base.Height - 50);
}
}
Aprs compilation, vous devriez une fentre contenant le Hash de votre application, l'URL et sa
zone :
Date
Vous avez remarqu que certaines options ncessitent la signature de l'assembly. Pour signer
une assembly, cela reste relativement simple. Vous allez dans les proprits du projet et vous allez
sur l'onglet "Signature" et vous cochez la case "Signer l'assembly"
Si vous retournez dans votre solution, vous avez maintenant un fichier .pfx qui est apparu et
qui contient la signature numrique de votre application.
Notez que si vous r-excutez le projet prcdent, vous avez un champ supplmentaire
(StrongName) qui est apparu dans l'evidence utilise :
Date
Une autre information qui peut tre utile pour la suite, c'est de savoir rcuprer un jeton de
cl publique pour votre application. Pour cela, vous devez ouvrir la commande Visual Studio et saisir
la commande suivante :
sn -T "<chemin de votre assembly>"
En rponse directe, vous aurez le jeton de cl publique qui s'affichera dans la console (Pour
avoir un jeton disponible, il est obligatoire de signer votre application.) :
Setting environment for using Microsoft Visual Studio 2008 x86 tools.
C:\Program Files\Microsoft Visual Studio 9.0\VC>sn -T "D:\Documents\dotNet Franc
e\Framework - VB\Chapitre 11\bin\Debug\Chapitre 11.exe"
Microsoft (R) .NET Framework Strong Name Utility Version 3.5.30729.1
Copyright (c) Microsoft Corporation. Tous droits rservs.
Le jeton de la cl publique est 7a507855d0c56903
C:\Program Files\Microsoft Visual Studio 9.0\VC>
Date
10
11
Pour cette partie, nous allons modifier les paramtres propres l'utilisateur en cours. En effet,
c'est la seule section qui contient toutes les catgories de scurit possible ; les autres ayant les
mmes fonctions mais plus grande chelle.
Si vous droulez la ligne Ordinateur, vous avez quatre nouvelles sections qui apparaissent :
"Groupes de codes", qui permettent d'associer des jeux d'autorisations avec des
assemblies particulires.
"Jeux d'autorisations", qui sont l'quivalent des groupes d'utilisateurs. Ils rassemblent
plusieurs rgles de scurit sous un mme nom.
"Assemblys de stratgie", qui contient toutes les assemblies soumises des rgles de
scurit et qui se trouvent dans le cache d'assembly (GAC pour Global Assembly
Cache).
"Applications approuves", qui contient toutes les assemblies qui sont considres comme digne de
confiance (Fully Trusted). Les autres assemblies soumises des rgles sont dites de confiance
partielle (Partially Trusted).
Date
12
2.3.1
Pour voir plus en dtail chaque autorisation du jeu d'autorisation, il vous suffit de doublecliquer sur l'une des autorisations affiches pour en montrer les permissions. Ci-dessous, nous
affichons les permissions de l'autorisation nomme "Reflexion" :
Date
13
Vous pouvez bien sur crer vos propres jeux d'autorisation. Pour a, il vous suffit de faire clicdroit sur "Jeux d'autorisations" et de faire "Nouveau" :
Si vous avez export un jeu d'autorisation en XML, vous pouvez l'importer nouveau en
slectionnant "Importer un jeu d'autorisation partir d'un fichier XML". Sinon, laissez la premire
option slectionne, saisissez le nom et une description du jeu d'autorisations. Ensuite, cliquez sur
"Suivant".
Dans le cadre suivant, vous slectionnez les autorisations disponibles pour le jeu en cours
d'dition. Pour ajouter des autorisations, il vous suffit de cliquer sur l'autorisation ajouter et de
faire "Ajouter >>".
Date
14
Chaque autorisation porte un nom assez explicite qui n'a pas besoin d'tre dtaill. Aussi, je
me contenterais de dtailler ceux qui peuvent l'tre moins :
Magasin X509 : Spcifie l'autorisation d'accder, modifier, ajouter ou supprimer une
entre du magasin de certificats X509.
Service d'annuaire : Spcifie l'accs aux bases de donnes Active Directory.
DNS : Spcifie les autorisations effective quand l'envoi de requtes DNS.
Lorsque vous cliquez sur le bouton ajouter, une nouvelle fentre s'ouvre, dans laquelle vous
pouvez modifier les permissions :
Date
15
Date
16
2.3.2
Date
17
Ensuite, cliquez sur "Suivant". Sur la fentre suivante, vous slectionnerez le jeu
d'autorisations qui rgira les permissions du groupe de code (Vous pouvez aussi choisir de crer un
nouveau jeu d'autorisations) :
Date
18
Dans l'exemple, nous basons notre groupe de codes sur le jeu d'autorisations cr plus haut.
Quand tout est paramtr selon vos besoins, cliquez sur "Suivant" puis sur "Terminer". De toute
faon, vous pourrez modifier les autorisations du groupe plus tard.
Pour l'exemple, nous modifierons le groupe de codes cr et nous cocherons la case "Ce
niveau de stratgie ne bnficiera que des autorisations du jeu d'autorisation associ ce groupe de
codes" ; la raison en sera explique plus bas.
Cot code, on rutilisera le projet cr au dbut de ce chapitre ; Nous n'enlverons aucun code
mais nous ajouterons le code suivant dans le constructeur de la classe principale, juste avant la
boucle foreach :
'VB
Try
Dim s As System.Windows.Forms.SaveFileDialog = New
System.Windows.Forms.SaveFileDialog()
s.ShowDialog()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
//C#
try
{
System.Windows.Forms.SaveFileDialog
System.Windows.Forms.SaveFileDialog();
s.ShowDialog();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
s = new
Date
19
Malgr notre ligne d'affichage d'une boite de dialogue SaveFileDialog, aucune autre fentre
que la fentre principale ne sera affich ; et c'est entirement explicable. Rappelez-vous, dans la
partie prcdente, notre jeu d'autorisations autorise l'affichage des fentres (Interface utilisateur)
mais interdit l'affichage des boites de dialogue en sauvegarde. Cette interdiction lve une exception
affiche dans la console.
Attention : La scurit du .NET Framework peut tre tout aussi puissante que le systme
RBS pour les utilisateurs de la machine Windows. Seulement, ce qui fait sa puissance peut
aussi rapidement devenir un vritable dsastre si elle est mal configure. Des rgles de
scurit trop exigeantes peuvent mme vous empcher de lancer Visual Studio ; ce
dernier utilisant certaines assemblies du Framework, il gnrera des erreurs tour de bras, vous
empchant ainsi toute utilisation normale.
Note : Pour vous aider configurer correctement vos rgles de scurit, n'hsitez pas utiliser
l'valuation d'assembly. A l'image de l'outil "Autorisation effective" pour les utilisateurs, il permet
d'afficher toutes les rgles de scurit affectant une assembly spcifie. Pour cela, faites clic-droit sur
"Stratgie de scurit du runtime" et slectionnez "Evaluer l'assembly".
Il ne vous reste plus qu' slectionner le fichier contenant l'assembly valuer, indiquer
quelles informations afficher et cliquer sur Suivant :
Date
20
Date
21
Ici nous pouvons voir clairement que "Copie de GroupTest" est un groupe de code enfant du
groupe "All_code".
Tout l'heure, nous avions affich les autorisations effectives sur l'assembly et avions constat
que les rgles dfinies par notre jeu d'autorisation taient bien prsentes.
Maintenant, si nous modifions le groupe de code "Copie de GroupTest", que nous dcochons
la case indique et que nous affichons nouveau les autorisations effectives :
Date
22
Nous pouvons remarquer prsent que l'assembly est passe en "Non restreint".
Cette case "Ce niveau []" permet en fait de forcer la CLR appliquer uniquement les permissions du
jeu d'autorisation li au groupe de code et ce, sans tenir compte des autorisations du groupe de code
parent. Si nous la dcochons, notre groupe de code "Copie de GroupTest" va de nouveau hriter des
rgles de scurit du groupe "All_code" qui est configur pour permettre n'importe quel
programme de grer n'importe quelle ressource.
Date
23
2.3.3
Applications approuves
Cette section regroupe les applications "ClickOnce" ( dploiement rapide) considres
comme approuves, c'est-a-dire quelles sont rgies par des rgles de scurit non paramtrable.
2.3.4
Date
24
Date
25
Maintenant que nous avons vu les trois principales valeurs qui nous intressent dans
lnumration SecurityAction, nous allons dtailler les demandes de permissions principales
misent disposition par le Framework .NET :
Classes
Description
AspNetHostingPermission
Demande daccs entre le systme et un environnement
Asp.NET.
DataProtectionPermission
Demande daccs la mmoire et des donnes chiffres.
DirectoryServicesPermission
Demande
daccs
lespace
de
nom
System.DirectoryServices.
DnsPermission
Demande daccs un serveur DNS.
EnvironmentPermission
Demande daccs aux variables du systme et de
lenvironnement de lutilisateur.
EventLogPermission
Demande daccs au journal dvnements.
FileDialogPermission
Demande daccs un fichier du systme partir dune
boite de dialogue.
FileIOPermission
Demande daccs un fichier du systme.
IsolatedStorageFilePermission Demande daccs aux zones de stockages isoles
KeyContainerPermission
Demande daccs un conteneur de cl. Voir la partie sur
la scurit des donnes.
OdbcPermission
Demande daccs une source de donne ODBC.
OleDbPermission
Demande daccs une base de donnes en utilisant
OleDb.
OraclePermission
Demande daccs une base de donnes Oracle.
PerformanceCounterPermission
Demande daccs aux compteurs de performances.
PrintingPermission
Demande daccs aux imprimantes.
ReflectionPermissions
Demande de permission dutilisation des outils de lespace
de nom System.Reflection.
RegistryPermission
Demande daccs au registre Windows.
ServiceControllerPermission
Demande daccs au contrle des services.
SocketPermission
Demande lautorisation de crer une connexion par
sockets.
SqlClientPermission
Demande laccs une base de donnes SQL.
UIPermission
Demande daccs linterface utilisateur et au pressepapier. Ncessaire au dbuggeur de Visual Studio.
WebPermission
Demande daccs une ressource sur internet par HTTP.
Note : Ces classes possdent toutes une version attribut mais vous pouvez les utiliser en tant
quobjets. Nous ne dtaillerons pas cette faon de faire.
Date
26
Nous allons illustrer un peu ce que nous avons vu avec un court exemple :
Tout dabord nous crons un fichier texte la racine de notre disque C : que nous appelons
test.txt. Ensuite, nous relanons la console MMC et nous autorisons l'accs au fichier par notre
assembly uniquement en lecture (Par souci de simplicit, ajoutez galement l'accs total la gestion
de la scurit et l'interface utilisateur).
Ensuite nous allons accder dans notre application une premire fois en lecture et une
seconde en criture.
Date
27
'VB
Imports System.IO
Imports System.Security.Permissions
<Assembly: UIPermission(SecurityAction.RequestOptional,
Clipboard:=UIPermissionClipboard.AllClipboard,
Window:=UIPermissionWindow.AllWindows)> _
<Assembly: FileIOPermission(SecurityAction.RequestMinimum,
Read:="C:\test.txt")> _
<Assembly: FileIOPermission(SecurityAction.RequestOptional,
Write:="C:\test.txt")> _
Module partie2
Public Sub Main()
Try
Console.WriteLine("Tentative de lecture")
Dim sr As StreamReader = New StreamReader("c:\test.txt")
sr.Close()
Console.WriteLine("Tentative d'criture")
Dim sw As StreamWriter = New StreamWriter("c:\test.txt")
sw.Close()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Console.Read()
End Sub
End Module
Date
28
//C#
using System;
using System.IO;
using System.Security.Permissions;
[assembly: UIPermission(SecurityAction.RequestOptional, Window =
UIPermissionWindow.AllWindows, Clipboard =
UIPermissionClipboard.AllClipboard)]
[assembly: FileIOPermission(SecurityAction.RequestMinimum, Read =
@"C:\test.txt")]
[assembly: FileIOPermission(SecurityAction.RequestOptional, Write =
@"C:\test.txt")]
namespace Chapitre_11
{
class Partie2
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Tentative de lecture")
StreamReader sr = new StreamReader(@"c:\test.txt");
sr.Close();
Console.WriteLine("Tentative d'criture")
StreamWriter sw = new StreamWriter(@"c:\test.txt");
sw.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
Date
29
revanche,
si
nous
changeons
le
second
paramtrage
FileIOPermission
de
Pour finir, supprimez les rgles de scurit dfinie dans ce test grce la console MMC et
modifiez le second paramtrage FileIOPermission de RequestOptional RequestRefuse.
Tentative de lecture
Tentative d'criture
chec de la demande d'autorisation de type 'System.Security.Permissions.FileIOPermission, mscorlib,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Nous aurons droit la mme erreur que si nous avions laiss le paramtrage de la CLR avec
une demande RequestOptional.
Maintenant que nous savons comment restreindre les permissions au niveau de l'assembly,
nous pourrions galement nous demander comment faire pour appeler du code de confiance totale
partir d'une assembly de confiance partielle. Pour cela, rien de plus simple que d'ajouter l'attribut
suivant :
'VB
<Assembly: System.Security.AllowPartiallyTrustedCallers()>
//C#
[assembly: System.Security.AllowPartiallyTrustedCallers]
Sachez toutefois que les membres publiques d'une assembly non-signe sont accessibles
depuis l'extrieur, mme si cet attribut n'est pas prsent !
Date
30
Date
31
Dans le cas de LinkDemand, nous avons choisit simplement de fermer la porte clef, ds
quune personne ouvert la porte, tous le monde peut entrer, tous le processus est simplifi,
mais les intrus peuvent rentrer trs facilement.
InheritanceDemand est une version plus pousse du dispositif douverture par badge. On
peut imaginer que nous avons rajouts un vigile qui va vrifier que les personnes qui
accompagnent un employ sont autorises entrer (par exemple des clients).
Maintenant que nous y voyons un peu plus clair sur la mthode dclarative de demande de
permissions, nous allons parler un petit peu de la mthode imprative.
Nous avons vu que pour faire une demande de permission dclarative, il nous fallait utiliser un
attribut au dessus de nos classes ou mthodes. Pour faire une demande de permission imprative,
nous allons instancier un objet qui hrite de CodeAccessPermission et utiliser les mthodes qui
conviennent. Cela va nous permettre de faire des demandes de permissions pour une partie prcise
dun bloc plutt que pour le bloc entier.
Les mthodes de CodeAccessPermission ne vous serons pas trangre puisquelles portent
le mme nom que les valeurs de lnumration SecurityAction et ont les mmes comportements.
En revanche LinkDemand et InheritanceDemand nexistent pas.
Afin de comprendre la diffrence entre les deux nous allons voir un exemple dutilisation des
deux mthodes. Notre exemple ne va utiliser que Demand, les autres actions seront vues ensuite.
VB
Imports System.IO
Imports System.Security.Permissions
<FileIOPermission(SecurityAction.Demand, Write:="C:\")> _
Public Sub Ecrire()
Dim sw As StreamWriter = New StreamWriter("C:\test.txt")
sw.WriteLine("blabla")
sw.Flush()
sw.Close()
End Sub
Public Sub EcrireDeux()
Dim FP As FileIOPermission = New
FileIOPermission(FileIOPermissionAccess.Write, "C:\test.txt")
FP.Demand()
Dim sw As StreamWriter = New StreamWriter("C:\test.txt")
sw.WriteLine("tructruc")
sw.Flush()
sw.Close()
End Sub
Public Sub Lire()
Dim sr As StreamReader = New StreamReader("C:\test.txt")
Console.WriteLine(sr.ReadToEnd())
sr.Close()
End Sub
Public Sub Main()
Ecrire()
Lire()
EcrireDeux()
Lire()
Console.Read()
End Sub
Date
32
//C#
using System.Security.Permissions;
using System.IO;
[FileIOPermission(SecurityAction.Demand, Write = @"C:\")]
public static void Ecrire()
{
StreamWriter sw = new StreamWriter(@"C:\test.txt");
sw.WriteLine("blabla");
sw.Flush();
sw.Close();
}
public static void EcrireDeux()
{
FileIOPermission FP = new
FileIOPermission(FileIOPermissionAccess.Write, @"C:\test.txt");
FP.Demand();
StreamWriter sw = new StreamWriter(@"C:\test.txt");
sw.WriteLine("tructruc");
sw.Flush();
sw.Close();
}
public static void Lire()
{
StreamReader sr = new StreamReader(@"C:\test.txt");
Console.WriteLine(sr.ReadToEnd());
sr.Close();
}
public static void Main(string[] args)
{
Ecrire();
Lire();
EcrireDeux();
Lire();
Console.Read();
}
Nous avons donc utilis la mthode dclarative pour la premire mthode Ecrire. Nous
demandons lautorisation dcrire sur tout le lecteur C, si la permission est accorde, nous pourrons
crire partout sur ce lecteur. Cependant, vous pouvez avoir les droits daccs au lecteur C sans pour
autant les avoir sur le fichier concern. Dans tous les cas, si vous ne possdez pas les droits
ncessaires, une exception sera leve.
Dans la deuxime mthode EcrireDeux, nous faisons une demande de permission
imprative. Nous indiquons que nous voulons crire sur le fichier test.txt en particulier. Grce cette
mthode nous allons pouvoir grer les cas o une demande est refuse afin quaucune exception ne
soit leve, nous allons le voir dans un exemple venir.
Bien entendu, les deux mthodes Ecrire et EcrireDeux ont le mme comportement final
comme en atteste la console :
blabla
tructruc
Nous allons reprendre notre exemple prcdent et grer le cas o la demande serait refuse.
Par exemple nous pourrons afficher une boite de dialogue demandant quel endroit lapplication
pourra enregistrer le fichier. Vous aurez besoin dimporter lespace de nom System.Security pour
effectuer la vrification :
Date
33
VB
Imports System.IO
Imports System.Security.Permissions
Imports System.Security
Public Sub EcrireDeux()
Dim FP As FileIOPermission = New
FileIOPermission(FileIOPermissionAccess.Write, "C:\test.txt")
If (SecurityManager.IsGranted(FP)) Then
Dim sw As StreamWriter = New StreamWriter("C:\test.txt")
sw.WriteLine("tructruc")
sw.Flush()
sw.Close()
Else
Console.WriteLine("Erreur")
End If
End Sub
//C#
using System.Security.Permissions;
using System.IO;
using System.Security;
public static void EcrireDeux()
{
FileIOPermission FP = new
FileIOPermission(FileIOPermissionAccess.Write, @"C:\test.txt");
if (SecurityManager.IsGranted(FP) == true)
{
StreamWriter sw = new StreamWriter(@"C:\test.txt");
sw.WriteLine("tructruc");
sw.Flush();
sw.Close();
}
else
{
Console.WriteLine("Erreur");
}
}
Nous avons un peu modifi notre mthode EcrireDeux, tout dabord, nous nutilisons plus
les mthodes de CodeAccessPermission. Nous instancions juste un objet FileIOPermission
qui sera vrifi dans la condition suivante. Nous vrifions que la permission est accorde grce la
mthode statique SecurityManager.IsGranted. Si la valeur retourne est true, alors cest que la
permission est accorde, nous pouvons crire dans notre fichier.
Bien entendu, sil est possible de faire des demandes de permissions, il est galement possible
de les interdire. Pour cela, vous pouvez procder galement de faon imprative ou dclarative.
Pour refuser des droits explicitement, vous pouvez utiliser :
Deny : Cette valeur va nous permettre de supprimer une permission ou un jeu
d'autorisations de la mthode concerne (Elle va crer une liste noire des permissions
effectives sur la mthode).
PermitOnly : Permet de supprimer toutes les autorisations accordes jusqu'ici et de
n'autoriser que celles qui sont affectes par ce paramtre (Elle va crer une liste
blanche des permissions effectives sur la mthode).
Dans cet exemple, nous crons plusieurs mthodes permettant daccder au fichier C:\test.txt
ainsi quune mthode lanant les deux autres mais qui est quipe dune restriction dclarative :
Date
34
'VB
Imports System.IO
Imports System.Security.Permissions
Public Sub ReadTest()
Dim sr As StreamReader = New StreamReader("c:\test.txt")
sr.Close()
End Sub
Public Sub WriteTest()
Dim sw As StreamWriter = New StreamWriter("c:\test.txt")
sw.Close()
End Sub
<FileIOPermission(SecurityAction.PermitOnly, Read:="C:\test.txt")> _
Public Sub DoneAll()
ReadTest()
WriteTest()
End Sub
Public Sub Main()
Try
Console.WriteLine("Tentative de lecture")
ReadTest()
Console.WriteLine("Tentative d'criture")
WriteTest()
Console.WriteLine("Opration groupe")
DoneAll()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Console.Read()
End Sub
Date
35
//C#
using System.IO;
using System.Security.Permissions;
public static void ReadTest()
{
StreamReader sr = new StreamReader(@"C:\test.txt");
sr.Close();
}
public static void WriteTest()
{
StreamWriter sr = new StreamWriter(@"C:\test.txt");
sr.Close();
}
[FileIOPermission(SecurityAction.PermitOnly, Read="C:\test.txt")]
public static void DoneAll()
{
ReadTest();
WriteTest();
}
public static void Main(string[] args)
{
try
{
Console.WriteLine("Tentative de lecture");
ReadTest();
Console.WriteLine("Tentative d'criture");
WriteTest();
Console.WriteLine("Opration groupe");
DoneAll();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
Tentative de lecture
Tentative d'criture
Opration groupe
chec de la demande d'autorisation de type 'System.Security.Permissions.FileIOPe
rmission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c56193
4e089'.
Nous constatons quaucune exception nest leve si nous passons par lune des mthodes
ReadTest ou WriteTest. En revanche, si nous appelons la mthode DoneAll, laccs en criture
chouera.
Le rsultat aurait t strictement identique si nous avions remplac
"SecurityAction.PermitOnly, Read" par "SecurityAction.Deny, Write ". La seule
diffrence est que dans ce cas-ci, nous n'autorisons que la lecture et dans l'autre, nous interdisons
l'criture.
Date
36
Date
37
//C#
Imports System.IO
Imports System.Security.Permissions
Imports System.Security
Dim permissions As PermissionSet = New
PermissionSet(PermissionState.None)
permissions.AddPermission(New
FileIOPermission(FileIOPermissionAccess.Write, "C:\test.txt"))
permissions.AddPermission(New
FileIOPermission(FileIOPermissionAccess.Write, "C:\test1.txt"))
permissions.Demand()
//C#
using System.Security.Permissions;
using System.IO;
using System.Security;
PermissionSet permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new
FileIOPermission(FileIOPermissionAccess.Write, @"C:\test.txt"));
permissions.AddPermission(new
FileIOPermission(FileIOPermissionAccess.Write, @"C:\test1.txt"));
permissions.Demand();
Il peut tre intressant galement de transformer lobjet PermissionSet en XML pour pouvoir
limporter ensuite dans dautres mthodes. Pour cela vous devrez utiliser la mthode ToXml. Voici ce
qui ressort si nous convertissons le PermissionSet ci-dessus en XML :
<PermissionSet class="System.Security.PermissionSet"version="1">
<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Write="C:\test.txt;C:\test1.txt"/>
</PermissionSet>
Note : Toute classe base sur CodeAccessPermission possde galement les mthodes ToXml et
FromXml.
Date
38
Note : Aucun exemple ne peut tre facilement fourni avec LinkDemand. En effet, LinkDemand
est plus complexe illustrer et il agit au moment de la compilation JIT plutt qu'a l'excution du
programme.
Voici un exemple avec Assert dans lequel nous appelons 2 mthodes qui tentent une criture
sur un fichier dont l'accs est interdit en criture :
'VB
<FileIOPermission(SecurityAction.Deny, Write:="C:\test.txt")> _
Public Sub Main()
Try
Console.WriteLine("Tentative d'opration groupe")
DoneAll()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Try
Console.WriteLine("Ecriture a partir de Main")
Dim sw As StreamWriter = New StreamWriter("c:\test.txt")
sw.Close()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Console.Read()
End Sub
Public Sub WriteTest()
Dim sw As StreamWriter = New StreamWriter("c:\test.txt")
sw.Close()
End Sub
<FileIOPermission(SecurityAction.Assert, Write:="C:\test.txt")> _
Public Sub DoneAll()
Dim sw As StreamWriter = New StreamWriter("c:\test.txt")
sw.Close()
WriteTest()
End Sub
Date
39
//C#
[FileIOPermission(SecurityAction.Deny, Write="C:\test.txt")]
public static void Main(string[] args)
{
try {
Console.WriteLine("Tentative d'opration groupe");
DoneAll();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
try {
Console.WriteLine("Ecriture a partir de Main");
StreamWriter sw = new StreamWriter(@"C:\test.txt");
sw.Close();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
Console.Read();
}
public static void WriteTest()
{
StreamWriter sr = new StreamWriter(@"C:\test.txt");
sr.Close();
}
[FileIOPermission(SecurityAction.Assert, Write="C:\test.txt")]
public static void DoneAll()
{
StreamWriter sw = new StreamWriter(@"C:\test.txt");
sw.Close();
WriteTest();
}
40
Date
41
4.1 Authentification
Le Framework .NET propose deux classes permettant de reprsenter un utilisateur ou un
groupe dutilisateur. Grce ces deux classes nous allons pouvoir couvrir les besoins basiques de
lauthentification.
Ces
deux
classes
se
trouvent
dans
lespace
de
nom
System.Security.Principal.
Note : Ces deux classes ne fonctionnent que sous un environnement Windows.
4.1.1
Date
42
Nom : SCHMAC\Paul
4.1.2
Date
43
//C#
static void Main()
{
WindowsIdentity IdentiteUtilisateur = WindowsIdentity.GetCurrent();
WindowsPrincipal GroupeUtilisateur = new
WindowsPrincipal(IdentiteUtilisateur);
}
Date
44
'VB
Sub Main()
Dim IdentiteUtilisateur As WindowsIdentity =
WindowsIdentity.GetCurrent()
Dim GroupeUtilisateur = New WindowsPrincipal(IdentiteUtilisateur)
If (GroupeUtilisateur.IsInRole(WindowsBuiltInRole.Administrator))
Then
Console.WriteLine(IdentiteUtilisateur.Name + " fait partie
des Administrateurs")
End If
If (GroupeUtilisateur.IsInRole("Utilisateurs")) Then
Console.WriteLine(IdentiteUtilisateur.Name + " fait partie
des Utilisateurs locaux")
End If
If (GroupeUtilisateur.IsInRole("TEST\Utilisateurs")) Then
Console.WriteLine(IdentiteUtilisateur.Name + " fait partie
des Utilisateurs du domaine TEST")
End If
End Sub
//C#
Console.Read()
static
End Subvoid Main()
{
WindowsIdentity IdentiteUtilisateur = WindowsIdentity.GetCurrent();
WindowsPrincipal GroupeUtilisateur = new
WindowsPrincipal(IdentiteUtilisateur);
if (GroupeUtilisateur.IsInRole(WindowsBuiltInRole.Administrator))
Console.WriteLine(IdentiteUtilisateur.Name + " fait partie des
Administrateurs");
if (GroupeUtilisateur.IsInRole(@"Utilisateurs"))
Console.WriteLine(IdentiteUtilisateur.Name + " fait partie des
Utilisateurs locaux");
if (GroupeUtilisateur.IsInRole(@"TEST\Utilisateurs"))
Console.WriteLine(IdentiteUtilisateur.Name + " fait partie des
Utilisateurs du domaine TEST");
Console.Read();
}
Date
45
4.1.4
Authentification gnrique
Avec WindowsIdentity, nous avons cre un objet reprsentant lidentit dun utilisateur
Windows. WindowsPrincipal reprsentait lui les groupes utilisateurs auquel lutilisateur
appartient. Il y a plusieurs autres types dutilisateurs et de groupes dutilisateurs que vous pouvez
avoir besoin de reprsenter. Dans la plupart des cas, vous devrez crer vos propres classes
implmentant IIdentity et IPrincipal. Le Framework .NET fournit malgr tout deux autres
classes permettant de reprsenter utilisateur et groupe dutilisateurs : GenericIdentity et
GenericPrincipal.
Ces deux classes permettent de crer des utilisateurs virtuels afin de grer facilement les
droits dune application simple. Voici un exemple de cration des objets GenericIdentity et
GenericPrincipal :
'VB
Sub Main()
Dim utilisateur As GenericIdentity = New GenericIdentity("Toto",
"Biometrie")
Dim roles() As String = New String() {"Utilisateurs",
"Administrateurs"}
Dim GroupeGenerique As GenericPrincipal = New
GenericPrincipal(utilisateur, roles)
End Sub
//C#
static void Main()
{
GenericIdentity utilisateur = new GenericIdentity("Toto",
"Biometrie");
string[] roles = new string[] { "Utilisateurs", "Administrateurs" };
GenericPrincipal GroupeGenerique = new GenericPrincipal(utilisateur,
roles);
}
Dabord nous crons lobjet GenericIdentity, nous mettons en paramtre son nom
dutilisateur, et la mthode dauthentification.
Ensuite nous instancions lobjet GenericPrincipal, nous passons en paramtre lobjet
GenericIdentity prcdent, et un tableau des rles auquel il appartient, Users et Administrators.
Date
46
Si vous voulez maintenant faire en sorte que les paramtres de scurit du Thread soient
associs cet utilisateur gnrique, il suffit de placer votre identit gnrique dans la proprit
CurrentPrincipal du thread :
'VB
Sub Main()
Dim utilisateur As GenericIdentity = New GenericIdentity("Toto",
"Biometrie")
Dim roles() As String = New String() {"Utilisateurs",
"Administrateurs"}
Dim GroupeGenerique As GenericPrincipal = New
GenericPrincipal(utilisateur, roles)
Thread.CurrentPrincipal = GroupeGenerique
Console.WriteLine(Thread.CurrentPrincipal.Identity.Name)
Console.Read()
End Sub
//C#
static void Main()
{
GenericIdentity utilisateur = new GenericIdentity("Toto",
"Biometrie");
string[] roles = new string[] { "Users", "Administrators" };
GenericPrincipal GroupeGenerique = new GenericPrincipal(utilisateur,
roles);
Thread.CurrentPrincipal = GroupeGenerique;
Console.WriteLine(Thread.CurrentPrincipal.Identity.Name);
Console.Read()
}
Toto
Nous associons notre objet GenericPrincipal Thread.CurrentPrincipal et pour
vrifier, on affiche Identity.Name.
Date
47
4.2 Autorisation
Dans le processus de scurisation des donnes, lautorisation est une phase cl de laccs aux
donnes. En effet, sans elle, il vous sera impossible davoir accs une partie des ressources.
Le .NET Framework vous donne la possibilit de vrifier que lutilisateur qui excute votre code
possde bien le bon rle (autrement dit, quil adhre au groupe dutilisateur ayant les droits
suffisants pour effectuer cette opration). Pour cela, vous utiliserez soit la classe PrincipalPermission
(pour le test de faon imprative) soit lattribut PrincipalPermission (pour le test de faon
dclarative).
Ces
deux
lments
se
trouvent
dans
l'espace
de
nom
System.Security.Permissions.
En ce qui concerne la mthode dclarative, vous pouvez spcifier les paramtres suivant :
Name : Reprsente le nom complet de l'entit vrifier. Par exemple, si nous
souhaitons autoriser l'utilisateur "Jean" sur la machine "Pc-Familial", le nom complet
serait "Pc-Familial\Jean" ("Pc-Familial" reprsente le domaine dans lequel se trouve la
machine. Si vous vous authentifiez sur un rseau portant un nom de domaine, vous
devrez spcifier le domaine suivi du login de l'utilisateur)
Authenticated : Spcifie un boolen indiquant si l'utilisateur doit tre authentifi ou
non.
Role : Indique le nom du groupe d'utilisateur dans lequel on doit se trouver pour
correspondre aux critres de recherche.
SecurityAction : Indique l'action de scurit entreprendre (demande, interdiction, )
Si vous prfrez utiliser la faon imprative, les constructeurs de la classe PrincipalPermission
vous permettent de spcifier :
Name : Le nom d'utilisateur (comme pour la mthode dclarative)
Role : Le nom du groupe d'utilisateur (comme pour la mthode dclarative)
Authenticated : La restriction d'authentification (comme pour la mthode dclarative)
Ou alors l'un des valeurs de l'numration PermissionState. Cette numration vous fourni
deux valeurs :
None : Qui indique que l'utilisateur n'a aucun accs aux ressources
Unrestricted : Qui indique que l'utilisateur a un accs total aux ressources.
Date
48
Dans le code suivant, nous avons cr une mthode qui a besoin quun utilisateur authentifi
et ayant les droits dadministration excute lapplication. Si lutilisateur courant ne respecte pas lune
de ces conditions, une exception sera leve :
VB
Imports System.Security.Permissions
Sub Main()
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsP
rincipal)
Try
Admin()
Catch ex As Exception
Console.WriteLine("Autorisation refuse" + vbNewLine +
ex.Message)
End Try
Console.Read()
End Sub
<PrincipalPermission(SecurityAction.Demand, Authenticated:=True,
Role:="Administrateurs")> _
Public Sub Admin()
Console.WriteLine("Autorisation accorde!")
End Sub
//C#
using System.Security.Permissions;
static void Main()
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincip
al);
try
{
Admin();
}
catch (Exception ex)
{
Console.WriteLine("Autorisation refuse\n" + ex.Message);
}
Console.Read();
}
[PrincipalPermission(SecurityAction.Demand, Authenticated=true,
Role="Administrateurs")]
public static void Admin()
{
Console.WriteLine("Autorisation accorde!");
}
Date
49
Dans le premier encadr, vous avez la liste des entits dont les droits sont modifis (accepts
ou refuss) sur l'lment et dans l'encadr du dessous, vous avez la liste des droits effectifs appliqus
l'entit slectionne au dessus.
Date
50
Date
51
Date
52
//C#
using System.Security.AccessControl;
using System.Security.Principal;
using System.IO;
static void Main(string[] args)
{
string fichier = @"C:\test.txt";
FileSecurity secu = new FileSecurity(fichier,
AccessControlSections.All);
AuthorizationRuleCollection dacl =
secu.GetAccessRules(true,true,typeof(NTAccount));
foreach(FileSystemAccessRule ar in dacl)
Console.WriteLine(ar.IdentityReference.Value + " a le(s) droit(s)
" + ar.FileSystemRights.ToString());
FileSystemAccessRule ndacl = new FileSystemAccessRule("Utilisateurs",
FileSystemRights.Delete | FileSystemRights.Modify,
AccessControlType.Allow);
secu.AddAccessRule(ndacl);
File.SetAccessControl(fichier, secu);
Console.Read();
}
Date
53
Dans l'exemple, vous aurez pu constater que lorsqu'on demande rcuprer la liste DACL ou
SACL, trois paramtres sont ncessaires. Les deux premiers indiquent respectivement si la recherche
doit inclure les droits spcifiques l'lment et les droits hrits du conteneur parent. Le troisime
paramtre est un objet de type Type reprsentant le "formatage" utilis pour reprsenter les entits.
Vous ne pouvez pas y passer n'importe quel type! Vous ne pourrez utiliser que :
Le type System.Security.Principal.NTAccess, pour obtenir une
reprsentation sous forme de texte des entits.
Le type System.Security.Principal.SecurityIdentifier, permettant
d'obtenir une reprsentation en utilisant les identifiants numriques des entits (SID).
Important : Pour pouvoir modifier les droits d'accs une ressource, vous devez, que a
soit via le systme d'exploitation ou via le code, possder le droit de modification des
rgles de scurit. Par exemple, sous Windows Vista, vous ne pourrez pas modifier les
permissions sur C:\Windows tant que vous tes un membre du groupe Utilisateurs ou
Administrateurs!
Date
54
Date
55
Dans l'exemple ci-dessous, nous calculons une empreinte SHA256 protge avec une cl et
une autre non protge.
'VB
Imports System.Security.Cryptography
Imports System.Text
Imports System.IO
Sub Main()
Dim rfc As Rfc2898DeriveBytes = New Rfc2898DeriveBytes("Mot de
passe", 12)
Dim hsha256 As HMACSHA256 = New HMACSHA256(rfc.GetBytes(64))
Dim sha256 As SHA256Managed = New SHA256Managed()
Dim b() As Byte = Encoding.Unicode.GetBytes("Phrase Hache")
hsha256.ComputeHash(b)
sha256.ComputeHash(b)
Console.WriteLine(hsha256.HashName + " gnre l'empreinte " +
Convert.ToBase64String(hsha256.Hash) + " protge par la cl " +
Convert.ToBase64String(hsha256.Key))
Console.WriteLine("SHA256 gnre l'empreinte " +
Convert.ToBase64String(sha256.Hash))
Console.Read()
End Sub
//C#
using System.Security.Cryptography;
using System.Text;
using System.IO;
static void Main(string[] args)
{
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes("Mot de passe", 12);
HMACSHA256 hsha256 = new HMACSHA256(rfc.GetBytes(64));
SHA256Managed sha256 = new SHA256Managed();
byte[] b = Encoding.Unicode.GetBytes("Phrase Hache");
hsha256.ComputeHash(b);
sha256.ComputeHash(b);
Console.WriteLine(hsha256.HashName + " gnre l'empreinte " +
Convert.ToBase64String(hsha256.Hash) + " protge par la cl " +
Convert.ToBase64String(hsha256.Key));
Console.WriteLine("SHA256 gnre l'empreinte " +
Convert.ToBase64String(sha256.Hash));
Console.Read();
}
Date
56
Lors de la compilation, nous constatons que l'empreinte protge par mot de passe est
toujours diffrente de la prcdente. Ceci s'explique par le fait que nous utilisons la classe
Rfc2898DeriveBytes qui se charge de gnrer une cl pseudo-alatoire en se basant sur la phrase
passe en argument. L'empreinte calcule en utilisant SHA256 seul est toujours la mme.
SHA256 gnre l'empreinte tW5Ij4Lr32uJBvZD1ezSI5yyg6p4R4E1aUcyrNyW2PI= protge par la cl
bEB8lHiuBb+VpeD2hKZck3BV1Xe/ap+OhGqUPCo2kb00gGJhrfLmT2/BaiaMWqAhZprrg
9Rdtnc38ZaIWmpDcw==
SHA256 gnre l'empreinte qUF3tT1eV8ojg8l8H//ShhoAUEAPUVRj4e4UIlHnF5k=
Mme s'il est trs peu probable que plusieurs donnes diffrentes aient la mme empreinte, il
faut veiller bien choisir l'algorithme de calcul en fonction du niveau de scurit requis. Par exemple,
l'empreinte MD5 commence montrer des faiblesses. Pour des applications demandant un haut
niveau de scurit, prfrez les algorithmes SHA256, 384
Date
57
Cet exemple parat plus complexe quil ne lest vraiment. Nous commenons par crer notre
chaine transformer en cl et notre salt. La chane est un string et le salt un tableau doctets.
Ensuite nous crons notre objet de type Rfc2898DeriveBytes en passant au constructeur notre
chane et notre salt.
Enfin nous instancions un objet reprsentant un algorithme de chiffrement que nous verrons
dans la partie suivante. Ce quil faut en retenir se trouve dans la dernire ligne : Nous rcuprons
Date
58
grce GetBytes la cl et lassocions notre algorithme. Pour rcuprer une cl de la bonne taille,
nous passons en paramtre la taille dsire, ici AES.KeySize reprsente la taille de la cl que ncessite
notre algorithme en bits, que nous divisons par 8 pour obtenir la taille en octets.
Date
59
6.2.2
Date
60
Voici maintenant les principaux membres de ces classes qui sont tous hrits de
System.Security.Cryptography.SymmetricAlgorithm :
Membres
Description
Permet dobtenir ou de dfinir la cl secrte. La cl est gnre
automatiquement si aucune nest spcifie.
KeySize
Permet dobtenir ou de dfinir la taille de la cl secrte en bits. Vous
naurez normalement pas besoin de redfinir cette proprit car le
runtime choisit toujours la taille ayant le meilleur rapport
rapidit/scurit.
LegalKeySizes
Reprsente un tableau des tailles des cls secrtes utilisables par
lalgorithme.
Mode
Permet dobtenir ou de dfinir le mode de fonctionnement de
lalgorithme. Pour dfinir le mode de fonctionnement, vous pourrez
utiliser les valeurs de lnumration CipherMode.
IV
Permet de dfinir ou dobtenir le vecteur dinitialisation du
chiffrement/dchiffrement. Ce vecteur est un ensemble de d'octets
utiliss pour raliser le chiffrement du premier paquet d'octets
chiffrer. Voir cet article pour plus de dtails.
CreateDecryptor
Cre un objet permettant le dchiffrement de donnes. Lobjet est de
type ICryptoTransform.
CreateEncryptor
Cre un objet permettant le chiffrement de donnes. Lobjet est de type
ICryptoTransform.
GenerateKey
Gnre une nouvelle cl secrte, vous pourrez appeler cette mthode si
vous souhaitez changer votre cl secrte.
GenerateIV
Gnre un nouveau vecteur dinitialisation.
ValidKeySize
Dtermine si la taille de la cl spcifie est valide pour lalgorithme
choisi.
Afin de pouvoir dchiffrer une donne, vous devrez crer un objet possdant la mme cl, le
mme mode de chiffrement et le mme IV que pour le chiffrement.
Key
Maintenant que nous avons vu quelques bases sur le chiffrement symtrique, nous allons
pouvoir comprendre comment tout cela fonctionne grce un exemple.
Date
61
'VB
Imports System.Security.Cryptography
Imports System.IO
Imports System.Text
Sub Main()
'(1)
Dim chaine As String = "MotDePasse"
Dim salt() As Byte = Encoding.ASCII.GetBytes("CeciEstUnSalt")
Dim cle As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(chaine,
salt)
Dim AES As RijndaelManaged = New RijndaelManaged()
AES.Key = cle.GetBytes(AES.KeySize / 8)
Dim phrase As String = "Cette phrase va tre chiffre puis
dchiffre"
Dim fichier As String = "C:\test.txt"
'(2)
Dim encryptor As ICryptoTransform = AES.CreateEncryptor(AES.Key,
AES.IV)
'(3)
Dim fichierSortant As FileStream = New FileStream(fichier,
FileMode.Create, FileAccess.Write)
Dim chiffre As CryptoStream = New CryptoStream(fichierSortant,
encryptor, CryptoStreamMode.Write)
Dim ecris As StreamWriter = New StreamWriter(chiffre)
'(4)
ecris.Write(phrase)
ecris.Close()
'(5)
Dim fichierEntrant As FileStream = New FileStream(fichier,
FileMode.Open, FileAccess.Read)
Dim decryptor As ICryptoTransform = AES.CreateDecryptor(AES.Key,
AES.IV)
Dim dechiffre As CryptoStream = New CryptoStream(fichierEntrant,
decryptor, CryptoStreamMode.Read)
Dim lis As StreamReader = New StreamReader(dechiffre)
'(6)
Console.WriteLine(lis.ReadToEnd())
lis.Close()
Console.Read()
End Sub
Date
62
//C#
using System.Security.Cryptography;
using System.IO;
using System.Text;
public static void Main(string[] args)
{
//(1)
string chaine = "MotDePasse";
byte[] salt = Encoding.ASCII.GetBytes("CeciEstUnSalt");
Rfc2898DeriveBytes cle = new Rfc2898DeriveBytes(chaine, salt);
RijndaelManaged AES = new RijndaelManaged();
AES.Key = cle.GetBytes(AES.KeySize / 8);
string phrase = "Cette phrase va tre chiffre puis dchiffre";
string fichier = @"C:\test.txt";
//(2)
ICryptoTransform encryptor = AES.CreateEncryptor(AES.Key, AES.IV);
//(3)
FileStream fichierSortant = new FileStream(fichier, FileMode.Create,
FileAccess.Write);
CryptoStream chiffre = new CryptoStream(fichierSortant, encryptor,
CryptoStreamMode.Write);
StreamWriter ecris = new StreamWriter(chiffre);
//(4)
ecris.Write(phrase);
ecris.Close();
//(5)
FileStream fichierEntrant = new FileStream(fichier, FileMode.Open,
FileAccess.Read);
ICryptoTransform decryptor = AES.CreateDecryptor(AES.Key, AES.IV);
CryptoStream dechiffre = new CryptoStream(fichierEntrant, decryptor,
CryptoStreamMode.Read);
StreamReader lis = new StreamReader(dechiffre);
//(6)
Console.WriteLine(lis.ReadToEnd());
lis.Close();
Console.Read();
}
63
Date
64
6.3.1
RSACryptoServiceProvider
Cette classe donne accs au cryptage RSA. Cette mthode de cryptage vous permettra
d'utiliser des cls dont la taille peut aller de 384 bits 16384 bits! En voici les principaux membres :
Membres
Description
Clear
Permet de vider toutes ressources en mmoire utilises par le
RSACryptoServiceProvider.
Decrypt
Permet de dcrypter des donnes cryptes par une cl publique.
Encrypt
Permet d'encrypter des donnes en utilisant la cl publique.
ExportParameters
Exporte les paramtres de cls publiques et/ou prives dans une
structure RSAParameters.
FromXmlString
Importe les paramtres de cls partir d'une chane XML.
ImportParameters
Importe les paramtres de cls partir d'une structure
RSAParameters.
SignData
Cre une signature numrique pour un fichier en deux tapes : dabord
en gnrant un hash et ensuite en gnrant une signature base sur ce
hash.
SignHash
Permet de signer l'empreinte de hash spcifie en utilisant la cl prive.
ToXmlString
Exporte les paramtres de cls sous forme de chaine XML.
VerifyData
Vrifie une signature numrique en la comparant celle produite par
SignData.
VerifyHash
Vrifie une signature numrique base sur le hash du fichier.
PersistKeyInCsp
Indique si le fournisseur de cryptage RSA doit stocker la cl prive dans
le service de chiffrement CryptoAPI*.
UseMachineKeyStore
Proprit statique indiquant si le fournisseur de cryptage RSA doit
stocker la cl prive dans le magasin de cls de l'ordinateur.
PublicOnly
Contient un boolen indiquant si le service de cryptage RSA actuel ne
contient qu'une cl publique.
*Toute machine Windows est quipe d'un service de chiffrement qui permet de stocker les
cls prives dans une section propre l'utilisateur actuel de la base de registre en plus de fournir les
mthodes de chiffrement standard. Vous aurez plus d'informations en visitant la section CryptoAPI
de MSDN ou encore un article concernant le stockage des cls du service de chiffrement.
Voici un exemple concret de l'utilisation du service de cryptage RSA. Cet exemple a t fait de
telle sorte que l'on puisse facilement le transposer sur un dialogue scuris de donnes via un rseau
par exemple.
Nous avons deux mthodes : FournisseurDeDonnees et Destinataire. FournisseurDeDonnees
reprsente la machine que l'on souhaite contacter distance. Elle prendra en paramtre la cl
publique que le destinataire aura prit soin de gnrer avant d'envoyer sa requte.
La mthode Destinataire doit tre appele deux fois : Une premire fois sans arguments ce qui
permettra de gnrer la cl prive et la cl publique et une seconde fois avec la cl prive en
argument afin de lancer le dcryptage des donnes enregistres dans le fichier C:\test.bin.
Afin d'viter d'utiliser des stockages du service de chiffrement de faon inutile, nous allons
utiliser le stockage des cls sous formes d'objets RSAParameters. Dans le cas o vous auriez besoin
de sauvegarder les cls prives dans le service de chiffrement, il vous suffira de crer une instance de
la classe CspParameters en oubliant pas de spcifier un nom de conteneur (via la proprit
KeyContainerName),
de passer votre objet dans le constructeur de la classe
RSACryptoServiceProvider et de placer la proprit PersistKeyInCsp True :
Date
65
VB
Imports System.Security.Cryptography
Imports System.IO
Imports System.Text
Dim taillecle As Integer
Dim chemin_fichier As String
Dim _clepublic, _cleprivee As RSAParameters
Sub Main()
taillecle = 384
chemin_fichier = "C:\test.bin"
Destinataire()
FournisseurDeDonnees(_clepublic)
Destinataire(_cleprivee)
Console.Read()
End Sub
'Mthode gnrant les cls prives et publiques
Public Sub Destinataire()
Dim keygen As RSACryptoServiceProvider = New
RSACryptoServiceProvider(taillecle)
_clepublic = keygen.ExportParameters(False)
_cleprivee = keygen.ExportParameters(True)
Console.WriteLine("Destinataire a gnr les cls suivantes:" +
vbNewLine + "Cle prive: " + keygen.ToXmlString(True) + vbNewLine +
vbNewLine + "Cle publique: " + keygen.ToXmlString(False) + vbNewLine)
keygen.Clear()
End Sub
'Mthode de dcryptage des donnes l'aide de la cl prive
Public Sub Destinataire(ByVal cleprivee As RSAParameters)
Dim fichier As FileStream = New FileStream(chemin_fichier,
FileMode.Open)
Dim octets(fichier.Length - 1) As Byte
fichier.Read(octets, 0, fichier.Length)
fichier.Close()
Console.WriteLine("Texte avant dcryptage: {0}",
Encoding.Unicode.GetString(octets))
Dim decrypt As RSACryptoServiceProvider = New
RSACryptoServiceProvider(taillecle)
decrypt.ImportParameters(cleprivee)
Dim finaltxt As StringBuilder = New StringBuilder()
Dim o() As Byte = decrypt.Decrypt(octets, False)
Console.WriteLine("Texte aprs dcryptage: {0}",
Encoding.Unicode.GetString(o))
End Sub
Date
66
VB - Suite
'Mthode cryptant les donnes en utilisant la cl publique
Public Sub FournisseurDeDonnees(ByVal clepublic As RSAParameters)
Dim encryptor As RSACryptoServiceProvider = New
RSACryptoServiceProvider(taillecle)
encryptor.ImportParameters(clepublic)
Console.WriteLine("Fournisseur de donnes." + vbNewLine + "Cle
prive disponible?" + (Not encryptor.PublicOnly).ToString() + vbNewLine)
Dim fichier As FileStream = New FileStream(chemin_fichier,
FileMode.Truncate)
Dim o() As Byte =
encryptor.Encrypt(Encoding.Unicode.GetBytes("Donnees."), False)
For Each b As Byte In o
fichier.WriteByte(b)
Next
fichier.Flush()
fichier.Close()
encryptor.Clear()
End Sub
Date
67
//C#
using System.Security.Cryptography
using System.IO
using System.Text
private static int taillecle;
private static string chemin_fichier;
private static RSAParameters _clepublic;
private static RSAParameters _cleprivee;
static void Main(string[] args)
{
taillecle = 384;
chemin_fichier = @"C:\test.bin";
Destinataire();
FournisseurDeDonnees(_clepublic);
Destinataire(_cleprivee);
Console.Read();
}
//Mthode gnrant les cls prives et publiques
public static void Destinataire()
{
RSACryptoServiceProvider keygen = new
RSACryptoServiceProvider(taillecle);
_clepublic = keygen.ExportParameters(false);
_cleprivee = keygen.ExportParameters(true);
Console.WriteLine("Destinataire a gnr les cls suivantes:\n" +
"Cle prive: " + keygen.ToXmlString(true) + "\n\n"
+
"Cle publique: " + keygen.ToXmlString(false) +
"\n");
keygen.Clear();
}
Date
68
//C# - Suite
//Mthode cryptant les donnes en utilisant la cl publique
public static void FournisseurDeDonnees(RSAParameters clepublic)
{
//Cr l'outil d'encryption des donnes
RSACryptoServiceProvider encryptor = new
RSACryptoServiceProvider(taillecle);
encryptor.ImportParameters(clepublic);
Console.WriteLine("Fournisseur de donnes.\n" + "Cle prive
disponible?" + (!encryptor.PublicOnly).ToString() + "\n");
//Ecrit les donnes cryptes dans le fichier
FileStream fichier = new FileStream(chemin_fichier,
FileMode.Truncate);
byte[] o = encryptor.Encrypt(Encoding.Unicode.GetBytes("Donnees."),
false);
foreach(byte b in o)
fichier.WriteByte(b);
fichier.Flush();
fichier.Close();
encryptor.Clear();
}
Pour excuter correctement ce programme, vous devrez d'abord crer le fichier C:\test.bin.
Lorsque vous excutez ce programme, vous devriez obtenir quelque chose de similaire a
dans la console :
Destinataire a gnr les cls suivantes:
Cle prive: <RSAKeyValue><Modulus>0H4COsdum97UQNSM0cZehGDaMrXA7rMYb3RhJGdDmvKHID
NNpnSEOtULcHDmN8AF</Modulus><Exponent>AQAB</Exponent><P>7+me3vc7g479qh6bhEMpdipt
lD0KGCqj</P><Q>3nkFX8qU2EDrZPIk3PDXIkXXdoopR303</Q><DP>AJjBJ2bQBBS/9sNauap9GOkkG
qFIPCUn</DP><DQ>z837Vx7DKbx6JDCKflX4nere97rWFBDB</DQ><InverseQ>GaotrImHs4dXSjz0A
1/V/yKTYT1JnqYn</InverseQ><D>m7vT/IXlaAaM8xQRT8xl42nY8pHy2BnrqEpwl/T63ckE2vW9ImJ
rMQ0naN7WWTXN</D></RSAKeyValue>
Cle publique: <RSAKeyValue><Modulus>0H4COsdum97UQNSM0cZehGDaMrXA7rMYb3RhJGdDmvKH
IDNNpnSEOtULcHDmN8AF</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
Fournisseur de donnes.
Cle prive disponible?False
Texte avant dcryptage: ????????????????????????
Texte aprs dcryptage: Donnees.
Date
69
Si vous ouvrez le fichier C:\test.bin, vous devriez avoir un texte totalement incomprhensible :
Afin de dterminer quelle(s) cl(s) sera exporte(s) lors de l'appel une mthode
d'exportation, vous pouvez en gnral passer en argument un boolen indiquant :
True : la cl prive sera exporte en plus de la cl publique.
False : Seule la cl publique sera exporte.
Lorsque vous appelez une des mthodes de cryptage ou de dcryptage, vous devez spcifier
deux paramtres :
Un tableau d'octets contenant les donnes crypter.
Un boolen indiquant si le service de chiffrement utilisera PKCS#1 v1.5
(essentiellement pour des soucis de rtrocompatibilits puisque disponible depuis plus
longtemps, il est dconseill de nos jours car il prsente de nombreuses faiblesses) ou
OAEP (disponible uniquement sur des machines XP ou plus rcentes).
Vous aurez constat que dans la cl prive au format XML, plusieurs balises sont cres.
Chacune de ces balises reprsentent une partie des donnes permettant de gnrer les cls utilises
(pour savoir de quelle faon sont gnres les cls, je vous renvoi vers le lien concernant l'algorithme
RSA. Sachez juste ventuellement que "Modulus" est le module de chiffrement n et "Exponent" est
l'exposant de chiffrement e).
6.3.2
DSACryptoServiceProvider
Cette classe vous donne accs aux algorithmes de calcul DSA. Elle possde les mmes
membres que RSACryptoServiceProvider mais ne dispose pas des mthodes Encrypt et
Decrypt. Du fait de l'absence de ces deux mthodes, le cryptage DSA ne peut pas tre utilis
directement pour crypter des donnes. En revanche, il peut tre d'une grande utilit si vous
souhaitez implmenter un service fournissant des signatures, des cls publiques/prives et/ou des
empreintes digitales de donnes.
Date
70
Date
71
'VB
Imports System.Security.Cryptography
Imports System.IO
Sub Main()
'(1)
Dim RSA As RSACryptoServiceProvider = New
RSACryptoServiceProvider()
Dim clepublique As String = ""
Dim signatureNumerique() As Byte
'(2)
signatureNumerique = Signature(RSA, clepublique)
Console.WriteLine("La signature est : {0}",
Convert.ToBase64String(signatureNumerique))
'(3)
Verification(RSA, signatureNumerique, clepublique)
Console.Read()
End Sub
Public Function Signature(ByRef provider As RSACryptoServiceProvider,
ByRef clepublique As String) As Byte()
'(4)
Dim flux As FileStream = New FileStream("C:\test.txt",
FileMode.Open, FileAccess.Read)
Dim lecteur As BinaryReader = New BinaryReader(flux)
'(5)
Dim donnees() As Byte = lecteur.ReadBytes(CType(flux.Length,
Integer))
lecteur.Close()
flux.Close()
'(6)
clepublique = provider.ToXmlString(False)
'(7)
Return provider.SignData(donnees, New
SHA1CryptoServiceProvider())
End Function
Public Sub Verification(ByRef provider As RSACryptoServiceProvider, ByVal
signature() As Byte, ByRef clefpublique As String)
'(8)
provider.FromXmlString(clefpublique)
Dim flux As FileStream = New FileStream("C:\test.txt",
FileMode.Open, FileAccess.Read)
Dim lecteur As BinaryReader = New BinaryReader(flux)
'(9)
Dim donnees() As Byte = lecteur.ReadBytes(CType(flux.Length,
Integer))
lecteur.Close()
flux.Close()
'(10)
If (provider.VerifyData(donnees, New SHA1CryptoServiceProvider(),
signature)) Then
Console.WriteLine("La signature est vrifie")
Else
Console.WriteLine("La signature est mauvaise")
End If
End Sub
Date
72
//C#
using System.Security.Cryptography;
using System.IO;
public static void Main(string[] args)
{
//(1)
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
string clepublique = "";
byte[] signatureNumerique = null;
//(2)
signatureNumerique = Signature(ref RSA, ref clepublique);
Console.WriteLine("La signature est : {0}",
Convert.ToBase64String(signatureNumerique));
//(3)
Verification(ref RSA, signatureNumerique, ref clepublique);
Console.Read();
}
public static byte[] Signature(ref RSACryptoServiceProvider provider, ref
string clepublique)
{
//(4)
FileStream flux = new FileStream(@"C:\test.txt", FileMode.Open,
FileAccess.Read);
BinaryReader lecteur = new BinaryReader(flux);
//(5)
byte[] donnees = lecteur.ReadBytes((int)flux.Length);
lecteur.Close();
flux.Close();
//(6)
clepublique = provider.ToXmlString(false);
//(7)
return provider.SignData(donnees, new SHA1CryptoServiceProvider());
}
public static void Verification(ref RSACryptoServiceProvider provider,
byte[] signature, ref string clefpublique)
{
//(8)
provider.FromXmlString(clefpublique);
FileStream flux = new FileStream(@"C:\test.txt", FileMode.Open,
FileAccess.Read);
BinaryReader lecteur = new BinaryReader(flux);
//(9)
byte[] donnees = lecteur.ReadBytes((int)flux.Length);
lecteur.Close();
flux.Close();
//(10)
if (provider.VerifyData(donnees, new SHA1CryptoServiceProvider(),
signature))
Console.WriteLine("La signature est vrifie");
else
Console.WriteLine("La signature est mauvaise");
}
Date
73
Pour plus de clart nous avons plac des numros dans le code permettant de commenter
chaque partie.
1) Nous instancions un objet RSACryptoServiceProvider qui va nous permettre de signer et
vrifier la signature.
2) Nous appelons la mthode Signature, rcuprons sa valeur de retour puis nous laffichons. La
mthode Signature signe un fichier retourne la signature et passe par rfrence la valeur de
clepublique.
3) Nous appelons la mthode Verification qui va se charger de vrifier la signature du fichier.
4) On cre deux flux, un flux sur un fichier, et un BinaryReader utilisant le flux de fichier.
5) On lit entirement le fichier et on remplit un tableau doctets avec les informations
recueillies
6) On rcupre la cl publique sous forme XML (ici rang dans une chane de caractre)
7) On signe le fichier partir de son contenu (donnees) et avec un hash en SHA1, on retourne la
signature.
8) On rcupre la cl publique sous forme XML.
9) On lit le contenu du fichier et le range dans des tableaux doctets (mme tape que 5)
10) On vrifie la signature. A partir du contenu du fichier que lon hash grce SHA1 on cre une
nouvelle signature que l'on compare celle passe en troisime paramtre.
Voici ce qui ressort dans la console. Bien entendu la signature est diffrente d'un fichier un autre :
La signature est : LCgTxY3XYOPB3rTTLzT6dBas3x7lpwaaA2/HHaJNvcUgcHXe+EMhWKetUm9xT
v37X1+wv5PUI7Jh8KXwZ2POoHYFr3vhKFsvG31PcGCoyYKrjCkBJ9kDzdttdgAMo67xvAXl1Fxry1Vqh
9VxyT7Xvw4GPfhS96u2R0/mc3ncsBs=
La signature est vrifie
Date
74
7 Conclusion
Vous voil donc quip en matire de scurit en ce qui concerne le Framework .NET. Vous
savez dsormais comment fonctionne les rgles de scurit de la CLR et quels sont les moyens pour
prvenir les exploits de vos applications ou encore le piratage de donnes sauvegardes.
A la fin de ce chapitre, vous devriez:
Savoir comment fonctionne le CAS du Framework .NET et comment le configurer.
Avoir compris comment fonctionnent les rgles de scurit par rapport au systme
d'exploitation hte qui excutera l'assembly.
Savoir comment effectuer des demandes d'autorisations, comment en refuser que a
soit dans le code (au dessus des mthodes/classes) ou au niveau de l'assembly toute
entire.
Savoir comment grer les ACLs (Discrtionnaire ou de scurit) du systme
d'exploitation partir du code.
Connaitre les diffrentes techniques possibles pour chiffrer des donnes afin de les
protger lors de transfert ou pour les stocker long terme sur un mdia (disque dur,
cd-rom)
N'oubliez pas que la librairie MSDN peut vous tre d'une aide prcieuse pour vos
dveloppements :
Date