CHƢƠNG TRÌNH THỬ NGHIỆM

Một phần của tài liệu Nghiên cứu phối hợp hai phương pháp nén và mã hóa thông tin (Trang 86 - 99)

4.3.1 Mô tả chung

Theo Hình 4.2 để gửi đi file đã nén và mã hoá ngƣời dùng cần phải gửi kèm theo file bản mã của khoá AES đã đƣợc sử dụng để mã hoá tệp tin nén. Khi ngƣời nhận tệp tin nén cần:

- Dùng khoá bí mật RSA của mình để giải mã khoá AES nhận đƣợc - Dùng khoá AES để giải mã tệp tin nén

- Giải nén tệp tin

- Ý tƣởng cài đặt chƣơng trình cho qui trình trên nhƣ sau:

Khi mã hoá, chƣơng trình chỉ nhận file bản rõ, khoá AES và khoá RSA là tham số đầu vào, khoá AES sau khi đƣợc mã hoá bằng thuật toán RSA sẽ đƣợc lƣu ra một tệp, tệp tin nén sau khi mã hoá sẽ đƣợc lƣu trên một tệp (tệp cuối).

Giải mã, chƣơng trình nhận bản mã của khoá AES, khoá bí mật RSA và tệp nén làm tham số đầu vào, chƣơng trình sẽ đọc bản mã của khoá AES giải mã để lấy khoá, sau đó khoá đƣợc sử dụng để giải mã tệp cuối. Tệp sau giải mã đƣợc giải nén để có tệp tin ban đầu

4.3.2 Ý tƣởng cài đặt

4.3.2.1 Ngôn ngữ lập trình

Ngôn ngữ lập trình C# là một trong những ngôn ngữ lập trình hƣớng đối tƣợng hiện đại, mạnh mẽ và mềm dẻo. Là ngôn ngữ lập trình đƣợc Microsoft phát triển trên nền tảng của hai ngôn ngữ lập trình C và C++ do vậy mà nó mang sức mạnh của C++ nhƣng lại đƣợc cho rằng dễ dàng sử dụng nhƣ Visual Basic.

C# cũng là ngô ngữ hƣớng Module. Mã nguồn C# có thể đƣợc viết trong những phần đƣợc gọi là những lớp, những lớp này chứa các phƣơng thức thành viên của nó. Những lớp và những phƣơng thức có thể đƣợc sử dụng lại trong ứng dụng hay các chƣơng trình khác. Bằng cách truyền các mẫu thông tin đếnnhững lớp hay phƣơng thức chúng ta có thể tạo ra những mã nguồn dùng lại có hiệu quả.

Cũng nhƣ các ngôn ngữ khác trong hệ thống Visual Studio.Net. C#.Net đƣợc hỗ trợ mạnh bởi hệ thống thƣ viện đồ sộ NetFrameWork của Microsoft.

Đây là lý do tại sao C# đƣợc lựa chọn để cài đặt chƣơng trình Demo cho luận văn này.

4.3.2.2 Cấu trúc chƣơng trình

Chƣơng trình cho phép nén, mã hoá trên nhiều loại file khác nhau: văn bản (.doc, xls, pptt, txt…), ảnh (bitmap, Jpg…), các file video… Các loại file khác nhau có định dạng và cấu trúc file cũng khác nhau do đó quá trình giãi mã và giải nén ngoài việc giữ nguyên nội dung file gốc phải đảm bảo cả về mặt định dạng và cấu trúc file ban đầu

1. Xây dựng lớp ConvertStringTobyte.cs gồm các phƣơng thức:

- readfileTostring: Đọc tệp có định dạng tuỳ ý trả về một xâu ký tự

Đọc file theo từng bit, chuyển dãy bit thành dãy số nguyên sau đó chuyển số nguyên thành các ký tự và ghép thành một xâu

- Createfile: Từ xâu ký tự ghi thành tệp gốc (giữ nguyên nội dung và cấu trúc) Chuyển mỗi ký tự trong xâu thành một số nguyên, đổi các số nguyên thành các bit sau đó ghi tệp theo các bit.

- Ghi file text:

+ Input: xâu ký tự, đƣờng dẫn + Output: tệp văn bản

2. Nén dữ liệu bằng phƣơng pháp LZW (Lempel - Zip - Welch) – Xây dựng lớp LZW.cs

a. Nén dữ liệu:

Input: đƣờng dẫn tệp tin cần nén

Output: Tệp tin đã nén (với tên: tên file gốc + phần mở rộng lzw)

Tệp tin nén sẽ đƣợc đặt cùng thƣ mục với tệp tin gốc

Trong quá trình nén sử dụng một bảng băm để lƣu từ điển nén theo thuật toán LZW đã trình bày trong phần 3.3.2.2 mục 3.

b. Giải nén dữ liệu:

+ Input: đƣờng dẫn tệp cần tin nén;

+ Output: tệp tin giải nén (có tên: tên của tập tin ban đầu)

Tệp tin giải nén đƣợc đặt trong cùng thƣ mục với tệp tin nén

Quá trình giải nén sử dụng từ điển đƣợc xây dựng dần từ văn bản đã xét. Từ điển này đƣợc lƣu trữ trong một bảng băm. Tuy nhiên khi từ điển quá lớn, số thứ tự của các từ mã càng về sau càng lớn, đôi khi để lƣu trữ các từ mã này cần số bit nhiều hơn để lƣu trữ bản thân từ mã. Mặt khác nếu từ mã có số thứ tự lớn lại xuất hiện nhiều

lần trong bản nén điều này ảnh hƣởng nhiều đến hiệu quả nén. Để khắc phục nhƣợc điểm này dựa vào ý tƣởng của phƣơng pháp nén theo mô hình thống kê, từ nào xuất hiện nhiều lần đƣợc mã hoá bằng từ mã ngắn hơn. Nhƣ vậy ở đây sau khi xây dựng từ điển và bản mã cần thêm một công đoạn kiểm tra lại bản mã thống kê số lần lặp lại của các từ mã sau đó đánh lại số thứ tự của từ điển đồng thời thay thế các từ mã trong bản nén. Trƣớc khi thay đổi bản mã và từ điển cần sử dụng mảng để lƣu lại ánh xạ thay đổi giữa từ mã cũ và từ mã mới

Quá trình giải nén các kí tự không đƣợc ghi ngay ra tệp tin giải nén mà chuỗi ký tự sẽ đƣợc lƣu thành một xâu, xâu ký tự đƣợc chuyển về dạng bit để ghi tệp theo đúng cấu trúc ban đầu.

3. Nén bằng phƣơng pháp GZIP – Xây dựng lớp: Gzip.cs

- Sử dụng thƣ viện có sẵn của C#.Net: System.Io.Compression

- Sử dụng lớp có sẵn trong thƣ viện: Gzipstream gồm hai phƣơng thức CompressMode và DecompressMode

- Phƣơng thức Compress

+ Input: đƣờng dẫn tệp tin cần nén; đƣờng dẫn tệp tin sau khi nén + Output: tệp tin nén (tên file nén = tên tệp ban đầu + phần mở rộng .gzip)

void Compress(String input, String output)

fileOutput = new FileStream(output, FileMode.Create, FileAccess.Write); gzipStream = new GZipStream(fileOutput, CompressionMode.Compress, true); fileInput = new FileStream(input, FileMode.Open, FileAccess.Read, FileShare.Read); buffer = new byte[fileInput.Length];

gzipStream.Write(buffer, 0, buffer.Length);

- Nhƣ đã trình bày trong phần mở đầu 4.3.2.2 nội dung tệp tin nén sẽ đƣợc chuyển thành một mảng số nguyên (byte) trƣớc khi áp dụng giải thuật nén.

- Tệp tin nén đƣợc đặt trong cùng thƣ mục với tệp tin ban đầu - Phƣơng thức Decompress

+ Input: đƣờng tệp tin nén, đƣờng dẫn tệp tin giải nén + Output: tệp tin nén

fileInput = new FileStream(input, FileMode.Open, FileAccess.Read); fileOutput = new FileStream(output, FileMode.Create, FileAccess.Write); gzipStream = new GZipStream(fileInput, CompressionMode.Decompress, true); fileOutput.Write(buffer, 0, count);

4. Huffman – xây dựng hai lớp: HuffmanTree.cs và Node.cs a. Lớp HuffmanTree.cs

Phƣơng thức: Build (string)

Trong phƣơng thức sử dụng kiểu từ điển để lƣu trữ các kí tự có trong xâu cùng với số lần xuất hiện của kí tự đó trong xâu

Xây dựng các cây con từ danh sách kí từ vừa lƣu trữ trong từ điển Xây dựng cây nhị phân đầy đủ từ các cây con

Phƣơng thức: BitArrayEncode (string);

Mã hoá xâu kí tự trả về một dãy bít nhị phân, trong phƣơng thức có gọi dến phƣơng thức Traverse(char symbol, List<bool> data) của lớp Node.

Để thu đƣợc bản mã cần đổi dãy bit về xâu kí tự và ghi lại vào file nén. Phƣơng thức String Decode (BitArray);

Từ dãy bit giải mã về xâu kí tự sử dụng cây nhị phân đã xây dựng

b. Node.cs

Gồm có các thuộc tính: char Symbol: ký tự của node int Frequency: trọng số của node Node Right: cây con trái

Node Left: cây con phải

Phƣơng thức: Traverse(char symbol, List<bool> data): trả về dãy bit để mã hoá ký tự symbol.

Trong phƣơng thức này có sử dụng kỹ thuật đệ qui để tìm ra dãy bit mã hoá kí tự cần tìm:

if (Left != null)

List<bool> leftPath = new List<bool>(); leftPath.AddRange(data);

leftPath.Add(false);

left = Left.Traverse(symbol, leftPath); if (Right != null)

List<bool> rightPath = new List<bool>(); rightPath.AddRange(data);

rightPath.Add(true);

right = Right.Traverse(symbol, rightPath);

5. Mã hoá tệp tin (AES Encryption)

- Thuật toán mã hoá AES đƣợc đặt trong lớp AES.cs

- Trong C#. Net có thƣ viện System.Security.Cryptography; hỗ trợ mã hoá tệp tin bằng thuật toán AES

a. Mã hoá - thủ tục Encrypt

Input: bản rõ, khoá AES, (độ dài khoá) Output: bản mã

Để chuyển một chuỗi thành một dãy byte để phù hợp với phép mật hóa đối xứng sử dụng phƣơng thức PasswordDeriveBytes. Có nhiều cách để chuyển một chuỗi thành một dãy byte bằng các kỹ thuật khác, tuy nhiên, cách tiếp cận đó không đủ bảo mật. Ví dụ, hầu hết các password đều tƣơng đối ngắn và sử dụng có giới hạn các ký tự (chữ cái và số). Điều này làm giảm sức mạnh của các khóa đƣợc sinh ra. Tuy nhiên, bạn có thể sử dụng một giá trị chuỗi làm seed cho một bộ sinh số ngẫu nhiên, việc này có thể sinh ra một dãy byte với độ bảo mật cao có thể sử dụng làm khóa. Khi tạo một đối tƣợng PasswordDeriveBytes, cần cung cấp password và giá trị salt cho hàm khởi dựng. Salt là một dãy ngẫu nhiên các byte. Nó đƣợc kết hợp với password khi sinh ra khóa. Nếu sử dụng một giá trị salt khác 0, bạn có thể chống chọi với kiểu tấn công từ điển (dictionary attack), trong đó kẻ tấn công truy tìm một khóa cho mỗi từ trong từ điển và cố sử dụng danh sách các khóa đƣợc-tạo-trƣớc này để giải mật hóa dữ liệu. Vấn đề ở chỗ kẻ tấn công sinh ra danh sách khóa với giả định là không có giá trị salt. Khi sử dụng một giá trị salt, kẻ tấn công cần phải tìm ra nó rồi mới tạo ra danh sách khóa.

Quá trình mã hoá gồm các bƣớc: Tạo khoá hợp lệ cho quá trình mã hoá:

PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] {0x00, 0x01, 0x02, 0x1C, 0x1D, 0x1E, 0x03, 0x04, 0x05, 0x0F, 0x20, 0x21, 0xAD, 0xAF, 0xA4});

Chuyển văn bản mã hoá về dãy byte

byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(Data);

Mã hoá dãy byte với cặp khoá hợp lệ vừa tạo ra và trả về xâu ký tự.

byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(16), pdb.GetBytes(16)); return Convert.ToBase64String(encryptedData);

b. Giải mã - thủ tục Desecrypt

- Quá trình giải mã gồm các bƣớc

- Tạo khoá hợp lệ cho quá trình giải mã:

PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] {0x00, 0x01, 0x02, 0x1C, 0x1D, 0x1E, 0x03, 0x04, 0x05, 0x0F, 0x20, 0x21, 0xAD, 0xAF, 0xA4});

- Chuyển văn bản mã hoá về dãy byte

byte[] cipherBytes = Convert.FromBase64String(Data);

- Giải mã dãy byte với cặp khoá hợp lệ vừa tạo ra và trả về xâu ký tự.

byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(16), pdb.GetBytes(16)) return System.Text.Encoding.Unicode.GetString(decryptedData);

