II. Thi hành Blowfish
Động lực cho cấu trúc mật mã Feistel
Một mật mã khối hoạt động với một khối plaintext gồm n bit để kết xuất một khối ciphertext n bit. Có 2n khả năng khác nhau có thể của các khối, và để cho có thể đảo ngược quả trình mã hóa (tức, có thể giải mã trở lại), mỗi khối phải đưa ra một khối ciphertext độc nhất. Một biến đổi như thế gọi là biến đổi nghịch đảo được hay biến đổi không cô độc. Ví dụ sau đây làm sáng tỏ thế nào là biến đổi cô độc và không cô độc, với n = 2.
Ánh xạ không cô độc Ánh xạ cô độc Plaintext Ciphertext Plaintex
t Ciphertext
00 11 00 11
01 10 01 10
10 00 10 01
11 01 11 01
Ở trường hợp thứ hai, một ciphertext 01 có thể đưa ra một trong hai khối plaintext. Nên nếu ta tự giới hạn các ánh xạ không cô độc.
Hình 1 minh họa logic của một mật mã thay thế chung với n = 4. Một đầu vào 4 bit đưa ra 16 khả năng có thể của trạng thái đầu vào, mỗi trạng thái trình bày bằng 4 bit ciphertext. Các ánh xạ mã hóa và giải mã hóa có thể được định nghĩa bằng một bảng, như bảng 3. Đây là dạng chung nhất của mật mã khối và có thể được sử dụng để định nghĩa bất cứ ánh xạ nghịch đảo được nào giữa plaintext và ciphertext. Feistel ám chỉ đến điều này như mật mã khối lý tưởng, bởi vì nó cho phép tối đa cố khả năng ánh xạ mã hóa có thể từ khối plaintext [FEIS75].
Hình 1. Khối thay thế chung n-bit n-bit (minh họa với n = 4)
Bảng 3 Các bảng mã hóa và giải mã hóa cho mật mã thay thế
Plaintext Ciphertext Plaintext Ciphertext
0000 1110 0000 1110 0001 0100 0001 0011 0010 1101 0010 0100 0011 0001 0011 1000 0100 0010 0100 0001 0101 1111 0101 1100 0110 1011 0110 1010 0111 1000 0111 1111 1000 0011 1000 0111 1001 1010 1001 1101 1010 0110 1010 1001 1011 1100 1011 0110 1100 0101 1100 1011 1101 1001 1101 0010 1110 0000 1110 0000 1111 0111 1111 0101
Nhưng có một vấn đề thực tiễn với mật mã khối. Nếu một kích thước khối nhỏ được sử dụng, chẳng hạn n = 4, thì hệ thống tương đương với một mật mã thay thế cổ điển. Các hệ thống như vậy, như chúng ta đã thấy, rất dễ tổn thương bởi một phân tích thống kê trên plaintext. Nhược điểm này không phải đặc điểm cố hữu khi sử dụng một mật mã thay thế, nhưng lại xảy ra với việc sử dụng một khối kích thước nhỏ trong mật mã khối. Nếu n đủ lớn và cho phép một sự thay thế nghịch đảo bất kỳ giữa plaintext và ciphertext, thì các đặc trưng thống kê của plaintext nguồn được che đậy và làm thất bại kiểu phân tích mã bằng thống kê.
Tuy nhiên, một mật mã tùy ý thay thế nghịch đảo (mật mã khối lý tưởng) với một kích thước khối lớn là không thực tế. Để có một sự biến đổi như thế, phép ánh xạ, tự nó, phải thiết lập mật khóa. Xem xét lại với bảng 3, bảng này định
nghĩa cụ thể một pháp ánh xạ nghịch đảo từ plaintext sang ciphertext bằng các mục trong cột thứ hai, cột này chứa các giá trị của ciphertext cho mỗi khối plaintext. Điều này, về mặt bản chất, là mật khóa xác định rõ ánh xạ giữa các khả năng ánh xạ có thể. Trong trường hợp này, sử dụng phương pháp định nghĩa khóa rành mạch, chiều dài khóa là 4 bit × 16 hàng = 64 bit. Tổng quát, với mật mã khối lý tưởng n-bit, chiều dài mật khóa định nghĩa theo cách này là n×2n bit. Với một khối 64-bit, là một chiều dài mong muốn để cản trở các tấn công thống kê, chiều dài mật khóa đòi hỏi là 64×264 =270≈ 1021 bit.
Khi thấy được các khó khăn này, Feistel chỉ ra rằng cái cần thiết là cái xấp xỉ với hệ thống mật mã khối lý tưởng với n lớn, xây dựng bên ngoài các thành phần dễ dàng nhận thấy [FEIS75]. Nhưng trước khi chuyển sang cách tiếp cận của Feistel, chúng ta hãy thực hiện một quan sát khác. Chúng ta có thể sử dụng mật mã khối thay thế chung, nhưng, để làm cho nó dễ thực hiện, chúng ta tự hạn chế thành một tập con các khả năng ánh xạ nghịch đảo có thể. Ví dụ, giả sử ta định nghĩa phép ánh xạ bằng một hệ phương trình tuyến tính. Trong trường hợp n = 4, chúng ta có
y1 = k11x1 + k12x2 + k13x3 + k14x4
y2 = k21x1 + k22x2 + k23x3 + k24x4
y3 = k31x1 + k32x2 + k33x3 + k34x4
y4 = k41x1 + k42x2 + k43x3 + k44x4
với xi là bốn các số nhị phân của khối plaintext, các yi là bốn số nhị phân của ciphertext, kị là các hệ số nhị phân. Kích thước của khóa chỉ là n2, trong trường hợp này là 16 bit. Sự nguy hiểm trong kiểu công thức này ở chỗ nó có thể là đối tượng bẻ gãy của bất kỳ sự phân tích mã của một ai nhận ra cấu trúc thuật toán. Trong ví dụ này, điều chúng ta có là bản chất của mật mã Hill được áp dụng cho dữ liệu nhị phân thay vì các ký tự. Một hệ thống tuyến tính đơn giản như hệ thống này là quá dễ bị tấn công.
Mật mã Feistel
Feistel [FEIS73] đã đề nghị một mật mã khối gần như lý tưởng bằng cách tận dụng ý niệm về một sản phẩm mật mã mà là kết quả của sự thực hiện hai hay nhiều phép mã hóa đơn giản nối tiếp tuần tự sao cho kết quả sau cùng hay sản phẩm là một mật mã mạnh hơn. Sự cần thiết của phương pháp là phát triển một mật mã khối với chiều dài khóa k bit và một khối chiều dài n bit, cho phép tổng cộng đến 2k khả năng biến đổi, thay vì là 2n! được cung cấp cho khối mã hóa lý tưởng.
Trên thực tế, Feistel đề nghị việc sử dụng một mật mã thế chỗ cho các hình thức mã hóa thay thế và hoán vị. Thực sự thì đây là đề nghị của Claude Shannon nhằm phát triển một sản phẩm mật mã thay cho các hàm xáo trộn và khuếch tán [SHAN49]. Chúng ta sẽ nghiên cứu các khái niệm về chúng tiếp theo đây và rồi sẽ bàn về mật mã Feistel. Nhưng trước hết, đáng để biết về sự kiện: cấu
trúc mật mã Feistel, ra đời vào khoảng một phần tư cuối cùng của thế kỷ trước và nó, dựa trên sự đề nghị của Shannon vào năm 1945, là cấu trúc được sử dụng bởi nhiều mật mã khối đối xứng đáng chú ý mà vẫn được sử dụng hiện nay.
Xáo trộn và khuếch tán
Các thuật ngữ xáo trộn và khuếch tán được giới thiệu bởi Claude Shannon. Giả thiết rằng đối phương có kiến thức nào đó về các đặc trưng thống kê của plaintext. Ví dụ, trong thông điệp đọc được của một ngôn ngữ nào đó, phân bố tần số đối với các ký tự khác nhau có thể đã biết. Hoặc có thể có các từ hay cụm từ thường xuất hiện trong thông điệp. Nếu các thống kê này bằng cách nào đó được phản ánh trong ciphertext, kẻ bẻ mã rất có thể suy luận được khóa mã hay một phần của khóa hay ít nhất là một tập khóa mà có thể chứa khóa chính xác. Shannon nói đến một mật mã mạnh đến mức lý tưởng, tất cả các thống kê về ciphertext là độc lập với khóa sử dụng. Mật mã thay thế bất kỳ nào đó mà chúng ta đã thảo luận (Hình 1) là một mật mã như thế, nhưng như chúng ta thấy, nó không thực tế.
Khác với việc viện cầu đến các hệ thống lý tưởng, Shannon đề nghị hai phương pháp làm sụp đổ các phân tích mã kiểu thống kê: xáo trộn và khuếch tán. Với phương pháp xáo trộn, thống kê cấu trúc của plaintext bị loãng ra trong một phạm vi thống kê lớn của plaintext. Điều này đạt được bằng mỗi con số của plaintext ảnh hưởng tới giá trị của nhiều số trong pt; nói chung điều này là tương đương với mỗi con số của ciphertext ảnh hưởng tới nhiều con số của plaintext. Một ví dụ về phương pháp xáo trộn là mã\ hóa một thông điệp M = m1, m2, m3, … gồm các ký tự với một phép lấy trung bình:
26 mod m y 1 i n n = ∑ = + k i
thêm liên tiếp k ký tự để có một ký tự ciphertext yn. Ai đó đều có thể chứng minh rằng thống kê cấu trúc của plaintext đã bị che giấu đi. Do đó, tần số ký tự trong ciphertext sẽ là gần với plaintext; các tần số chùm mẫu tự cũng sẽ gần với
plaintext và v.v…. Trong một khối mật mã nhị phân, phương pháp xáo trộn có thể đạt được bằng cách lặp lại việc thi hành một hoán vị nào đó trên dữ liệu theo sau bởi sự áp dụng một hàm cho hoán vị đó; và hiệu ứng là các bit từ các vị trí khác nhau trong plaintext được biến thành bit đơn trong ciphertext.
Mọi khối mật mã đều yêu cầu một sự biến đổi từ một khối plaintext thành một khối ciphertext với sự biến đổi tùy thuộc khóa. Cơ chế của sự khuếch tán đòi hỏi tạo ra quan hệ thống kê giữa plaintext và ciphertext càng phức tạp càng tốt để ngăn trở các cố gắng suy luận ra khóa. Theo hướng khác, sự xáo trộn cần tạo ra quan hệ giữa thống kê về ciphertext và giá trị của khóa mã phức tạp nhất có thể được và cũng để ngăn cản các cố gắng tìm ra được khóa mã. Do vậy, kể cả khi mà đối phương có được các xử lý thống kê trên ciphertext thì cách mà khóa mã được dùng để đưa ra ciphertext đó là quá phức tạp để tìm được khóa. Điều này đạt được nhờ việc dùng một thuật toán thay thế phức tạp. Ngược lại, một hàm thay thế tuyến tính sẽ thêm vào một ít xáo trộn.
Cấu trúc mật mã Feistel
Hình 2. Mạng Feistel cổ điển
Hình 2 miêu tả cấu trúc đã được định nghĩa bởi Feistel. Các đầu vào của thuật toán mã hóa là một khối plaintext có chiều dài 2w bit và một khóa K. Khối plaintext được chia thành hai nửa, L0 và R0. Hai nửa dữ liệu đi qua n vòng xử lý rồi được tổ hợp lại thành khối ciphertext. Mỗi vòng xử lý i có các đầu vào Li-1 và Li-1 lấy từ vòng trước cùng với khóa con Ki, lấy từ khóa K tổng. Nói chung, các khóa con Ki đều khác nhau và khác khóa K.
Tất cả các vòng đều có chung cấu trúc. Một phép thay thế được thực hiện trên nửa bên trái của dữ liệu bằng cách áp dụng một hàm vòng đơn F cho nửa phải của dữ liệu, rồi lấy XOR đầu ra của hàm đó với nửa trái của dữ liệu. Hàm vòng đơn có cấu trúc chung cho mỗi vòng nhưng làm việc với từng khóa con Ki khác nhau của
vòng tương ứng. Theo sau phép thay thế này, một phép hoán vị được thi hành bằng cách hoán đổi giá trị của hai nửa dữ liệu1. Cấu trúc này là một dạng cụ thể của mạng thay thế - hoán vị substitution-permutation network (SPN) đã được Shannon đề nghị.
Sự thi hành chính xác mạng Feistel tùy thuộc vào sự lựa chọn của các đặc tính tham số và thiết kế sau đây:
Kích thước khối: Kích thước khối càng lớn càng được bảo mật nhưng làm giảm tốc độ mã hóa/giải mã của thuật toán. Bảo mật tốt đạt được khi có sự khuếch tán tốt. Thông thường, một khối 64 bit được coi là một phép cân bằng các yếu tố chấp nhận được và nó gần như là phổ biến trong tất cả các thiết kế thuật toán mật mã khối. Tuy nhiên thuật toán AES mới sử dụng một kích thước khối 128 bit.
Kích thước khóa: Kích thước khóa càng lớn càng được bảo mật nhưng làm giảm tốc độ mã hóa/giải mã của thuật toán. Bảo mật càng tốt hơn nếu có xáo trộn tốt làm tăng khả năng chống lại các tấn công thô bạo. Các kích thước khóa 64 bit hay nhỏ hơn một chút hiện nay đang được coi là không thỏa đáng và, 128 bit đã trở thành kích thước chung.
Số vòng xử lý: Bản chất của mật mã Feistel là một vòng đơn đưa ra tính bảo mật không cao nhưng nhiều vòng sẽ làm tăng an ninh. Số vòng thường là 16.
Thuật toán sinh khóa con: Thuật toán càng phức tạp sẽ càng làm khó phân tích mã cho đối phương.
Hàm vòng đơn: Một lần nữa, càng phức tạp càng có khả năng chống lại khả năng phân tích phá mã.
Còn hai cân nhắc khác trong thiết kế mật mã Feistel:
Phần mềm mã hóa/giải mã: Trong nhiều trường hợp, sự mã hóa được nhúng trong các ứng dụng hay là các chức năng tiện ích để không cần thiết phải thực hiện bằng thiết bị phần cứng. Theo đó, tốc độ của thuật toán trở nên liên quan mật thiết. Dễ phân tích: Mặc dù chúng ta mong muốn tạo ra thuật toán phức tạp nhất có thể đối với những kẻ bẻ mã, nhưng vẫn còn có những lợi ích khi tạo ra các thuật toán dễ phân tích. Nghĩa là, nếu thuật toán rõ ràng, súc tích trong trình bày thì nó càng dễ dàng trong phân tích các tính dễ tổn thương và như thế sẽ dễ dàng hơn để phát triển để phát triển công cụ làm tăng sức mạnh thuật toán. Ví dụ, Blowfish là một thuật toán không dễ phân tích chức năng.
Thuật toán giải mã Feistel
Tiến trình giải mật mã Feistel về mặt bản chất cũng giống như tiến trình mã hóa. Quy tắc như sau: Sử dụng ciphertext làm đầu vào của thuật toán, nhưng dùng các khóa con Ki theo trật tự ngược lại với trật tự đã dùng trong mã hóa. Tức là, dùng Kn ở vòng đầu, Kn-1 ở vòng thứ hai v.v… cho đến khi Ki được dùng ở vòng cuối cùng. Đây là một đặc tính hay bởi vì theo cách đó chúng ta không cần phải thi hành hai thuật toán khác nhau, một cho mã hóa và một cho giải mã. Xét hình 3 để quan sát sự nghịch đảo trật tự khóa con được áp dụng cho cùng thuật toán mã hóa. Hình 3 minh họa tiến trình mã hóa đi xuống ở nửa bên trái và giải mã đi ngược lên ở nửa hình bên phải của thuật toán 16 vòng (kết quả là như
nhau cho bất cứ số vòng nào). Để rõ ràng hơn, chúng ta sử dụng các ký hiệu LEi
và REi đối với dữ liệu di chuyển qua thuật toán mã hóa, các ký hiệu LDi và RDi
đối với dữ liệu di chuyển qua thuật toán giải mã. Sơ đồ này biểu thị rằng, tại mỗi vòng, giá trị trung gian của tiến trình giải mã là bằng với giá trị tương ứng của tiến trình mã hóa với hai nửa dữ liệu tráo đổi. Để phát biểu theo cách khác, đặt đầu ra của vòng mã hóa thứ i là LEi||REi (Li nối chuỗi với Ri). Sau đó đầu vào tương ứng cho vòng giải mã thứ 16i là REi||LEi hay tương tự như RD16-i||LD16-i.
Hãy khảo sát hình 3 để minh họa tính hợp lệ của sự khẳng định vừa rồi2. Sau vòng lặp cuối cùng của tiến trình mã hóa, hai nửa đầu ra được tráo đổi, như thế
ciphertext là RE16||LE16. Đầu ra của vòng đó là ciphertext. Bây giờ, lấy ciphertext đó như đầu vào của cùng thuật toán. Đầu vào của vòng đầu tiên RE16||LE16 bằng với 32 bit tráo đổi của đầu ra của vòng mã hóa thứ 16.
Bây giờ chúng ta muốn chỉ rõ rằng đầu ra của vòng giải mã đầu tiên bằng với một tráo đổi 32-bit đầu vào của vòng mã hóa thứ 16. Trước hết, xét tiến trình mã hóa. Ta thấy rằng LE16 = RE15 RE16 = LE15 x F(RE15, K16) Khi giải mã LD1 = RD0 = LE16 = RE15 RD1 = LD0 x F(RD0, K16) = RE16 x F(RE15, K16)
= [LE15 x F(RE15, K16)] x F(RE15, K16) Phép XOR có các tính chất sau: [A x B] x C = A x [B x C] D x D = 0
E x 0 = E
Nên, chúng ta có LD1 = RE15 and RD1 = LE15. Bởi vậy, đầu ra vòng giải mã đầu tiên là LE15||RE15, chính là 32-bit tráo đổi của đầu vào vòng mã hóa thứ 16. Sự tương đồng này đúng với tất cả 16 vòng lặp. Chúng ta có thể đúc kết lại tiến trình này dưới dạng chung. Đối với vòng lặp mã hóa thứ i trong thuật toán mã hóa LEi = REi-1