1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Báo cáo bài tập lớn cơ sở an toàn và bảo mật thông tin đề tài gửi, nhận một file dữ liệu giữa hai máy sử dụng thuật toán aes bằng ngôn ngữ java

42 8 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Báo cáo bài tập lớn cơ sở an toàn và bảo mật thông tin đề tài gửi, nhận một file dữ liệu giữa hai máy sử dụng thuật toán aes bằng ngôn ngữ java
Tác giả Phùng Hoài Thương, Phạm Trường Minh
Người hướng dẫn Th.S Nguyễn Đào Trường
Trường học Học Viện Kỹ Thuật Mật Mã Khoa Công Nghệ Thông Tin
Chuyên ngành An Toàn và Bảo Mật Thông Tin
Thể loại Báo cáo bài tập lớn
Năm xuất bản 2023
Thành phố Hà Nội
Định dạng
Số trang 42
Dung lượng 6,05 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Cấu trúc

  • CHƯƠNG 1. CƠ SỞ LÝ THUYẾT (9)
    • 1.1 Giới thiệu chung (9)
    • 1.2 Xây dựng thuật toán (10)
      • 1.2.1 Xây dựng bảng S-box (10)
      • 1.2.2 Giải thuật sinh khóa phụ (12)
      • 1.2.3 Quá trình mã hóa (16)
      • 1.2.4 Quá trình giải mã (20)
    • 1.3 Lập trình Socket TCP/IP trong Java (22)
      • 1.3.1 Tổng quan về Socket (22)
      • 1.3.2 Lập trình TCP Socket với Java (24)
  • CHƯƠNG 2. THỰC NGHIỆM (26)
    • 2.1 Cài đặt thuật toán sinh khóa (26)
      • 2.1.1 Hàm RotWord (26)
      • 2.1.2 Hàm SubWord (27)
      • 2.1.3 Hàm XorRcon (27)
      • 2.1.4 Hàm KeyExpansion (27)
    • 2.2 Cài đặt thuật toán mã hóa (28)
      • 2.2.1 Hàm AddRoundKey (28)
      • 2.2.2 Hàm SubBytes (29)
      • 2.2.3 Hàm ShiftRows (29)
      • 2.2.4 Hàm MixColumns (30)
      • 2.2.5 Hàm MaHoaAES (31)
    • 2.3 Cài đặt thuật toán giải mã (32)
      • 2.3.1 Hàm InvShiftRows (32)
      • 2.3.2 Hàm InvSubBytes (33)
      • 2.3.3 Hàm InvMixColumns (33)
      • 2.3.4 Hàm GiaiMaAES (33)
    • 2.4 Cài đặt giao thức TCP/IP (34)
      • 2.4.1 Server (34)
      • 2.4.2 Client (36)
    • 2.5 Kết quả thực nghiệm (37)
  • KẾT LUẬN (41)
  • TÀI LIỆU THAM KHẢO (42)

Nội dung

HỌC VIỆN KỸ THUẬT MẬT MÃKHOA CÔNG NGHỆ THÔNG TIN BÁO CÁO BÀI TẬP LỚN CƠ SỞ AN TOÀN VÀ BẢO MẬT THÔNG TIN ĐỀ TÀI: Gửi, nhận một file dữ liệu giữa hai máy sử dụng thuật toán AES bằng ngôn n

CƠ SỞ LÝ THUYẾT

Giới thiệu chung

Trong mật mã học, mã hóa là quá trình chuyển đổi thông tin từ định dạng dễ hiểu sang dạng không thể hiểu được mà không có công cụ giải mã Ngược lại, giải mã là phương pháp khôi phục thông tin đã được mã hóa về dạng ban đầu, thực hiện quá trình ngược lại của mã hóa.

AES, hay Tiêu chuẩn mã hóa nâng cao, là một thuật toán mã hóa khối được chính phủ Hoa Kỳ công nhận và áp dụng làm tiêu chuẩn mã hóa.

 Thuật toán được xây dựng dựa trên Rijndael Cipher phát triển bởi 2 nhà mật mã học người Bỉ: Joan Daemen và Vincent Rijmen.

AES hoạt động với các khối dữ liệu 128 bit và hỗ trợ độ dài khóa là 128 bit, 192 bit hoặc 256 bit Các khóa mở rộng được sử dụng trong quá trình mã hóa được tạo ra thông qua thủ tục sinh khóa Rijndael.

Thuật toán AES thực hiện hầu hết các phép toán trong một trường hữu hạn của các byte Dữ liệu đầu vào 128 bit được chia thành 16 byte, có thể được sắp xếp thành 4 cột, mỗi cột gồm 4 phần tử, tạo thành một ma trận 4x4 gọi là ma trận trạng thái.

 Tùy thuộc vào độ dài của khóa sử dụng 128 bit, 192 bit hay 256 bit mà thuật toán có số lần lặp khác nhau

 Các bước xử lý chính : o Quá trình mở rộng khóa sử dụng o Quá trình mã hóa o Quá trình giải mã

Xây dựng thuật toán

Bảng S-box thuận được tạo ra bằng cách xác định nghịch đảo cho các giá trị trong trường hữu hạn GF(2^8) thông qua đa thức x^8 + x^4 + x^3 + x + 1 Giá trị 0 không có nghịch đảo và được ánh xạ thành 0, trong khi các nghịch đảo khác được chuyển đổi thông qua phép biến đổi affine.

Công thức tính các giá trị bảng S-box và bảng S-box tương ứng

Hình 1.1 Công thức và bảng S-box

Trong đó, mỗi bit sẽ được tính theo công thức:

 yi là bit thứ i của byte cần chuyển đổi

 xi là bit thứ i của byte kết quả sau khi chuyển đổi

 ci là bit thứ i của byte có giá trị là H63 = B01100011. 1.2.1.2 Bảng S – box nghịch đảo

Công thức và bảng S – box nghịch đảo được xây dùng như sau :

Hình 1.2 Công thức và S-box nghịch đảo

Trong đó mỗi bit sẽ được tính theo công thức:

 xi là bit thứ i của byte cần chuyển đổi

 yi là bit thứ i của byte kết quả sau khi chuyển đổi

 di là bit thứ i của byte có giá trị là H05 = B00000101.

1.2.2 Giải thuật sinh khóa phụ

Chức năng KeyExpansion tính toán khóa vòng cho quá trình mã hóa và tạo ngõ ra Kết quả của KeyExpansion là một khóa vòng phục vụ cho chức năng AddRoundKey Đối với mã hóa AES-128, có 10 khóa vòng, bao gồm 9 lần AddRoundKey trong quá trình mã hóa và 1 lần ở bước tạo ngõ ra.

Chức năng KeyExpansion được thực hiện thông qua 4 chức năng là RotWord, SubWord, AddRcon và AddW.

Khóa mã hóa AES-128 sử dụng một khóa mã 128 bit, được chia thành 4 word, mỗi word có kích thước 4 byte, ký hiệu là w[j] với j là số nguyên Tổng số từ trong mã hóa này là 44, được đánh số từ 0 đến 43, bao gồm 4 từ cho khóa mã (w[0], w[1], w[2], w[3]) và 4 từ cho mỗi khóa vòng, với khóa vòng 1 là w[4] đến w[7] và khóa vòng 10 là w[40] đến w[43].

Từ w[j] tính theo công thức sau, với 3 < j < 44. w[j] = AddW[j - 4] = w[j - 1] + w[j - 4] w[j = 4∗ n] = AddW[j - 4] = trans(w[j - 1])+ w[j - 4]

Khi tính toán các từ ở vị trí j là bội số của 4, như w[4], w[8], và w[40], cần phải biến đổi w[j-1] qua ba chức năng RotWord, SubWord và AddRcon, được gọi là trans(w[j-1]), trước khi thực hiện phép XOR với w[j-4].

Khóa mã key ở mục 1 được sử dụng để minh họa việc tính toán khóa vòng. Khóa mã key[127:0] được chia làm 4 từ như biểu thức sau: w[0] = 2b7e1516 w[1] = 28aed2a6 w[2] = abf71588 w[3] = 09cf4f3c

Để tính toán khóa vòng 1, cần thực hiện các phép tính cho 4 từ w[4], w[5], w[6] và w[7] Trước tiên, trans(w[3]) phải được tính thông qua ba chức năng RotWord, SubWord và AddRcon Kết quả là w[4] = AddW[0] = trans(w[3]) + w[0] và w[5] = AddW[1].

Chức năng RotWord thực hiện quay trái từ w[j] một byte.

Hình 1.4 Thực thi RotWord cho từ w[3]

Chức năng SubWord thực hiện thay thế các phi tuyến từng byte của kết quả RotWord theo bảng sS-box

Hình 1.6 Thực thi SubWord khi chuyển đổi từ w[3]

Chức năng AddRcon thực hiện phép XOR giữa kết quả SubWord và giá trị Rcon[j/4], với j là bội số của 4 Có 10 giá trị Rcon[j/4] tương ứng với 10 lần tính toán khóa vòng Kết quả của chức năng AddRcon sẽ là biến đổi cuối cùng của trans(w[j-1]).

Hình 1.8 Thực thi AddRcon khi chuyển đổi từ w[3]

Chức năng AddW thực hiện XOR w[j-4] với w[j-1] hoặc trans(w[j-1]) như công thức để tạo ra khóa vòng.

Hình 1.9 Thực thi AddW để tạo khóa vòng 1

Hình 1.10 Sơ đồ quá trình mã hóa

Quá trình mã hóa bao gồm các bước :

 Khởi động vòng lặp o AddRoundKey — Mỗi cột của trạng thái đầu tiên lần lượt được kết hợp với một khóa con theo thứ tự từ đầu dãy khóa.

Trong quá trình mã hóa, có bốn bước chính: SubBytes, nơi mỗi byte trong trạng thái được thay thế bằng một byte khác theo bảng S-box; ShiftRows, trong đó các hàng của trạng thái được dịch chuyển vòng theo số bước khác nhau; MixColumns, là quá trình trộn các cột trong khối thông qua một phép biến đổi tuyến tính; và cuối cùng là AddRoundKey, bước thêm khóa vòng vào trạng thái.

 Vòng lặp cuối o SubBytes o ShiftRows o AddRoundKey

Tại chu trình cuối thì bước MixColumns không thực hiện.

 Được áp dụng từ vòng lặp thứ 1 tới vòng lặp Nr

 Trong biến đổi Addroundkey(), một khóa vòng được cộng với state bằng một phép XOR theo từng bit đơn giản.

 Mỗi khóa vòng gồm có 4 từ (128 bit) được lấy từ lịch trình khóa 4 từ đó được cộng vào mỗi cột của state, sao cho:

 Biến đổi SubBytes() thay thế mỗi byte riêng rẽ của state [Sr,c] bằng một giá trị mới [S’ r,c] sử dụng bảng thay thế (S - box) được xây dựng ở trên.

 Ví dụ, byte cần thay thế là H08 thì dò ở hàng số 0 và cột số 8 trong bảng S-box sẽ được kết quả là 30.

 Trong biến đổi ShiftRows(), các byte trong ba hàng cuối cùng của trạng thái được dịch vòng đi các số byte khác nhau (độ lệch) Cụ thể :

S’r,c = Sr,(c + shift ( r, Nb)) mod Nb (Nb = 4)

 Trong đó giá trị dịch shift (r, Nb) phụ thuộc vào số hàng r như sau:

Hàng đầu tiên giữ nguyên, trong khi ba hàng còn lại được dịch theo quy tắc: hàng thứ hai dịch vòng trái một lần, hàng thứ ba dịch vòng trái hai lần, và hàng thứ tư dịch vòng trái ba lần.

 Biến đổi MixColumns() tính toán trên từng cột của state Các cột được coi như là đa thức trong trường GF(28) và nhân với một đa thức a(x) với: a(x) = (03)x^3 +(01)x^2 +(01)x + (02)

 Biến đổi này có thể được trình bày như phép nhân một ma trận, mà mỗi byte được hiểu như là một phần tử trong trường GF(28): s’(x) = a(x) xor s(x):

 Mô tả bằng ma trận như sau :

Mã hóa là quá trình chuyển đổi một bản rõ (plaintext) thành bản mã (ciphertext) bằng cách sử dụng một khóa mã (key), nhằm bảo vệ thông tin gốc Giải mã, ngược lại, là quá trình khôi phục bản rõ từ bản mã thông qua việc sử dụng phương pháp nghịch đảo của mã hóa.

Thuật toán giải mã khá giống với thuật toán mã hóa về mặt cấu trúc nhưng 4 hàm sử dụng là 4 hàm ngược của quá trình mã hóa.

Bảng 1.1 So sánh số vòng mã hóa và giải mã

 Bản chất hàm InvAddRoundKey chính là hàm AddRoundKey vì khi xor 2 lần thì nó sẽ quay về chính nó.

InvShiftRows là chức năng đảo ngược của ShiftRows, thực hiện việc quay phải từng hàng của ma trận trạng thái Quá trình này diễn ra theo byte với hệ số quay tăng dần từ 0 đến 3 Cụ thể, hàng đầu tiên giữ nguyên vị trí, hàng thứ hai quay một byte, hàng thứ ba quay hai byte và hàng thứ tư quay ba byte.

Chức năng InvSubBytes thực hiện việc thay thế từng byte của ma trận trạng thái bằng các giá trị quy định trong chuẩn AES Giá trị thay thế cho InvSubBytes được xác định bởi bảng S-box đảo (Inverse S-box).

 Ví dụ, byte cần thay thế là Ha7 thì dò ở hàng "a" và cột số 7 trong bảng S-box đảo sẽ được kết quả là H89.

Tương tự như MixColumns nhưng đa thức nhân ở đây đã được thay đổi a(x) = (0e)x^3 +(0b)x^2 +(0d)x + (09)

Lập trình Socket TCP/IP trong Java

Trong mạng máy tính, các mô hình tham chiếu với kiến trúc phần tầng như OSI và TCP/IP đóng vai trò quan trọng trong việc hỗ trợ trao đổi thông tin giữa các ứng dụng trên nhiều máy tính khác nhau.

Hình 1.18 Mô hình OSI và TCP/IP

Dữ liệu sẽ được đóng gói từ tầng trên cùng đến tầng vật lý, sau đó tầng vật lý sẽ chuyển dữ liệu đến máy bên nhận Tại đây, dữ liệu sẽ được giải mã từ tầng vật lý lên tầng ứng dụng.

Socket là giao diện giao tiếp giữa tầng ứng dụng và tầng giao vận, cho phép các ứng dụng gửi và nhận thông điệp Nó được quản lý bởi hệ điều hành và được ràng buộc với một mã số cổng (Port Number) để xác định ứng dụng gửi hoặc nhận thông điệp.

Tầng giao vận bao gồm hai phương thức chính là TCP (Transmission Control Protocol) và UDP (User Datagram Protocol), dẫn đến hai loại socket cơ bản: Stream Socket sử dụng TCP để truyền dòng bytes và Datagram Socket sử dụng UDP để truyền gói tin Trong ngôn ngữ lập trình Java, chúng ta có ba loại socket khác nhau.

1 Stream Socket (TCP) : Tạo luồng dữ liệu hai chiều, đáng tin cậy, có trình tự và không trùng lặp, dữ liệu chỉ được gửi/nhận khi có đã có liên kết Dùng với Socket Class của java.

2 Datagram Socket (UDP): Có thể nhận dữ liệu không theo tình tự, trùng lặp Dùng với DatagramSocket Class.

3 Multicast Socket : cho phép dữ liệu được gửi đến nhiều bên nhận một lúc Dùng với DatagramSocket Class.

Socket được hỗ trợ trên nhiều ngôn ngữ như C, Java, Pearl, Python,… Sau đây là một ví dụ lập tình socket với Java.

1.3.2 Lập trình TCP Socket với Java

Đúng với đặc điểm của giao thức TCP, việc thiết lập một kết nối hai chiều là cần thiết trước khi máy chủ và máy khách có thể bắt đầu trao đổi thông điệp.

Ban đầu, phía server tạo Socket được ràng buộc với một cổng (port number) để chờ nhận yêu cầu từ phía client.

Client yêu cầu server bằng cách tạo một Socket TCP với địa chỉ IP và port number tương ứng Khi Socket được tạo, client TCP thiết lập liên kết với server TCP và chờ nhận chấp nhận kết nối TCP đảm bảo dịch vụ truyền tin cậy và có thứ tự giữa client và server, với mỗi thông điệp đều nhận được xác nhận trả về.

Sau đây là một ví dụ ứng dụng đơn giản về lập trình TCP Socket với Java.

 Client đọc dòng văn bản nhập từ bàn phím người dùng , gửi tới server qua Socket

 Server đọc các dòng văn bản gửi từ Socket

 Server sẽ chuyển lại dòng văn bản kèm theo “Server accepted” tới phía client qua Socket

 Client đọc dòng văn bản từ socket và in ra dòng văn bản nhận được từ server

Hình 1.21 Quá trình gửi-nhận tin giữa Client-Server

Mỗi phía server và client đều có hai luồng dữ liệu: một luồng ra từ Socket để gửi thông điệp và một luồng vào từ Socket để nhận thông điệp Do đó, mỗi bên sẽ có hai biến input và output, cụ thể là inFromServer, outToServer và inFromClient, outToClient.

THỰC NGHIỆM

Cài đặt thuật toán sinh khóa

2.1.1 Hàm RotWord private static int rotWord(int word) { return (word >> 24);

- Mục đích : dịch trái 8 bit của 1 word o Ta sẽ lấy byte234 dịch trái 8 bit và nối với byte đầu o Để lấy được byte đầu, ta dịch phải word 24 bit

- Chú ý : & 0xFF để lấy ra 1 byte

2.1.2 Hàm SubWord private static int subWord(int word) { int subWord = 0; for (int i = 24; i >= 0; i -= 8) { int in = word >> 24; subWord |= sBox[in] 24);

} return s; //bổ sung khóa mỗi vòng

- Cách cài đặt khá đơn giản chỉ cần lấy từng cột của ma trận trạng thái XOR từng cột của ma trận KEY

2.2.2 Hàm SubBytes private int[][] subBytes(int[][] state) { for (int i = 0; i < 4; i++) { for (int j = 0; j < Nb; j++) { state[i][j] = subWord(state[i][j]) & 0xFF;

- Hàm này thực hiện lấy từng kí tự trong mảng trạng thái đối chiếu trong S-box, tương tự với hàm SubWord.

2.2.3 Hàm ShiftRows private int[][] shiftRows(int[][] state) { int temp1, temp2, temp3, i; temp1 = state[1][0]; for (i = 0; i < Nb - 1; i++) { state[1][i] = state[1][(i + 1) % Nb];

} state[1][Nb - 1] = temp1; temp1 = state[2][0]; temp2 = state[2][1]; for (i = 0; i < Nb - 2; i++) { state[2][i] = state[2][(i + 2) % Nb];

} state[2][Nb - 2] = temp1; state[2][Nb - 1] = temp2; temp1 = state[3][0]; temp2 = state[3][1]; temp3 = state[3][2]; for (i = 0; i < Nb - 3; i++) { state[3][i] = state[3][(i + 3) % Nb];

} state[3][Nb - 3] = temp1; state[3][Nb - 2] = temp2; state[3][Nb - 1] = temp3; return state;

Ta thực hiện việc lấy từng ký tự trong từng hàng của mảng trạng thái, dịch vòng các số byte tương ứng 0, 1, 2, 3, và cuối cùng ghép các byte lại để thu được kết quả.

- Xây dựng hàm Mul private static int mult(int a, int b) { int sum = 0; while (a != 0) { if ((a & 1) != 0) { sum = sum ^ b;

The function `mixColumns` processes each column of the state matrix by performing specific multiplications and XOR operations For each column, it calculates four temporary values: `temp0`, `temp1`, `temp2`, and `temp3`, using a combination of the `mult` function with constants 0x02 and 0x03 These temporary values are then assigned back to the respective positions in the state matrix, effectively transforming the column data This operation is crucial for enhancing the security of the encryption process.

Trước khi thực hiện phép nhân, cần dịch vòng các giá trị để lấy từng byte Sau khi nhân các giá trị 2, 3, 1 theo thứ tự tương ứng, mảng kết quả sẽ được dịch ngược để thu được kết quả cuối cùng.

2.2.5 Hàm MaHoaAES private void cipher(int[][] in, int[][] out) { for (int i = 0; i < in.length; i++) {

System.arraycopy(in[i], 0, out[i], 0, in.length); } actual = 0; addRoundKey(out, actual); for (actual = 1; actual < Nr; actual++) { subBytes(out); shiftRows(out); mixColumns(out); addRoundKey(out, actual);

} subBytes(out); shiftRows(out); addRoundKey(out, actual);

Hàm mã hóa được thực hiện qua ba quá trình, với các hàm tương ứng sử dụng khóa trong từng vòng lặp Độ dài khóa chủ yếu ảnh hưởng đến số vòng lặp trong quá trình mã hóa.

Cài đặt thuật toán giải mã

Thuật toán giải mã được cài đặt tương tự như thuật toán mã hóa theo các bước tương ứng, ta sử dụng lại hàm AddRoundKey.

2.3.1 Hàm InvShiftRows private int[][] invShiftRows(int[][] state) { int temp1, temp2, temp3, i;

// row 1; temp1 = state[1][Nb - 1]; for (i = Nb - 1; i > 0; i ) { state[1][i] = state[1][(i - 1) % Nb];

// row 2 temp1 = state[2][Nb - 1]; temp2 = state[2][Nb - 2]; for (i = Nb - 1; i > 1; i ) { state[2][i] = state[2][(i - 2) % Nb];

// row 3 temp1 = state[3][Nb - 3]; temp2 = state[3][Nb - 2]; temp3 = state[3][Nb - 1]; for (i = Nb - 1; i > 2; i ) { state[3][i] = state[3][(i - 3) % Nb];

} state[3][0] = temp1; state[3][1] = temp2; state[3][2] = temp3; return state;

 Hàm được cài đặt tương tự với hàm ShifRows.

2.3.2 Hàm InvSubBytes private int[][] invSubBytes(int[][] state) { for (int i = 0; i < 4; i++) { for (int j = 0; j < Nb; j++) { state[i][j] = invSubWord(state[i][j]) & 0xFF;

 Hàm thực hiện chức năng giống hàm SubBytes tuy nhiên ta lấy giá trị trong bảng S-box nghịch đảo

Hàm invMixColumns được xây dựng tương tự như hàm MixColumns, với việc thực hiện phép nhân các hệ số E, D, B, 9 và sau đó thực hiện phép XOR giữa các giá trị Trong hàm này, ta lặp qua từng cột của trạng thái và tính toán các giá trị tạm thời temp0, temp1, temp2, temp3 bằng cách nhân các phần tử của cột với các hệ số tương ứng và thực hiện phép XOR Cuối cùng, các giá trị tạm thời này được gán lại cho các phần tử trong cột của trạng thái.

2.3.4 Hàm GiaiMaAES private void decipher(int[][] in, int[][] out) { for (int i = 0; i < in.length; i++) {

System.arraycopy(in[i], 0, out[i], 0, in.length); } actual = Nr; addRoundKey(out, actual); for (actual = Nr - 1; actual > 0; actual ) { invShiftRows(out); invSubBytes(out); addRoundKey(out, actual); invMixColumnas(out);

} invShiftRows(out); invSubBytes(out); addRoundKey(out, actual);

 Các vòng trong giải mã cũng được thực hiện theo các hàm con tương ứng với khóa trong từng vòng lặp đã trình bày trong lý thuyết.

Cài đặt giao thức TCP/IP

String inputKey = keyTextField.getText(); if (!(inputKey.length() == 16 || inputKey.length() == 24 || inputKey.length() == 32)) {

// Valid key length, store input key in a variable or do something with it

JOptionPane.showMessageDialog(this, "Độ dài key là 16, 24 hoặc 32 ký tự");

FileInputStream fis = new FileInputStream(file);

OutputStream os = socket.getOutputStream(); byte[] buffer = new byte[4096]; int bytesRead = 0; while ((bytesRead = fis.read(buffer)) != -1) { cipher = new AES(key); buffer = cipher.ECB_encrypt(buffer); os.write(buffer, 0, bytesRead);

} fis.close(); os.close(); socket.close();

JOptionPane.showMessageDialog(this, "Gửi file thành công"); } catch (IOException ex) { ex.printStackTrace();

JOptionPane.showMessageDialog(this, "Gửi file thất bại");}

- Server tạo Socket được ràng buộc với một cổng (port number) để chờ nhận yêu cầu từ phía client.

System.out.println("Máy chủ bắt đầu Đang đợi các kết nối đến ");

System.out.println("Kết nối thành lập Đang nhận tệp ");

InputStream is = socket.getInputStream(); byte[] buffer = new byte[4096]; int bytesRead = 0;

FileOutputStream fos = new FileOutputStream("D:\\inteliJ\\co-so-bao-mat-an- toan\\computer-b\\src\\received_file.txt");

BufferedOutputStream bos = new BufferedOutputStream(fos); while ((bytesRead = is.read(buffer)) != -1) {

// Giải mã dữ liệu được nhận về

// buffer = cipher.ECB_decrypt(buffer); bos.write(buffer, 0, bytesRead); decryptArea.append(new String(buffer, 0, bytesRead));

} bos.close(); is.close(); socket.close(); serverSocket.close();

System.out.println("Nhận file thành công");

System.out.println("Nhận file thất bại");

Client gửi yêu cầu đến server bằng cách tạo một Socket TCP trên máy của mình, kèm theo địa chỉ IP và số cổng (port number) tương ứng trên máy server Khi Socket được tạo, client TCP sẽ thiết lập một kết nối với server TCP và chờ nhận sự chấp nhận kết nối từ phía server.

Kết quả thực nghiệm

- Client: máy nhận sẽ nhận được chuỗi dạng mã hóa, sau đó user sẽ nhập key

Tại File nhận đã giải mã:

Ngày đăng: 25/05/2023, 19:58

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w