6. Mã hoá khoá công khai RSA

- Sử dụng thƣ viện System.Security.Cryptography; của C#.Net. Trong thƣ viện này sử dụng lớp RSACryptoServiceProvider:

- Tạo khoá bí mật RSA RSAProvider.ToXmlString(true) - Tạo khoá công khai RSA RSAProvider.ToXmlString(false) - Đọc khoá công khai từ tệp Xml:

rsaCryptoServiceProvider.FromXmlString( xmlString )

- Đọc khoá bí mật từ tệp xml

rsaCryptoServiceProvider.FromXmlString( xmlString )

- Mã hoá từng khối dữ liệu với đầu vào là một dãy byte và trả về dãy byte tƣơng ứng, sau đó dãy byte này đƣợc chuyển về một xâu kí tự của bản mã

byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt( tempBytes, true) stringBuilder.Append( Convert.ToBase64String( encryptedBytes ) )

- Giải mã từng từng khối dữ liệu với đầu vào là một dãy byte và trả về dãy byte tƣơng ứng sau đó dãy byte này đƣợc chuyển thành xâu kí tự trong bản rõ

arrayList.AddRange( rsaCryptoServiceProvider.Decrypt( encryptedBytes, true ) ); return Encoding.UTF32.GetString_

4.3.3 Thực hiện

Hình 4.8: Giao diện chương trình thử nghiệm

1. Nén tệp tin

- Nhập khoá AES trong Aes Input - Chọn thuật toán nén tron

- Nhấp nút Open file để mở tệp cần nén

- Chọn Compress Only để thực hiện nén dữ liệu, tệp tin nén sẽ đƣợc lƣu trong

cùng thƣ mục với tệp tin ban đầu với phần mở rộng là .lzw, .huf, .gzip ứng với từng thuật toán

2. Giải nén

- Chọn Extract Only, sau đó chọn tệp tin trong hộp thoại chọn tệp tin giải nén, tệp tin giải nén đƣợc đặt trong cùng thƣ mục với tệp tin nén.

3. Mã hoá tệp tin

- Nhập khoá AES trong AES Key Input

- Nếu chỉ mã hoá mà không nén, sau khi mở tệp tin ngƣời dùng chọn AES Encode, bản mã đƣợc đặt trong cùng thƣ mục với bản rõ.

4. Giải mã tệp tin

- Chọn độ dài khoá trong Modulus Size - Chọn hàm băm trong OAEP

- Chọn RSA Descryption, chọn bản mã của khoá Aes, hệ thống yêu cầu chọn khoá bí mật RSA để giải mã. Khoá AES sau khi đƣợc giải mã tự động điền vào AES Key Input

- Nếu muốn giải mã tệp tin chỉ mã hoá ngƣời dùng nhấp AES Descode, chọn tệp tin cần giải mã, tệp tin cần giải mã đƣợc đặt trong cùng thƣ mục với bản mã

5. Mã khoá AES bằng hệ mã hoá RSA a. Sinh khoá:

- Chọn độ dài cho khoá và bảng băm thích hợp sau đó nhấp Generate RSA KeyPair để sinh khoá, sau đó chọn đƣờng dẫn để lƣu khoá công khai (phần mở rộng .kez) và khoá bí mật (phần mở rộng .pke)

b. Mã hoá RSA

- Nhập khoá AES (AES Key Input)

- Chọn AES Encryption, chọn tệp khoá công khai RSA (.pke)

c. Giải mã RSA

- Chọn AES Descryption, chọn bản mã khoá AES, chọn khoá bí mật RSA (.kez)

6. Nén và mã hoá a. Nén tin

- Chọn phƣơng pháp nén - Chọn Open file để mở tệp tin - Nhập khoá AES

- Chọn COMPRESS

Tệp tin nén sẽ đƣợc đặt trong cùng thƣ mục với tệp tin ban đầu với phần mở rộng (.ael, .aeh, .aeg) tƣơng ứng với thuật toán nén đã chọn

c. Giải nén

- Nhập khoá AES hợp lệ

- Chọn EXTRACT, chọn tệp tin cần giải nén

4.3.4 Đánh giá

a. Một số kết quả thực hiện chƣơng trình - Mục tiêu:

+ Thử nghiệm các chức năng thực hiện của chƣơng trình

+ So sánh hiệu quả nén giữa các thuật toán nén và kích thƣớc tệp vừa nén, vừa mã hoá với tệp tin chỉ mã hoá hoặc mã hoá trƣớc nén sau

+ Đánh giá về mặt thời gian thực hiện các thuật toán

Chƣơng trình sau khi chạy thử với một số loại dữ liệu cho kết quả nhƣ sau - Loại tệp: tệp wordocument (Luanvan.doc) dung lƣợng: 1505 KB

STT Chƣơng trình Dung lƣợng sau khi

thực hiện Tỉ lệ 1. LZW 1251 KB 16.9 % 2. Huff 1332 KB 11.5 % 3. Gzip 966 KB 35.8 % 4. Lzw + AES 1776 KB -10.8 % 5. Huff + AES 1668 KB -18 % 6. Gzip + AES 1288 KB 14.4 % 7. AES 2007 KB -33.4 % 8. GPG 849 KB 43.6 %

- Loại tệp: textdocument (README.txt) dung lƣợng: 18 KB STT Chƣơng trình Dung lƣợng sau khi

thực hiện Tỉ lệ 1. LZW 12 KB 33.3 % 2. Huff 13 KB 27.8 % 3. Gzip 7 KB 61.1 % 4. Lzw + AES 16 KB 11.1 % 5. Huff + AES 17 KB 5.6 % 6. Gzip + AES 9 KB 50 % 7. AES 24 KB -33.3 % 8. GPG 7KB 61.1 %

- Loại tệp: xml Document (Microsoft.Data.xml) dung lƣợng: 1488 KB

STT Chƣơng trình Dung lƣợng sau khi

thực hiện Tỉ lệ 1. LZW 193 KB 87 % 2. Huff 920 KB 38.2 % 3. Gzip 110 KB 92.6 % 4. Lzw + AES 147 KB 90.1 % 5. Huff + AES 258 KB 82.7 % 6. Gzip + AES 1227 KB 17.5 % 7. AES 1957 KB -31.5 % 8. GPG 134 KB 91 %

- Loại tệp: JPG (Picture.JPG) dung lƣợng: 3656KB

STT Chƣơng trình Dung lƣợng sau khi

thực hiện Tỉ lệ 1. LZW 3958 KB -0.1 % 2. Huff 3655 KB 0 % 3. Gzip 3659 KB -8.3 % 4. GPG 3656 KB 0 % 5. Winzar 3656 KB 0 %

Bảng 4.1: Bảng kết quả thử nghiệm đánh giá hiệu quả nén

Về mặt thời gian sau khi chạy 20 lần với 2 tệp Giaoan.doc dung lƣợng 2346 KB, tệp Picture 3656 KB, tệp AVSQ1.Dat dung lƣợng 50093 KB. Chƣơng trình cho kết quả về mặt thời gian nhƣ sau (sử dụng biết StopWacth trong C#. Net nên đánh giá về mặt thời gian chỉ là kết quả tƣơng đổi)

+ Đơn vị do: giây

STT Chƣơng trình Giaoan.doc Picture.JPG AVSEQ1.Dat

1. LZW 2.83 – 2.97 4.57 – 4.76 2. Huff 1.53 – 1.74 2.43 – 2..51 3. Gzip 0.13 – 0.17 0.25 – 0.27 4. Lzw + AES 2.92 – 3.07 2.12 – 2.21 5. Huff + AES 1.83 – 1.94 2.73 – 2.78 7.83 – 7.99 6. Gzip + AES 0.32 – 0.39 0.58 – 0.63 7. AES 0.16 – 0.21 0.12 – 0.18 2.23 – 2.31 8. AES – LZW file 0.14 – 0.19 0.09 – 0.11

9. AES – GZIP file 0.14 – 0.19 0.08 – 0.13 1.09 – 1.13

Bảng 4.2: Bảng kết quả thử nghiệm đánh giá về mặt thời gian

b. Đánh giá

Bảng kết quả 4..1 trên cho thấy, hiệu quả nén của mỗi thuật toán phụ thuộc vào nhiều yếu tố: loại tệp tin, nội dung của mỗi loại tệp tin… Với tệp văn bản Huffman không hiệu quả bằng LZW, Gzip, tuy nhiên với tệp hình ảnh cho thấy Huffman có hiệu quả hơn so với LZW, Gzip.

Ngoài ra, hiệu quả nén còn phụ thuộc vào hiệu quả của cách xây dựng từ điển

Một phần của tài liệu Nghiên cứu phối hợp hai phương pháp nén và mã hóa thông tin (Trang 86 - 99)

Tải bản đầy đủ (PDF)

(99 trang)