Problème d'utilisation pour le cryptage façon Rijndael
Le
news.microsoft.com
Bonjour,
Je suis sous VB .Net 2003 et j'utilise une classe de cryptage Rijndael qui
fonctionne parfaitement.
Mon problème est que lorsque je décrypte, il se passe très rarement un
phénomène qui fait que soit le décryptage est impossible, soit la valeur
décryptée n'est pas égale à la valeur d'origine.
Ce phénomène se produit lorsque le caractère 10 ou le caractère 13 se
retrouve dans la chaîne cryptée.
En effet, je lis mon fichier (unicode) crypté ligne par ligne, et donc, la
chaîne cryptée se retrouve dans ce cas sur 2 lignes et fausse par conséquent
le décryptage de 2 facons différentes :
Soit le caractère 10 ou 13 est le 1er caractère est dans ce cas là, le
décryptage lui même génère une erreur (car la ligne lue est vide).
Soit le caractère 10 ou 13 est dans la chaîne est dans ce cas là, le
décryptage est bien possible, mais la valeur décryptée est différente de la
valeur d'origine.
J'ai bien pensé à remplacer dans la chaîne cryptée, avant d'enregistrer dans
le fichier, les caractères 10 et 13 par, par exemple 254 et 255 (ou tout
autre caractères valides), pour, lors du décryptage, remettre à l'endroit,
mais cette bidouille cache un autre problème, si la chaîne cryptée contenait
vraiment un caractère 254 ou 255, donc cela ne convient pas.
J'ai également pensé à remplacer dans la même perspective les caratères 10
et 13 par une chaîne plus longue (ex : 240 240 242 243 244 245 et 250 251
252 253 254 255) , mais le problème reste toujours possible même si cela le
raréfie.
Bref, mon problème est que je ne sais pas comment gérer ce phénomène.
Afin de vous aider au mieux, je vous met ci-dessous la classe Rijndael que
j'utilise (je l'ai appelé Raindoll, ca se prononce comme ca), suivi d'un
petit boût de code (cryptage et décyptage d'un simple compteur) qui permet
de très bien comprendre mon problème (j'ai remplacé ma clef de cryptage
ainsi que le vecteur pour des raisons de confidentialités).
Merci d'avance pour votre aide,
Stéphane
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Public Class raindoll
' Utilitaire de cryptographie
Protected Rijndael As New RijndaelManaged ' Fournit une implémentation de
l'algorithme de Rijndael pour le cryptage et le décryptage des données
Private m_Key() As Byte ' Clé de cryptage
Private m_IV() As Byte ' Vecteur d'interruption
' Constructeur par défaut : ne fait rien
Public Sub New()
End Sub
' Constructeur qui initialise la clé de cryptage et le vecteur
d'interruption.
' Les paramètres Key et IV représentent des tableaux de 16 octets
Public Sub New(ByVal Key() As Byte, ByVal IV() As Byte)
Me.Key = Key
Me.IV = IV
End Sub
' Autre constructeur qui initialise la clé de cryptage et le vecteur
d'interruption.
' Les paramètres sKey et sIV représentent des chaînes de 8 caractères
UNICODE.
Public Sub New(ByVal sKey As String, ByVal sIV As String)
Dim ue As New UnicodeEncoding ' Servira à convertir les chaînes en tableaux
d'octets
If sKey.Length > 8 Then ' Si la chaîne est trop longue, on la tronque
sKey = sKey.Substring(0, 8)
ElseIf sKey.Length < 8 Then ' Si par contre la chaîne est trop courte, on la
complète
Dim n As Integer = 8 - sKey.Length
For i As Integer = 0 To n - 1
sKey &= i
Next
End If
If sIV.Length > 8 Then
sIV = sIV.Substring(0, 8)
ElseIf sIV.Length < 8 Then
Dim n As Integer = 8 - sIV.Length
For i As Integer = 0 To n - 1
sIV &= i
Next
End If
' Conversion des deux chaînes en tableaux d'octets
Key = ue.GetBytes(sKey)
IV = ue.GetBytes(sIV)
End Sub
' Accesseur pour la clé de cryptage
Public Property Key() As Byte()
Get
Return m_Key
End Get
Set(ByVal Value As Byte())
m_Key = Value
End Set
End Property
' Accesseur pour le vecteur d'interruption
Public Property IV() As Byte()
Get
Return m_IV
End Get
Set(ByVal Value As Byte())
m_IV = Value
End Set
End Property
' Crypte le texte reçu du flux input et dirige le resultat vers le flux
output
Public Sub Encrypt(ByVal input As Stream, ByVal output As Stream)
' L'écriture dans le flux cs produira une sortie cryptée selon l'algorithme
de Rijndael
' avec m_Key comme clé et m_IV comme vecteur d'interruption
Dim cs As New CryptoStream(output, Rijndael.CreateEncryptor(m_Key, m_IV),
CryptoStreamMode.Write)
Dim buffer(100) As Byte ' tampon utilisé pour la lecture et l'écriture
Dim n As Integer ' nombre d'octets réellement lus ou écrits
' La suite ressemble à un transfert de données entre deux flux quelconques
Do
n = input.Read(buffer, 0, 100)
cs.Write(buffer, 0, n)
Loop Until n < 100
cs.Close()
End Sub
' Décrypte le texte reçu du flux input et dirige le resultat vers le flux
output
Public Sub Decrypt(ByVal input As Stream, ByVal output As Stream)
' La lecture à partir du flux cs est précédée du décryptage des données
d'origine.
' La clé de cryptage et le vecteur d'interruption doivent être les mêmes que
' ceux utilisés lors du cryptage des données.
Dim cs As New CryptoStream(input, Rijndael.CreateDecryptor(m_Key, m_IV),
CryptoStreamMode.Read)
Dim buffer(100) As Byte
Dim n As Integer
Do
n = cs.Read(buffer, 0, 100)
output.Write(buffer, 0, n)
Loop Until n < 100
cs.Close()
End Sub
' Crypte un texte en mémoire et retourne le texte crypté
Public Function EncryptText(ByVal original As String) As String
' On crée un MemoryStream avec le texte original
Dim UE As New UnicodeEncoding
Dim msIn As New MemoryStream(UE.GetBytes(original))
' et on en crée un autre pour la sortie
Dim msOut As New MemoryStream
' Les deux flux sont transmis à la méthode encrypt
Encrypt(msIn, msOut)
msIn.Close()
' Puis, on recupère le contenu du flux de sortie
Dim encrypted As String = UE.GetString(msOut.ToArray)
msOut.Close()
' Qu'on retourne en guise de resultat
Return encrypted
End Function
' Décrypte un texte en mémoire et retourne le texte décrypté
' Le principe est analogue à celui de EncryptText
Public Function DecryptText(ByVal encrypted As String) As String
Dim UE As New UnicodeEncoding
Dim msIn As New MemoryStream(UE.GetBytes(encrypted))
Dim msOut As New MemoryStream
Decrypt(msIn, msOut)
msIn.Close()
Dim decrypted As String = UE.GetString(msOut.ToArray)
msOut.Close()
Return decrypted
End Function
' Crypte un fichier texte et produit un autre fichier texte complètement
illisible
Public Sub EncryptFile(ByVal original As String, ByVal encrypted As String)
' On obtient un flux qui représente le fichier original
Dim fsIn As New FileStream(original, FileMode.Open)
' On en obtient un autre qui représente le fichier crypté
Dim fsOut As New FileStream(encrypted, FileMode.Create)
' On trasmet les deux flux à la méthode Encrypt et le travail est fait
Encrypt(fsIn, fsOut)
fsIn.Close()
fsOut.Close()
End Sub
' Décrypte un fichier texte crypté pour reconstituer le fichier original
' Le principe est analogue à celui de EncryptFile
Public Sub DecryptFile(ByVal encrypted As String, ByVal decrypted As String)
Dim fsIn As New FileStream(encrypted, FileMode.Open)
Dim fsOut As New FileStream(decrypted, FileMode.Create)
Decrypt(fsIn, fsOut)
fsIn.Close()
fsOut.Close()
End Sub
' Crypte un texte en mémoire à destination d'un fichier sur disque
Public Sub EncryptTextToFile(ByVal original As String, ByVal filename As
String)
' On crée un MemoryStream avec le texte original
Dim UE As New UnicodeEncoding
Dim msIn As New MemoryStream(UE.GetBytes(original))
' On obtient un flux de sortie qui représente le fichier crypté
Dim fsOut As New FileStream(filename, FileMode.Create)
' On trasmet les deux flux à la méthode Encrypt et le travail est fait
Encrypt(msIn, fsOut)
msIn.Close()
fsOut.Close()
End Sub
' Décrypte un fichier texte crypté et retourne le texte original
' sous la forme d'une très longue chaîne de caractères.
' Le principe est analogue à celui de EncryptTextToFile
Public Function DecryptTextFromFile(ByVal filename As String) As String
Dim UE As New UnicodeEncoding
Dim fsIn As New FileStream(filename, FileMode.Open)
Dim msOut As New MemoryStream
Decrypt(fsIn, msOut)
fsIn.Close()
Dim decrypted As String = UE.GetString(msOut.ToArray)
msOut.Close()
Return decrypted
End Function
End Class
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Code généré par le Concepteur Windows Form "
Public Sub New()
MyBase.New()
'Cet appel est requis par le Concepteur Windows Form.
InitializeComponent()
'Ajoutez une initialisation quelconque après l'appel InitializeComponent()
End Sub
'La méthode substituée Dispose du formulaire pour nettoyer la liste des
composants.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Requis par le Concepteur Windows Form
Private components As System.ComponentModel.IContainer
'REMARQUE : la procédure suivante est requise par le Concepteur Windows Form
'Elle peut être modifiée en utilisant le Concepteur Windows Form.
'Ne la modifiez pas en utilisant l'éditeur de code.
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents TextBox_effectués As System.Windows.Forms.TextBox
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents TextBox_erreurs As System.Windows.Forms.TextBox
Friend WithEvents CheckBox_Test As System.Windows.Forms.CheckBox
Friend WithEvents Label4 As System.Windows.Forms.Label
Friend WithEvents Label5 As System.Windows.Forms.Label
Friend WithEvents Label6 As System.Windows.Forms.Label
Friend WithEvents TextBox_erreurs_décryptage As System.Windows.Forms.TextBox
Friend WithEvents TextBox_erreurs_cryptage As System.Windows.Forms.TextBox
Friend WithEvents Label7 As System.Windows.Forms.Label
Friend WithEvents TextBox_détails As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label
Me.TextBox_effectués = New System.Windows.Forms.TextBox
Me.Label2 = New System.Windows.Forms.Label
Me.TextBox_erreurs = New System.Windows.Forms.TextBox
Me.CheckBox_Test = New System.Windows.Forms.CheckBox
Me.Label4 = New System.Windows.Forms.Label
Me.Label5 = New System.Windows.Forms.Label
Me.Label6 = New System.Windows.Forms.Label
Me.TextBox_erreurs_décryptage = New System.Windows.Forms.TextBox
Me.TextBox_erreurs_cryptage = New System.Windows.Forms.TextBox
Me.TextBox_détails = New System.Windows.Forms.TextBox
Me.Label7 = New System.Windows.Forms.Label
Me.SuspendLayout()
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(8, 8)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(168, 23)
Me.Label1.TabIndex = 0
Me.Label1.Text = "Tests de cryptage / décryptage"
'
'TextBox_effectués
'
Me.TextBox_effectués.Location = New System.Drawing.Point(160, 32)
Me.TextBox_effectués.Name = "TextBox_effectués"
Me.TextBox_effectués.ReadOnly = True
Me.TextBox_effectués.TabIndex = 1
Me.TextBox_effectués.Text = ""
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(8, 32)
Me.Label2.Name = "Label2"
Me.Label2.TabIndex = 2
Me.Label2.Text = "Effectués"
'
'TextBox_erreurs
'
Me.TextBox_erreurs.Location = New System.Drawing.Point(160, 72)
Me.TextBox_erreurs.Name = "TextBox_erreurs"
Me.TextBox_erreurs.ReadOnly = True
Me.TextBox_erreurs.TabIndex = 3
Me.TextBox_erreurs.Text = ""
'
'CheckBox_Test
'
Me.CheckBox_Test.Appearance = System.Windows.Forms.Appearance.Button
Me.CheckBox_Test.Location = New System.Drawing.Point(80, 608)
Me.CheckBox_Test.Name = "CheckBox_Test"
Me.CheckBox_Test.TabIndex = 5
Me.CheckBox_Test.Text = "Teste !"
Me.CheckBox_Test.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'Label4
'
Me.Label4.Location = New System.Drawing.Point(8, 64)
Me.Label4.Name = "Label4"
Me.Label4.Size = New System.Drawing.Size(144, 40)
Me.Label4.TabIndex = 6
Me.Label4.Text = "Valeur décryptée différente de la valeur d'origine"
'
'Label5
'
Me.Label5.Location = New System.Drawing.Point(8, 144)
Me.Label5.Name = "Label5"
Me.Label5.Size = New System.Drawing.Size(128, 23)
Me.Label5.TabIndex = 7
Me.Label5.Text = "Décryptage impossible"
'
'Label6
'
Me.Label6.Location = New System.Drawing.Point(8, 112)
Me.Label6.Name = "Label6"
Me.Label6.Size = New System.Drawing.Size(120, 23)
Me.Label6.TabIndex = 8
Me.Label6.Text = "Cryptage impossible"
'
'TextBox_erreurs_décryptage
'
Me.TextBox_erreurs_décryptage.Location = New System.Drawing.Point(160, 144)
Me.TextBox_erreurs_décryptage.Name = "TextBox_erreurs_décryptage"
Me.TextBox_erreurs_décryptage.ReadOnly = True
Me.TextBox_erreurs_décryptage.TabIndex = 9
Me.TextBox_erreurs_décryptage.Text = ""
'
'TextBox_erreurs_cryptage
'
Me.TextBox_erreurs_cryptage.Location = New System.Drawing.Point(160, 112)
Me.TextBox_erreurs_cryptage.Name = "TextBox_erreurs_cryptage"
Me.TextBox_erreurs_cryptage.ReadOnly = True
Me.TextBox_erreurs_cryptage.TabIndex = 10
Me.TextBox_erreurs_cryptage.Text = ""
'
'TextBox_détails
'
Me.TextBox_détails.Location = New System.Drawing.Point(8, 200)
Me.TextBox_détails.Multiline = True
Me.TextBox_détails.Name = "TextBox_détails"
Me.TextBox_détails.ReadOnly = True
Me.TextBox_détails.ScrollBars = System.Windows.Forms.ScrollBars.Both
Me.TextBox_détails.Size = New System.Drawing.Size(256, 400)
Me.TextBox_détails.TabIndex = 11
Me.TextBox_détails.Text = ""
'
'Label7
'
Me.Label7.Location = New System.Drawing.Point(8, 176)
Me.Label7.Name = "Label7"
Me.Label7.TabIndex = 12
Me.Label7.Text = "Détails"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(272, 637)
Me.Controls.Add(Me.Label7)
Me.Controls.Add(Me.TextBox_détails)
Me.Controls.Add(Me.TextBox_erreurs_cryptage)
Me.Controls.Add(Me.TextBox_erreurs_décryptage)
Me.Controls.Add(Me.Label6)
Me.Controls.Add(Me.Label5)
Me.Controls.Add(Me.Label4)
Me.Controls.Add(Me.CheckBox_Test)
Me.Controls.Add(Me.TextBox_erreurs)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.TextBox_effectués)
Me.Controls.Add(Me.Label1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub CheckBox_Test_CheckedChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles CheckBox_Test.CheckedChanged
Dim key(15) As Byte
Dim iv(15) As Byte
Dim cryptage As raindoll
Dim effectués As Integer = 0
Dim erreurs As Integer = 0
Dim erreurs_cryptage As Integer = 0
Dim erreurs_décryptage As Integer = 0
Dim fichier_tmp As String = System.IO.Path.GetTempFileName()
Dim txt_effectués, crypté, décrypté, ligne, détail As String
Dim fichier_r As System.IO.StreamReader
Dim fichier_w As System.IO.StreamWriter
Dim cryptage_ok, décryptage_ok As Boolean
If Me.CheckBox_Test.Checked Then
'Lancement du programme
'Définition de la clef de cryptage et du vecteur
For i As Byte = 0 To 15
key(i) = i
iv(i) = i
Next
cryptage = New raindoll(key, iv)
Me.CheckBox_Test.Text = "Stop !"
Me.TextBox_effectués.Text = effectués
Me.TextBox_erreurs.Text = erreurs
Me.TextBox_erreurs_cryptage.Text = erreurs_cryptage
Me.TextBox_erreurs_décryptage.Text = erreurs_décryptage
Me.TextBox_détails.Text = ""
Me.CheckBox_Test.Refresh()
While Me.CheckBox_Test.Checked Or effectués = Integer.MaxValue
effectués += 1
txt_effectués = effectués.ToString
If Math.IEEERemainder(effectués, 1000) = 0 Then
Me.TextBox_effectués.Text = txt_effectués
End If
'On crée (ou recrée en écransant) le fichier temporaire en écriture
fichier_w = New System.IO.StreamWriter(fichier_tmp, False,
System.Text.Encoding.Unicode)
Try
'On crypte le nombre de tests effectués
crypté = cryptage.EncryptText(txt_effectués)
cryptage_ok = True
Catch ex As Exception
cryptage_ok = False
End Try
If cryptage_ok Then
'On écrit le nombre crypté de tests effectués
fichier_w.WriteLine(crypté)
'Et on ferme le fichier écrit
fichier_w.Close()
'On réouvre le fichier temporaire, mais cette fois en lecture
fichier_r = New System.IO.StreamReader(fichier_tmp)
'On lit la ligne cryptée
ligne = fichier_r.ReadLine
Try
'On la décrypte
décrypté = cryptage.DecryptText(ligne)
décryptage_ok = True
Catch ex As Exception
décryptage_ok = False
End Try
If décryptage_ok Then
'On compare la chaîne décryptée avec le nombre de tests effectués
If décrypté <> txt_effectués Then
'Erreur de cryptage détectée
Me.TextBox_effectués.Text = txt_effectués
erreurs += 1
Me.TextBox_erreurs.Text = erreurs
détail = "Erreur de valeur " & erreurs & "/" & effectués & vbCrLf
détail &= "'Texte encrypté' : '" & crypté & "'" & vbCrLf
détail &= "Texte encrypté en hexa :" & vbCrLf
For Each caractère As String In crypté
détail &= Asc(caractère) & " "
Next
détail &= vbCrLf
détail &= "'Texte décrypté' : '" & décrypté & "'" & vbCrLf
détail &= "Texte décrypté en hexa :" & vbCrLf
For Each caractère As String In décrypté
détail &= Asc(caractère) & " "
Next
détail &= vbCrLf & "________________________" & vbCrLf & vbCrLf
Me.TextBox_détails.Text &= détail
End If
Else
'Une erreur s'est produite pendant le décryptage
Me.TextBox_effectués.Text = txt_effectués
erreurs_décryptage += 1
Me.TextBox_erreurs_décryptage.Text = erreurs_décryptage
détail = "Erreur de décryptage " & erreurs_décryptage & "/" & effectués &
vbCrLf
détail &= "'Texte encrypté' : '" & crypté & "'" & vbCrLf
détail &= "Texte encrypté en hexa :" & vbCrLf
For Each caractère As String In crypté
détail &= Asc(caractère) & " "
Next
détail &= vbCrLf & "________________________" & vbCrLf & vbCrLf
Me.TextBox_détails.Text &= détail
End If
'On ferme le fichier temporaire en lecture
fichier_r.Close()
Else
'Erreur de cryptage (ne s'est pour l'instant jamais produit)
'On ferme le fichier écrit
fichier_w.Close()
Me.TextBox_effectués.Text = txt_effectués
erreurs_cryptage += 1
Me.TextBox_erreurs_cryptage.Text = erreurs_cryptage
détail = "Erreur de cryptage " & erreurs_cryptage & "/" & effectués & vbCrLf
détail &= vbCrLf & "________________________" & vbCrLf & vbCrLf
Me.TextBox_détails.Text &= détail
End If
'Laisse le contrôle au système pour vérifier si l'on souhaite stopper le
programme
Application.DoEvents()
End While
End If
Me.TextBox_effectués.Text = txt_effectués
Me.CheckBox_Test.Text = "Teste !"
'On efface le fichier temporaire
IO.File.Delete(fichier_tmp)
End Sub
End Class
Je suis sous VB .Net 2003 et j'utilise une classe de cryptage Rijndael qui
fonctionne parfaitement.
Mon problème est que lorsque je décrypte, il se passe très rarement un
phénomène qui fait que soit le décryptage est impossible, soit la valeur
décryptée n'est pas égale à la valeur d'origine.
Ce phénomène se produit lorsque le caractère 10 ou le caractère 13 se
retrouve dans la chaîne cryptée.
En effet, je lis mon fichier (unicode) crypté ligne par ligne, et donc, la
chaîne cryptée se retrouve dans ce cas sur 2 lignes et fausse par conséquent
le décryptage de 2 facons différentes :
Soit le caractère 10 ou 13 est le 1er caractère est dans ce cas là, le
décryptage lui même génère une erreur (car la ligne lue est vide).
Soit le caractère 10 ou 13 est dans la chaîne est dans ce cas là, le
décryptage est bien possible, mais la valeur décryptée est différente de la
valeur d'origine.
J'ai bien pensé à remplacer dans la chaîne cryptée, avant d'enregistrer dans
le fichier, les caractères 10 et 13 par, par exemple 254 et 255 (ou tout
autre caractères valides), pour, lors du décryptage, remettre à l'endroit,
mais cette bidouille cache un autre problème, si la chaîne cryptée contenait
vraiment un caractère 254 ou 255, donc cela ne convient pas.
J'ai également pensé à remplacer dans la même perspective les caratères 10
et 13 par une chaîne plus longue (ex : 240 240 242 243 244 245 et 250 251
252 253 254 255) , mais le problème reste toujours possible même si cela le
raréfie.
Bref, mon problème est que je ne sais pas comment gérer ce phénomène.
Afin de vous aider au mieux, je vous met ci-dessous la classe Rijndael que
j'utilise (je l'ai appelé Raindoll, ca se prononce comme ca), suivi d'un
petit boût de code (cryptage et décyptage d'un simple compteur) qui permet
de très bien comprendre mon problème (j'ai remplacé ma clef de cryptage
ainsi que le vecteur pour des raisons de confidentialités).
Merci d'avance pour votre aide,
Stéphane
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Public Class raindoll
' Utilitaire de cryptographie
Protected Rijndael As New RijndaelManaged ' Fournit une implémentation de
l'algorithme de Rijndael pour le cryptage et le décryptage des données
Private m_Key() As Byte ' Clé de cryptage
Private m_IV() As Byte ' Vecteur d'interruption
' Constructeur par défaut : ne fait rien
Public Sub New()
End Sub
' Constructeur qui initialise la clé de cryptage et le vecteur
d'interruption.
' Les paramètres Key et IV représentent des tableaux de 16 octets
Public Sub New(ByVal Key() As Byte, ByVal IV() As Byte)
Me.Key = Key
Me.IV = IV
End Sub
' Autre constructeur qui initialise la clé de cryptage et le vecteur
d'interruption.
' Les paramètres sKey et sIV représentent des chaînes de 8 caractères
UNICODE.
Public Sub New(ByVal sKey As String, ByVal sIV As String)
Dim ue As New UnicodeEncoding ' Servira à convertir les chaînes en tableaux
d'octets
If sKey.Length > 8 Then ' Si la chaîne est trop longue, on la tronque
sKey = sKey.Substring(0, 8)
ElseIf sKey.Length < 8 Then ' Si par contre la chaîne est trop courte, on la
complète
Dim n As Integer = 8 - sKey.Length
For i As Integer = 0 To n - 1
sKey &= i
Next
End If
If sIV.Length > 8 Then
sIV = sIV.Substring(0, 8)
ElseIf sIV.Length < 8 Then
Dim n As Integer = 8 - sIV.Length
For i As Integer = 0 To n - 1
sIV &= i
Next
End If
' Conversion des deux chaînes en tableaux d'octets
Key = ue.GetBytes(sKey)
IV = ue.GetBytes(sIV)
End Sub
' Accesseur pour la clé de cryptage
Public Property Key() As Byte()
Get
Return m_Key
End Get
Set(ByVal Value As Byte())
m_Key = Value
End Set
End Property
' Accesseur pour le vecteur d'interruption
Public Property IV() As Byte()
Get
Return m_IV
End Get
Set(ByVal Value As Byte())
m_IV = Value
End Set
End Property
' Crypte le texte reçu du flux input et dirige le resultat vers le flux
output
Public Sub Encrypt(ByVal input As Stream, ByVal output As Stream)
' L'écriture dans le flux cs produira une sortie cryptée selon l'algorithme
de Rijndael
' avec m_Key comme clé et m_IV comme vecteur d'interruption
Dim cs As New CryptoStream(output, Rijndael.CreateEncryptor(m_Key, m_IV),
CryptoStreamMode.Write)
Dim buffer(100) As Byte ' tampon utilisé pour la lecture et l'écriture
Dim n As Integer ' nombre d'octets réellement lus ou écrits
' La suite ressemble à un transfert de données entre deux flux quelconques
Do
n = input.Read(buffer, 0, 100)
cs.Write(buffer, 0, n)
Loop Until n < 100
cs.Close()
End Sub
' Décrypte le texte reçu du flux input et dirige le resultat vers le flux
output
Public Sub Decrypt(ByVal input As Stream, ByVal output As Stream)
' La lecture à partir du flux cs est précédée du décryptage des données
d'origine.
' La clé de cryptage et le vecteur d'interruption doivent être les mêmes que
' ceux utilisés lors du cryptage des données.
Dim cs As New CryptoStream(input, Rijndael.CreateDecryptor(m_Key, m_IV),
CryptoStreamMode.Read)
Dim buffer(100) As Byte
Dim n As Integer
Do
n = cs.Read(buffer, 0, 100)
output.Write(buffer, 0, n)
Loop Until n < 100
cs.Close()
End Sub
' Crypte un texte en mémoire et retourne le texte crypté
Public Function EncryptText(ByVal original As String) As String
' On crée un MemoryStream avec le texte original
Dim UE As New UnicodeEncoding
Dim msIn As New MemoryStream(UE.GetBytes(original))
' et on en crée un autre pour la sortie
Dim msOut As New MemoryStream
' Les deux flux sont transmis à la méthode encrypt
Encrypt(msIn, msOut)
msIn.Close()
' Puis, on recupère le contenu du flux de sortie
Dim encrypted As String = UE.GetString(msOut.ToArray)
msOut.Close()
' Qu'on retourne en guise de resultat
Return encrypted
End Function
' Décrypte un texte en mémoire et retourne le texte décrypté
' Le principe est analogue à celui de EncryptText
Public Function DecryptText(ByVal encrypted As String) As String
Dim UE As New UnicodeEncoding
Dim msIn As New MemoryStream(UE.GetBytes(encrypted))
Dim msOut As New MemoryStream
Decrypt(msIn, msOut)
msIn.Close()
Dim decrypted As String = UE.GetString(msOut.ToArray)
msOut.Close()
Return decrypted
End Function
' Crypte un fichier texte et produit un autre fichier texte complètement
illisible
Public Sub EncryptFile(ByVal original As String, ByVal encrypted As String)
' On obtient un flux qui représente le fichier original
Dim fsIn As New FileStream(original, FileMode.Open)
' On en obtient un autre qui représente le fichier crypté
Dim fsOut As New FileStream(encrypted, FileMode.Create)
' On trasmet les deux flux à la méthode Encrypt et le travail est fait
Encrypt(fsIn, fsOut)
fsIn.Close()
fsOut.Close()
End Sub
' Décrypte un fichier texte crypté pour reconstituer le fichier original
' Le principe est analogue à celui de EncryptFile
Public Sub DecryptFile(ByVal encrypted As String, ByVal decrypted As String)
Dim fsIn As New FileStream(encrypted, FileMode.Open)
Dim fsOut As New FileStream(decrypted, FileMode.Create)
Decrypt(fsIn, fsOut)
fsIn.Close()
fsOut.Close()
End Sub
' Crypte un texte en mémoire à destination d'un fichier sur disque
Public Sub EncryptTextToFile(ByVal original As String, ByVal filename As
String)
' On crée un MemoryStream avec le texte original
Dim UE As New UnicodeEncoding
Dim msIn As New MemoryStream(UE.GetBytes(original))
' On obtient un flux de sortie qui représente le fichier crypté
Dim fsOut As New FileStream(filename, FileMode.Create)
' On trasmet les deux flux à la méthode Encrypt et le travail est fait
Encrypt(msIn, fsOut)
msIn.Close()
fsOut.Close()
End Sub
' Décrypte un fichier texte crypté et retourne le texte original
' sous la forme d'une très longue chaîne de caractères.
' Le principe est analogue à celui de EncryptTextToFile
Public Function DecryptTextFromFile(ByVal filename As String) As String
Dim UE As New UnicodeEncoding
Dim fsIn As New FileStream(filename, FileMode.Open)
Dim msOut As New MemoryStream
Decrypt(fsIn, msOut)
fsIn.Close()
Dim decrypted As String = UE.GetString(msOut.ToArray)
msOut.Close()
Return decrypted
End Function
End Class
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Code généré par le Concepteur Windows Form "
Public Sub New()
MyBase.New()
'Cet appel est requis par le Concepteur Windows Form.
InitializeComponent()
'Ajoutez une initialisation quelconque après l'appel InitializeComponent()
End Sub
'La méthode substituée Dispose du formulaire pour nettoyer la liste des
composants.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Requis par le Concepteur Windows Form
Private components As System.ComponentModel.IContainer
'REMARQUE : la procédure suivante est requise par le Concepteur Windows Form
'Elle peut être modifiée en utilisant le Concepteur Windows Form.
'Ne la modifiez pas en utilisant l'éditeur de code.
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents TextBox_effectués As System.Windows.Forms.TextBox
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents TextBox_erreurs As System.Windows.Forms.TextBox
Friend WithEvents CheckBox_Test As System.Windows.Forms.CheckBox
Friend WithEvents Label4 As System.Windows.Forms.Label
Friend WithEvents Label5 As System.Windows.Forms.Label
Friend WithEvents Label6 As System.Windows.Forms.Label
Friend WithEvents TextBox_erreurs_décryptage As System.Windows.Forms.TextBox
Friend WithEvents TextBox_erreurs_cryptage As System.Windows.Forms.TextBox
Friend WithEvents Label7 As System.Windows.Forms.Label
Friend WithEvents TextBox_détails As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label
Me.TextBox_effectués = New System.Windows.Forms.TextBox
Me.Label2 = New System.Windows.Forms.Label
Me.TextBox_erreurs = New System.Windows.Forms.TextBox
Me.CheckBox_Test = New System.Windows.Forms.CheckBox
Me.Label4 = New System.Windows.Forms.Label
Me.Label5 = New System.Windows.Forms.Label
Me.Label6 = New System.Windows.Forms.Label
Me.TextBox_erreurs_décryptage = New System.Windows.Forms.TextBox
Me.TextBox_erreurs_cryptage = New System.Windows.Forms.TextBox
Me.TextBox_détails = New System.Windows.Forms.TextBox
Me.Label7 = New System.Windows.Forms.Label
Me.SuspendLayout()
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(8, 8)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(168, 23)
Me.Label1.TabIndex = 0
Me.Label1.Text = "Tests de cryptage / décryptage"
'
'TextBox_effectués
'
Me.TextBox_effectués.Location = New System.Drawing.Point(160, 32)
Me.TextBox_effectués.Name = "TextBox_effectués"
Me.TextBox_effectués.ReadOnly = True
Me.TextBox_effectués.TabIndex = 1
Me.TextBox_effectués.Text = ""
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(8, 32)
Me.Label2.Name = "Label2"
Me.Label2.TabIndex = 2
Me.Label2.Text = "Effectués"
'
'TextBox_erreurs
'
Me.TextBox_erreurs.Location = New System.Drawing.Point(160, 72)
Me.TextBox_erreurs.Name = "TextBox_erreurs"
Me.TextBox_erreurs.ReadOnly = True
Me.TextBox_erreurs.TabIndex = 3
Me.TextBox_erreurs.Text = ""
'
'CheckBox_Test
'
Me.CheckBox_Test.Appearance = System.Windows.Forms.Appearance.Button
Me.CheckBox_Test.Location = New System.Drawing.Point(80, 608)
Me.CheckBox_Test.Name = "CheckBox_Test"
Me.CheckBox_Test.TabIndex = 5
Me.CheckBox_Test.Text = "Teste !"
Me.CheckBox_Test.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'Label4
'
Me.Label4.Location = New System.Drawing.Point(8, 64)
Me.Label4.Name = "Label4"
Me.Label4.Size = New System.Drawing.Size(144, 40)
Me.Label4.TabIndex = 6
Me.Label4.Text = "Valeur décryptée différente de la valeur d'origine"
'
'Label5
'
Me.Label5.Location = New System.Drawing.Point(8, 144)
Me.Label5.Name = "Label5"
Me.Label5.Size = New System.Drawing.Size(128, 23)
Me.Label5.TabIndex = 7
Me.Label5.Text = "Décryptage impossible"
'
'Label6
'
Me.Label6.Location = New System.Drawing.Point(8, 112)
Me.Label6.Name = "Label6"
Me.Label6.Size = New System.Drawing.Size(120, 23)
Me.Label6.TabIndex = 8
Me.Label6.Text = "Cryptage impossible"
'
'TextBox_erreurs_décryptage
'
Me.TextBox_erreurs_décryptage.Location = New System.Drawing.Point(160, 144)
Me.TextBox_erreurs_décryptage.Name = "TextBox_erreurs_décryptage"
Me.TextBox_erreurs_décryptage.ReadOnly = True
Me.TextBox_erreurs_décryptage.TabIndex = 9
Me.TextBox_erreurs_décryptage.Text = ""
'
'TextBox_erreurs_cryptage
'
Me.TextBox_erreurs_cryptage.Location = New System.Drawing.Point(160, 112)
Me.TextBox_erreurs_cryptage.Name = "TextBox_erreurs_cryptage"
Me.TextBox_erreurs_cryptage.ReadOnly = True
Me.TextBox_erreurs_cryptage.TabIndex = 10
Me.TextBox_erreurs_cryptage.Text = ""
'
'TextBox_détails
'
Me.TextBox_détails.Location = New System.Drawing.Point(8, 200)
Me.TextBox_détails.Multiline = True
Me.TextBox_détails.Name = "TextBox_détails"
Me.TextBox_détails.ReadOnly = True
Me.TextBox_détails.ScrollBars = System.Windows.Forms.ScrollBars.Both
Me.TextBox_détails.Size = New System.Drawing.Size(256, 400)
Me.TextBox_détails.TabIndex = 11
Me.TextBox_détails.Text = ""
'
'Label7
'
Me.Label7.Location = New System.Drawing.Point(8, 176)
Me.Label7.Name = "Label7"
Me.Label7.TabIndex = 12
Me.Label7.Text = "Détails"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(272, 637)
Me.Controls.Add(Me.Label7)
Me.Controls.Add(Me.TextBox_détails)
Me.Controls.Add(Me.TextBox_erreurs_cryptage)
Me.Controls.Add(Me.TextBox_erreurs_décryptage)
Me.Controls.Add(Me.Label6)
Me.Controls.Add(Me.Label5)
Me.Controls.Add(Me.Label4)
Me.Controls.Add(Me.CheckBox_Test)
Me.Controls.Add(Me.TextBox_erreurs)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.TextBox_effectués)
Me.Controls.Add(Me.Label1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub CheckBox_Test_CheckedChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles CheckBox_Test.CheckedChanged
Dim key(15) As Byte
Dim iv(15) As Byte
Dim cryptage As raindoll
Dim effectués As Integer = 0
Dim erreurs As Integer = 0
Dim erreurs_cryptage As Integer = 0
Dim erreurs_décryptage As Integer = 0
Dim fichier_tmp As String = System.IO.Path.GetTempFileName()
Dim txt_effectués, crypté, décrypté, ligne, détail As String
Dim fichier_r As System.IO.StreamReader
Dim fichier_w As System.IO.StreamWriter
Dim cryptage_ok, décryptage_ok As Boolean
If Me.CheckBox_Test.Checked Then
'Lancement du programme
'Définition de la clef de cryptage et du vecteur
For i As Byte = 0 To 15
key(i) = i
iv(i) = i
Next
cryptage = New raindoll(key, iv)
Me.CheckBox_Test.Text = "Stop !"
Me.TextBox_effectués.Text = effectués
Me.TextBox_erreurs.Text = erreurs
Me.TextBox_erreurs_cryptage.Text = erreurs_cryptage
Me.TextBox_erreurs_décryptage.Text = erreurs_décryptage
Me.TextBox_détails.Text = ""
Me.CheckBox_Test.Refresh()
While Me.CheckBox_Test.Checked Or effectués = Integer.MaxValue
effectués += 1
txt_effectués = effectués.ToString
If Math.IEEERemainder(effectués, 1000) = 0 Then
Me.TextBox_effectués.Text = txt_effectués
End If
'On crée (ou recrée en écransant) le fichier temporaire en écriture
fichier_w = New System.IO.StreamWriter(fichier_tmp, False,
System.Text.Encoding.Unicode)
Try
'On crypte le nombre de tests effectués
crypté = cryptage.EncryptText(txt_effectués)
cryptage_ok = True
Catch ex As Exception
cryptage_ok = False
End Try
If cryptage_ok Then
'On écrit le nombre crypté de tests effectués
fichier_w.WriteLine(crypté)
'Et on ferme le fichier écrit
fichier_w.Close()
'On réouvre le fichier temporaire, mais cette fois en lecture
fichier_r = New System.IO.StreamReader(fichier_tmp)
'On lit la ligne cryptée
ligne = fichier_r.ReadLine
Try
'On la décrypte
décrypté = cryptage.DecryptText(ligne)
décryptage_ok = True
Catch ex As Exception
décryptage_ok = False
End Try
If décryptage_ok Then
'On compare la chaîne décryptée avec le nombre de tests effectués
If décrypté <> txt_effectués Then
'Erreur de cryptage détectée
Me.TextBox_effectués.Text = txt_effectués
erreurs += 1
Me.TextBox_erreurs.Text = erreurs
détail = "Erreur de valeur " & erreurs & "/" & effectués & vbCrLf
détail &= "'Texte encrypté' : '" & crypté & "'" & vbCrLf
détail &= "Texte encrypté en hexa :" & vbCrLf
For Each caractère As String In crypté
détail &= Asc(caractère) & " "
Next
détail &= vbCrLf
détail &= "'Texte décrypté' : '" & décrypté & "'" & vbCrLf
détail &= "Texte décrypté en hexa :" & vbCrLf
For Each caractère As String In décrypté
détail &= Asc(caractère) & " "
Next
détail &= vbCrLf & "________________________" & vbCrLf & vbCrLf
Me.TextBox_détails.Text &= détail
End If
Else
'Une erreur s'est produite pendant le décryptage
Me.TextBox_effectués.Text = txt_effectués
erreurs_décryptage += 1
Me.TextBox_erreurs_décryptage.Text = erreurs_décryptage
détail = "Erreur de décryptage " & erreurs_décryptage & "/" & effectués &
vbCrLf
détail &= "'Texte encrypté' : '" & crypté & "'" & vbCrLf
détail &= "Texte encrypté en hexa :" & vbCrLf
For Each caractère As String In crypté
détail &= Asc(caractère) & " "
Next
détail &= vbCrLf & "________________________" & vbCrLf & vbCrLf
Me.TextBox_détails.Text &= détail
End If
'On ferme le fichier temporaire en lecture
fichier_r.Close()
Else
'Erreur de cryptage (ne s'est pour l'instant jamais produit)
'On ferme le fichier écrit
fichier_w.Close()
Me.TextBox_effectués.Text = txt_effectués
erreurs_cryptage += 1
Me.TextBox_erreurs_cryptage.Text = erreurs_cryptage
détail = "Erreur de cryptage " & erreurs_cryptage & "/" & effectués & vbCrLf
détail &= vbCrLf & "________________________" & vbCrLf & vbCrLf
Me.TextBox_détails.Text &= détail
End If
'Laisse le contrôle au système pour vérifier si l'on souhaite stopper le
programme
Application.DoEvents()
End While
End If
Me.TextBox_effectués.Text = txt_effectués
Me.CheckBox_Test.Text = "Teste !"
'On efface le fichier temporaire
IO.File.Delete(fichier_tmp)
End Sub
End Class

Poser une question


news.microsoft.com écrit :
Bonjour,
Si ton cryptage génère des caractères non imprimables (10 et 13 entre
autres), enregistre tes chaînes cryptées en les encodant en base64.
(voir System.Convert)
--
Fred
http://www.cerbermail.com/?3kA6ftaCvT
Stéphane.
"Fred"
Il est bien possible que je m'y sois mal pris... mais cela ne fonctionne
pas, j'ai maintenant un problème d'encryptage.
Je pense que ce nouveau problème vienne du fait que le cryptage soit déjà
encodé en unicode.
J'ai fait ainsi :
Dans la class Raindoll,
Dans la fonction
Public Function EncryptText(ByVal original As String) As String
Je remplace ceci :
' Qu'on retourne en guise de resultat
Return encrypted
par ceci :
' Qu'on retourne en guise de resultat
' Return encrypted
'en base 64
Dim encrypted_bytes As Byte()
For i As Integer = 1 To encrypted.Length
encrypted_bytes(i) = CByte(Asc(Mid(encrypted, i, 1)))
Next
Return Convert.ToBase64String(encrypted_bytes)
Puis, dans la fonction :
Public Function DecryptText(ByVal encrypted As String) As String
Je rajoute tout au début :
'reconversion de la base64 en normal
Dim encrypted_bytes As Byte()
encrypted_bytes = Convert.FromBase64String(encrypted)
encrypted = ""
For Each encrypted_byte As Byte In encrypted_bytes
encrypted &= Chr(encrypted_byte)
Next
"Fred"
Remplacer dans la fonction encrypt :
Dim encrypted_bytes As Byte()
par :
Dim encrypted_bytes(encrypted.Length) As Byte
Mais cette fois ci, j'ai 1 erreur systématique de décryptage... snif :/
"news.microsoft.com" message de news:
Dans décrypt, le mieux est de mettre uniquement cette ligne :
encrypted = UE.GetString(Convert.FromBase64String(encrypted))
juste après la déclaration de ue
mais maintenant, je n'ai que la moitié de mes caractères dans la chaine... à
cause de l'unicode qui code sur 2 octets.... re snif...
"news.microsoft.com" message de news: