Bonjour,
J'ai besoin de crypter un fichier byte par byte.
Existe-t-il une API Windows qui permet de faire ceci ?
Si non, merci de m'indiquer comment procéder.
Bonjour,
J'ai besoin de crypter un fichier byte par byte.
Existe-t-il une API Windows qui permet de faire ceci ?
Si non, merci de m'indiquer comment procéder.
En m'inspirant d'un autre exemple de Paul TOTH, je me suis amusé à faire quelque chose. J'espère que vous ne verrez pas d'inconvénient à ce que je le propose ici.
L'idée était donc de faire un tableau de conversion, comme dans l'exemple. Chaque caractère est associé (de façon aléatoire) à un unique autre caractère. Un deuxième tableau permet de revenir au caractère initial. Le code source est fabriqué par un programme. Les tables générées sont à chaque fois différentes.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 program MakeTables; {$APPTYPE CONSOLE} uses SysUtils; var a, b: array[byte]of byte; i, r: integer; s: string; t: textfile; begin { Associer à chaque nombre de 0 à 255 un unique autre nombre du même intervalle. Remplir une deuxième table qui permette de retrouver le premier nombre à partir du second. } Randomize; { Les nombres de 0 à 255 sont placés dans une chaîne, afin qu'on puisse les prélever. Les nombres sont écrits sous la forme hexadécimale. } for i := 0 to 255 do s := s + IntToHex(i, 2); for i := 0 to 255 do begin { On prend au hasard dans la chaîne. } r := Random(Length(s) div 2); { Le nombre est copié dans le tableau. } a[i] := StrToInt('$' + Copy(s, 2 * r + 1, 2)); { On retire le nombre de la chaîne. } Delete(s, 2 * r + 1, 2); end; Assert(Length(s) = 0); { On remplit la deuxième table. } for i := 0 to 255 do b[a[i]] := i; { On fabrique le code source. } AssignFile(t, 'Tables.pas'); Rewrite(t); WriteLn(t); WriteLn(t, 'unit Tables;'); WriteLn(t); WriteLn(t, 'interface'); WriteLn(t); WriteLn(t, 'const T1: array[char]of char ='); for i := 0 to 255 do s := s + '#' + Format('%.*d', [3, a[i]]); for i := 1 to 15 do WriteLn(t, Copy(s, 64 * (i - 1) + 1, 64) + '+'); WriteLn(t, Copy(s, 64 * (16 - 1) + 1, 64) + ';'); WriteLn(t); WriteLn(t, 'const T2: array[char]of char ='); SetLength(s, 0); for i := 0 to 255 do s := s + '#' + Format('%.*d', [3, b[i]]); for i := 1 to 15 do WriteLn(t, Copy(s, 64 * (i - 1) + 1, 64) + '+'); WriteLn(t, Copy(s, 64 * (i - 1) + 1, 64) + ';'); WriteLn(t); WriteLn(t, 'implementation'); WriteLn(t); WriteLn(t, 'end.'); WriteLn(t); CloseFile(t); WriteLn('FIN'); ReadLn; end.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 unit Crypt; interface function Encrypt(const s: ansistring): ansistring; function Decrypt(const s: ansistring): ansistring; procedure EncryptFile(const aFilename, aNewFilename: string); procedure DecryptFile(const aFilename, aNewFilename: string); implementation uses Tables; function Encrypt(const s: ansistring): ansistring; var i: integer; begin SetLength(result, Length(s)); for i := 1 to Length(result) do result[i] := T1[s[i]]; end; function Decrypt(const s: ansistring): ansistring; var i: integer; begin SetLength(result, Length(s)); for i := 1 to Length(result) do result[i] := T2[s[i]]; end; procedure EncryptFile(const aFilename, aNewFilename: string); var f: file; s: ansistring; sz: integer; begin Assign(f, aFilename); Reset(f, 1); sz := FileSize(f); SetLength(s, sz); BlockRead(f, s[1], sz); Close(f); s := Encrypt(s); Assign(f, aNewFilename); Rewrite(f, 1); BlockWrite(f, s[1], sz); Close(f); end; procedure DecryptFile(const aFilename, aNewFilename: string); var f: file; s: ansistring; sz: integer; begin Assign(f, aFilename); Reset(f, 1); sz := FileSize(f); SetLength(s, sz); BlockRead(f, s[1], sz); Close(f); s := Decrypt(s); Assign(f, aNewFilename); Rewrite(f, 1); BlockWrite(f, s[1], sz); Close(f); end; end.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 program Test1; {$APPTYPE CONSOLE} uses Crypt; var s: ansistring; begin s := 'Essai chiffrement-déchiffrement'; s := Encrypt(s); s := Decrypt(s); WriteLn(s); Write('ENTREE'); ReadLn; end.[EDIT]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 program Test2; {$APPTYPE CONSOLE} uses Crypt; begin EncryptFile('readme.indy.txt', 'encrypted.txt'); DecryptFile('encrypted.txt', 'decrypted.txt'); end.
Ajouté les fonctions EncryptFile et DecryptFile. Remplacé les types string et char par ansistring et ansichar. Le programme a été testé avec Delphi 7 et Delphi XE2.
[/EDIT]
J'ai testé avec succès l'exemple WinCrypt de Bernd Lehmann. Quoique le code soit de 1999, j'ai pu le compiler avec Delphi 7 et le test que j'ai fait sur un fichier texte a réussi.
Code : Sélectionner tout - Visualiser dans une fenêtre à part (* http://www.efg2.com/Lab/Library/Delphi/MathFunctions/BerndLehmannCrypto.zip *)
Bonjour,
Juste une première remarque : Dans l'unit Crypt on trouve result[i] := T1[s[i]] et result[i] := T2[s[i]] mais on n'y trouve pas la déclaration de T1 et T2.
A+.![]()
Bonjour ! Merci pour la réponse. Les tables T1 et T2 se trouvent dans l'unité Tables, qui est générée par le programme MakeTables. A chaque exécution les tables générées sont différentes. Voilà pourquoi je n'ai pas joint le code mais pour la clarté de la discussion il vaut peut-être mieux que je l'ajoute.
J'aimerais bien savoir ce que vous pensez de ce programme, ou si vous avez des améliorations à suggérer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 unit Tables; interface const T1: array[ansichar]of ansichar = #037#068#074#096#065#021#130#201#222#251#207#103#199#102#052#192+ #088#240#016#069#044#097#026#193#093#153#060#119#196#159#070#253+ #172#174#135#104#225#019#231#254#227#110#003#198#015#054#080#180+ #150#053#092#219#181#186#187#141#202#244#049#197#210#245#255#137+ #168#229#132#009#057#173#228#146#206#014#177#004#035#175#126#167+ #091#050#116#117#216#169#062#079#241#101#124#048#230#223#182#208+ #136#028#034#195#125#040#118#224#247#226#162#042#077#212#105#011+ #084#142#108#164#100#194#055#085#046#024#213#179#178#094#109#235+ #171#236#030#214#161#215#076#152#056#188#018#149#058#038#211#036+ #061#081#067#221#017#165#248#120#128#025#095#140#098#031#051#239+ #166#064#047#059#154#066#217#063#020#121#147#001#233#246#189#113+ #218#220#238#027#087#073#114#000#106#112#185#043#071#123#133#007+ #013#138#010#160#249#252#023#129#156#145#083#039#143#006#115#075+ #029#005#090#131#151#134#107#204#234#203#022#144#002#078#191#127+ #163#122#089#184#041#237#243#183#139#176#200#072#209#242#032#250+ #205#232#045#082#157#086#008#033#158#012#190#111#155#099#170#148; const T2: array[ansichar]of ansichar = #183#171#220#042#075#209#205#191#246#067#194#111#249#192#073#044+ #018#148#138#037#168#005#218#198#121#153#022#179#097#208#130#157+ #238#247#098#076#143#000#141#203#101#228#107#187#020#242#120#162+ #091#058#081#158#014#049#045#118#136#068#140#163#026#144#086#167+ #161#004#165#146#001#019#030#188#235#181#002#207#134#108#221#087+ #046#145#243#202#112#119#245#180#016#226#210#080#050#024#125#154+ #003#021#156#253#116#089#013#011#035#110#184#214#114#126#041#251+ #185#175#182#206#082#083#102#027#151#169#225#189#090#100#078#223+ #152#199#006#211#066#190#213#034#096#063#193#232#155#055#113#204+ #219#201#071#170#255#139#048#212#135#025#164#252#200#244#248#029+ #195#132#106#224#115#149#160#079#064#085#254#128#032#069#033#077+ #233#074#124#123#047#052#094#231#227#186#053#054#137#174#250#222+ #015#023#117#099#028#059#043#012#234#007#056#217#215#240#072#010+ #095#236#060#142#109#122#131#133#084#166#176#051#177#147#008#093+ #103#036#105#040#070#065#092#038#241#172#216#127#129#229#178#159+ #017#088#237#230#057#061#173#104#150#196#239#009#197#031#039#062; implementation end.
Re-bonjour,
Je retire ce que je viens de dire : les constantes T1 et T2 sont créées dans le fichier Tables.pas : un peu compliqué.
Autre remarque : il s'agit d'un simple cryptage par substitution et d'après la littérature facile à casser (par exemple, ShaiLeTroll écrit ici le 04/01/2012, 11h45 :http://www.developpez.net/forums/d11...e/#post6428544
Si en plus un hacker combine l'analyse statistique avec la recherche d'un mot probable et répété ça lui facilite encore davantage la vie.Dans une simple substitution de l'alphabet, une analyse statistique permet de retrouver les lettres les plus utilisées, si l'on connait la langue du texte, il est facile de retrouver le e pour le français et les autres lettres et de casser l'Alphabet utilisé pour la substitution !
Pour ma part j'aime bien le cryptage par la méthode Vigénère vu les avantages suivants :
a) Une même lettre est codée par des lettres différentes selon sa position dans le texte : rend inutilisable l'attaque par analyse de fréquence directe.
b) Attaque par mot probable : Nécessite que la longueur du mot probable soit supérieure ou égale à celle de la clé. Dans le français aucun mot probable ne dépasse 52 lettres :
- français courant : anticonstitutionnellement : 25 lettres.
- chimie : chlorure d'aminométhylpyrimidinyl-hydroxy-éthylméthy-thiazolium : 52 lettres.
Donc avec une clé de 26 ou 53 lettres, selon le contenu du texte en clair, cette attaque devient impossible puisque le texte en clair est formé de mots plus courts.
c) Attaque par brute-force en connaissant la longueur de la clé : Le nombre de clefs possibles est très grand même si la longueur de celle choisie est relativement courte.
Exemple, pour une clé de 13 lettres il y a 26 choix pour la première lettre, 26 choix pour la seconde lettre, etc... soit au total 26^13 = 2 481 152 873 203 736 576 choix possibles.
Un ordinateur essayant un million de clés par seconde mettrait 78 623 années pour toutes les essayer.
Et pour une clé de 26 lettres : 26^26 = 6 156 119 580 207 157 310 796 674 288 400 203 776 choix possibles => 195 075 657 851 267 438 296 850 années pour hacker.
Impossible de décrypter si on ne connaît pas la longueur de la clé, et même avec une seule et unique clé de longueur connue de 26 lettres on est tranquille pendant des milliards d'années en attendant les ordis quantiques.
Voici un bout de code pour la méthode Vigenère :
Pour utiliser, il suffit d'utiliser :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 function CodeDecVigenere(S, Clef: tMemoryStream; Coder: Boolean): tMemoryStream; // S = texte à crypter/décrypter // Clef = Clef de cryptage/décryptage // Si Coder = True alors Result = texte crypté sinon Result = texte décrypté. var i, LClef, poClef: Cardinal; Sens: smallint; ps, pc, pcd, pr: PByte; function Trans(Ch1, Ch2: byte; Sens: smallint): byte; var r: integer; begin r := (Ch1 + Ch2 * sens); if r > 255 then r := r - 256; if r < 0 then r := 256 + r; Result := r; end; begin Result := tMemoryStream.Create; Result.Position := 0; Result.SetSize(S.Size); ps := S.Memory; pc := Clef.Memory; pcd := pc; pr := Result.Memory; poClef := 0; if (Clef.Size <> 0) and (S.Size <> 0) then begin Lclef := Clef.Size; if Coder then Sens := -1 else Sens := +1; for I := 0 to S.Size - 1 do begin if poClef = Lclef then begin pc := pcd; poClef := 0; end; // Clef.Position := 0; pr^ := Trans(ps^, pc^, Sens); inc(ps); inc(pc); inc(pr); inc(poClef); end; end; end;
A+.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 var BufMess, BufCleVig: TMemoryStream; procedure StrToStream(Stream: TStream; Chaine: string); var i: integer; c: char; begin if length(Chaine) > 0 then for i := 1 to length(Chaine) do begin c := Chaine[i]; stream.Write(c, 1); end; c := #0; stream.Write(c, 1); end; // Lors du chargement depuis le disque du fichier à crypter/décrypter: ... BufMess := TMemoryStream.Create; BufMess.LoadFromFile(FileName); // fichier à crypter/décrypter BufCleVig := TMemoryStream.Create; StrToStream(BufCleVig, edClefVigenere.Text); // la clef ... // Pour le cryptage : ... BufMess.Position := 0; BufCleVig.Position := 0; BufMess := CodeDecVigenere(BufMess, BufCleVig, TRUE); ... // Pour le décryptage: ... BufMess.Position := 0; BufCle.Position := 0; BufMess := CodeDecVigenere(BufMess, BufCleVig, FALSE); ... // Pour afficher les résultats dans un RichEdit : ... RichEdit2.Lines.BeginUpdate; BufMess.Position := 0; RichEdit2.Lines.LoadFromStream(BufMess); RichEdit2.Lines.EndUpdate; BufMess.Free; BufCleVig.Free; ...![]()
Partager