Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 61

HỌC VIỆN KỸ THUẬT MẬT MÃ

KHOA CÔNG NGHỆ THÔNG TIN

BÁO CÁO MÔN HỌC

CƠ SỞ AN TOÀN VÀ BẢO MẬT THÔNG TIN

Đề tài:

VIẾT CHƯƠNG TRÌNH MÃ HÓA VÀ GIẢI MÃ MẬT MÃ DES SỬ


DỤNG NGÔN NGỮ JAVA

Sinh viên thực hiện: NGUYỄN MINH THIỆU – CT040246

NGUYỄN CHÍ DŨNG - CT040210

Giảng viên hướng dẫn: TS. NGUYỄN ĐÀO TRƯỜNG

Hà Nội, 2023

1
NHẬN XÉT CỦA GIẢNG VIÊN

.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................
.................................................................................................................................

MỤC LỤC

2
LỜI MỞ ĐẦU.....................................................................................................................7

CHƯƠNG 1. CỞ SỞ LÝ THUYẾT....................................................................................8

1.1 Tổng quan về an toàn và bảo mật thông tin...............................................................8

1.1.1 Sự cần thiết an toàn và bảo mật thông tin......................................................8

1.1.2 Các mối đe dọa đối với một hệ thống và các biện pháp ngăn chặn...............8

1.1.3 Mục tiêu chung của an toàn bảo mật thông tin..............................................9

1.1.4 Các phương pháp bảo mật.............................................................................9

1.1.5 Các phương pháp mã hóa..............................................................................9

1.2 Mật mã DES............................................................................................................10

1.2.1 Giới thiệu về chuẩn mã hóa DES................................................................10

1.2.2 Đặc điểm của thuật toán DES......................................................................10

1.2.3 Phương pháp bảo mật..................................................................................10

1.2.4 Ưu nhược điểm............................................................................................11

1.2.5 Sơ đồ khối...................................................................................................13

1.3 Ứng dụng của DES..................................................................................................15

1.4 Giới thiệu về ngôn ngữ lập trình Java......................................................................15

1.4.1 Tổng quan về ngôn ngữ lập trình Java........................................................15

1.4.2 Điểm mạnh của ngôn ngữ Java....................................................................18

1.5 Giới thiệu về công nghệ WebSockets......................................................................19

1.5.1 Tổng quan về WebSockets..........................................................................19

1.5.2 Ưu nhược điểm của WebSockets................................................................20

1.6 Cài đặt môi trường lập trình Java............................................................................21

CHƯƠNG 2. XÂY DỰNG CHƯƠNG TRÌNH MÃ HÓA VÀ GIẢI MÃ MẬT MÃ DES


BẰNG NGÔN NGỮ JAVA..............................................................................................22

2.1 Mô tả thuật toán.......................................................................................................22

2.1.1 Quy trình mã hóa.........................................................................................24

3
2.1.2 Quy trình giải mã.........................................................................................26

2.1.3 Hàm F..........................................................................................................26

2.1.4 Quá trính tạo khóa con.................................................................................27

2.1.5 Hàm (ánh xạ) mở rộng (E)...........................................................................29

2.1.6 Hộp S – Box................................................................................................30

2.1.7 Hộp P-Box...................................................................................................30

2.2 Triển khai lập trình..................................................................................................31

2.2.1 Các modules sử dụng trong quá trình mã hóa và giải mã............................31

2.2.2 Code mã hóa................................................................................................33

2.2.3 Code giải mã................................................................................................34

KẾT QUẢ VÀ ĐÁNH GIÁ..............................................................................................37

3.1 Kết quả.....................................................................................................................37

3.2 Kết luận và đánh giá thuật toán DES.......................................................................39

3.3 Hướng phát triển tiếp theo.......................................................................................40

TÀI LIỆU THAM KHẢO.................................................................................................41

PHỤ LỤC..........................................................................................................................42

4
DANH MỤC HÌNH VẼ
Hình 1. 1 Chuẩn mã dữ liệu DES............................................................................11
Hình 1. 2 Sơ đồ khối chương trình DES.................................................................13
Hình 1. 3 Sơ đồ khối quá trình sinh khóa................................................................14
Hình 1. 4 Ngôn ngữ Java.........................................................................................16

Hình 2. 1 Sơ đồ mã hóa DES..................................................................................23


Hình 2. 2 Sơ đồ một vòng DES...............................................................................24

Hình 3. 1. Giao diện gửi file....................................................................................37


Hình 3. 2. Giao diện gửi file mã hóa thành công....................................................37
Hình 3. 3. Giao diện nhập key sai...........................................................................38
Hình 3. 4. Giao diện nhận file mã hóa.....................................................................38
Hình 3. 5. Giao diện nhận file mã hóa thành công..................................................39

5
DANH MỤC BẢNG
Bảng 1. Hoán vị IP.................................................................................................25
Bảng 2. Hoán vị IP-1..............................................................................................25
Bảng 3. Hoán vị PC-1.............................................................................................28
Bảng 4. Bảng dịch bit tại các vòng lặp DES..........................................................29
Bảng 5. Hoán vị PC-2.............................................................................................29
Bảng 6. Hàm mở rộng E.........................................................................................30
Bảng 7. 8 hộp S-Box..............................................................................................30
Bảng 8. Bảng hoán vị P..........................................................................................30

6
LỜI MỞ ĐẦU

Từ thời xa xưa con người đã quan tâm đến việc làm thế nào để bảo mật các
tài liệu quan trọng, đặc biệt là trong lĩnh vực quân sự, ngoại giao… Ngày nay với
sự ra đời của máy tính cũng như sự phát triển của lĩnh vực Công nghệ thông tin,
các tài liệu văn bản, giấy tờ quan trọng đều được số hóa và xử lý trên máy tính,
được truyền đi trong môi trường mà mặc định là không an toàn. Do đó yêu cầu về
việc có một cơ chế, giải pháp để bảo vệ sự an toàn và bí mật của các thông tin nhạy
cảm, quan trọng ngày càng trở nên cấp thiết, bảo mật thông tin chính là lĩnh vực
đảm bảo cho mục đích này.

Mã hóa thông tin là một mảng kiến thức quan trọng trong chương trình đào
tạo công nghệ thông tin, em muốn đi sâu vào một phương pháp mã hóa cụ thể để
cài đặt các hệ mã để mã hóa file, văn bản nên em chọn đề tài Phương pháp mã hóa
DES, đây là phương pháp làm tiền đề cho các phương pháp mã hóa tốt nhất hiện
nay.

Khi làm đồ án này, em muốn giới Thầy Cô và các bạn kiến thức tổng quan
về mã hóa, đồng thời trình bày về phương pháp mã hóa DES và quy trình bảo mật
thông tin của phương pháp mã hóa DES.

MỤC TIÊU:

 Đề tài giới thiệu về hệ thống mã hóa và đi sâu nghiên cứu phương pháp mã hóa
DES, đưa ra hướng dẫn cài đặt chương trình mã hóa văn bản, file văn bản một
cách đơn giản, hiệu quả.

PHẠM VI ĐỀ TÀI:

 Tìm hiểu mã hóa thông tin


 Tìm hiểu hệ mã chuẩn DES
 Cài đặt chương trình gửi nhận một file dữ liệu giữa 2 máy sử dụng thuật toán
DES bằng Java

7
CHƯƠNG 1. CỞ SỞ LÝ THUYẾT
1.1 Tổng quan về an toàn và bảo mật thông tin

1.1.1 Sự cần thiết an toàn và bảo mật thông tin

 Thông tin là một bộ phần quan trọng và là tài sản thuộc quyền sở hữu của các
tổ chức.
 Sự thiệt hại và lạm dụng thông tin không chỉ ảnh hưởng đến người sử dụng
hoặc các ứng dụng mà nó còn gây ra các hậu quả tai hại cho toàn bộ tổ chức
đó.
 Thêm vào đó sự ra đời của Internet đã giúp cho việc truy cập thông tin ngày
càng trở nên dễ dàng hơn.

1.1.2 Các mối đe dọa đối với một hệ thống và các biện pháp ngăn chặn

 Có 3 hình thức chủyếu đe dọa đối với hệ thống:


 Phá hoại: kẻ thù phá hỏng thiết bị phần cứng hoặc phần mềm hoạt động trên hệ
thống.
 Sửa đổi: Tài sản của hệ thống bị sửa đổi trái phép. Điều này thường làm cho hệ
thống không làm đúng chức năng của nó. Chẳng hạn như thay đổi mật khẩu,
quyền người dùng trong hệ thống làm họ không thểtruy cập vào hệ thống để
làm việc.
 Can thiệp: Tài sản bị truy cập bởi những người không có thẩm quyền. Các
truyền thông thực hiện trên hệ thống bị ngăn chặn, sửa đổi.
 Các đe dọa đối với một hệ thống thông tin có thể đến từ ba loại đối tượng như
sau:
 Các đối tượng từ ngay bên trong hệ thống (insider), đây là những người có
quyền truy cập hợp pháp đối với hệ thống.
 Những đối tượng bên ngoài hệ thống (hacker, cracker), thường các đối tượng
này tấn công qua những đường kết nối với hệ thống như Internet chẳng hạn.
 Các phần mềm (chẳng hạn như spyware, adware …) chạy trên hệ thống.

8
 Các biện pháp ngăn chặn:
 Điều khiển thông qua phần mềm: dựa vào các cơ chế an toàn bảo mật của hệ
thống nền (hệ điều hành), các thuật toán mật mã học
 Điều khiển thông qua phần cứng: các cơ chế bảo mật, các thuật toán mật mã
học được cứng hóa để sử dụng
 Điều khiển thông qua các chính sách của tổ chức: ban hành các qui định của tổ
chức nhằm đảm bảo tính an toàn bảo mật của hệ thống.

1.1.3 Mục tiêu chung của an toàn bảo mật thông tin

Ba mục tiêu chính của an toàn bảo mật thông tin:

 Tính bí mật (Confidentiality): Đảm bảo rằng thông tin không bị truy cập bất
hợp pháp. Thuật ngữ privacy thường được sử dụng khi dữ liệu được bảo vệ có
liên quan tới các thông tin mang tính cá nhân.
 Tính toàn vẹn (Integrity): Đảm bảo rằng thông tin không bị sửa đổi bất hợp
pháp.
 Tính sẵn dùng (availability): Tài sản luôn sẵn sàng được sử dụng bởi nhưng
người có thẩm quyền

1.1.4 Các phương pháp bảo mật

 Viết mật mã: đảm bảo tính bí mật của thông tin truyền thông
 Xác thực quyền: được sử dụng để xác minh, nhận dạng quyền hạn của các
thành viên tham gia.

1.1.5 Các phương pháp mã hóa

1.1.5.1 Mã hóa đối xứng

 Các khoá giống nhau được sử dụng cho việc mã hoá và giải mã
 Thuật toán mã hoá sử dụng khoá đối xứng thường được biết đến là DES (Data
Encryption Standard)

9
 Các thuật toán mã hoá đối xứng khác được biết đến như: -Triple DES, DESX,
GDES, RDES - 168 bit key -RC2, RC4, RC5 - variable length up to 2048 bits -
IDEA - basis of PGP - 128 bit key.

1.1.5.2 Mã hóa bất đối xứng

 Các khoá dùng cho mã hoá và giải mã khác nhau nhưng cùng một mẫu và là
cặp đôi duy nhất (khoá private/ public).
 Khoá private chỉ được biết đến bởi người gửi.
 Khoá public được biết đến bởi nhiều người hơn nó được sử dụng bởi những
nhóm người đáng tin cậy đã được xác thực.

1.2 Mật mã DES

1.2.1 Giới thiệu về chuẩn mã hóa DES

 Ngày 13/5/1973 ủy ban quốc gia về tiêu chuẩn của Mỹ công bố yêu cầu về hệ
mật mã áp dụng cho toàn quốc. Điều này đã đặt nền móng cho chuẩn mã hóa
dữ liệu, hay là DES.
 Lúc đầu Des được công ty IBM phát triển từ hệ mã Lucifer, công bố vào năm
1975. –
 Sau đó Des được xem như là chuẩn mã hóa dữ liệu cho các ứng dụng.

1.2.2 Đặc điểm của thuật toán DES

 DES là thuật toán mã hóa khối, độ dài mỗi khối là 64 bit .


 Khóa dùng trong DES có độ dài toàn bộ là 64 bit. Tuy nhiên chỉ có 56 bit thực
sự được sử dụng; 8 bit còn lại chỉ dùng cho việc kiểm tra.
 Des xuất ra bãn mã 64 bit.
 Thuật toán thực hiện 16 vòng
 Mã hoá và giải mã được sử dụng cùng một khoá.
 DES được thiết kế để chạy trên phần cứng.

10
1.2.3 Phương pháp bảo mật

DES là thuật toán mã hóa với input là khối 64 bit, output cũng là khối 64 bit. Khóa
mã hóa có độ dài 56 bit, thực ra chính xác hơn phải là 64 bit với các bit ở vị trí chia
hết cho 8 có thể sử dụng là các bit kiểm tra tính chẵn lẻ. Số khóa của không gian
khóa K là 256

Hình 1. 1 Chuẩn mã dữ liệu DES

Bản rõ 64 bit sẽ được sử dụng chia thành 2 nữa L 0 và R0. Các vòng có chức năng
giống nhau, nhận input là Li-1 và Ri-1 từ vòng truớc và sinh ra output là các xâu 32 bit
Li và Ri như sau:

Li=Ri-1;

Ri=Li-1  f(Ri-1) trong đó f(Ri-1, Ki)=P(S(E(Ri-1)Ki));

Trong đó:

-  là ký hiệu của phép tuyển loại trừ (XOR) của hai xâu bit theo modulo 2.

- Hàm f là một hàm phi tuyến

- E là hoán vị mở rộng ánh xạ R i-1 từ 32 bit thành 48 bit (đôi khi tất cả các bit sẽ
được sử dụng hoặc một bit sẽ được sử dụng hai lần)

- P là hoán vị cố định khác của 32 bit

Một hoán vị khởi đầu (IP) được sử dụng cho vòng đầu tiên, sau vòng cuối cùng
nửa trái và phải sẽ được đổi cho nhau và xâu cuối cùng kết quả sẽ được hoán vị lần
cuối bởi hoán vị ngược của IP (IP-1).

Quá trình giải mã diễn ra tương tự nhưng với các khóa con ứng dụng vào các
vòng theo thứ tự ngược lại.

11
1.2.4 Ưu nhược điểm

1.2.4.1 Ưu điểm

 Có tính bảo mật cao

 Công khai, dễ hiểu

 Nó có thể triển khai trên thiết bị điện tử có kích thước nhỏ

1.2.4.2 Nhược điểm

 Tính bù

Nếu ta ký hiệu u là phần bù của u (ví dụ : 0100101) thì des có tính chất sau

 Khóa yếu

 Khóa yếu là các khóa mà theo thuật toán sinh khóa con thì tất cả 16 khóa con
đều như nhàu: K1=K2=…=K16

 Điểu đó khiến cho việc mã hóa và giải mã đối với khóa yếu là giống hệt nhau.

 Đồng thời còn có 6 cặp khóa nửa yếu (semi-weak key) khác với thuộc tính như
sau : y= DES(x,k1) và y=DES(x,k2)

 Nghĩa là với 2 khóa khác nhau nhưng mã hóa cùng một bản mã từ cùng một bản

 DES có cấu trúc đại số

 Với 64 bit khối bản rõ có thể được ánh xạ lên tất cả các vị trí của khối 64 bit
khối bản mã trong 264 cách. Trong thuật toán DES, với 56 bit khóa có thể cho
chúng ta 256 (khoảng 1017 ) vị trí ánh xạ. Với việc đa mã hóa thì không gian ánh
xạ còn lớn hơn. Tuy nhiên điều này chỉ đúng nếu việc mã hóa DES là không cấu
trúc.

 Không gian khóa K

12
 DES có 256 = 1017 khóa. Nếu chúng ta biết được một cặp “tin/mã” thì chúng ta có
thể thử tất cả 1017 khả năng này để tìm ra khóa cho kết quả khớp nhất.

1.2.5 Sơ đồ khối

Hình 1. 2 Sơ đồ khối chương trình DES

13
Hình 1. 3 Sơ đồ khối quá trình sinh khóa

14
1.3 Ứng dụng của DES

DES và 3DES được ứng dụng rộng rãi trong các lĩnh vực mật mã, xác thực, an
toàn thông tin... Năm 2002 tiêu chuẩn mã hóa tiên tiến AES (Advanced Encryption
Standard) được đề xuất thay thế cho tiêu chuẩn DES và 3DES, song vẫn có nhiều
lĩnh vực áp dụng sử dụng DES, 3DES sau này. Trong Thông tư số 01/2011/TT-
BTTTT ngày 04/01/2011 của Bộ Thông tin và Truyền thông Công bố Danh mục
tiêu chuẩn kỹ thuật về ứng dụng công nghệ thông tin trong cơ quan nhà nước quy
định Khuyến nghị áp dụng tiêu chuẩn 3DES và được xếp vào nhóm Tiêu chuẩn
về an toàn thông tin.

1.4 Giới thiệu về ngôn ngữ lập trình Java

1.4.1 Tổng quan về ngôn ngữ lập trình Java

1.4.1.1 Khái niệm

Java là một ngôn ngữ lập trình hướng đối tượng (OOP) và dựa trên các lớp (class),
ban đầu được phát triển bởi Sun Microsystems do James Gosling khởi xướng và
phát hành vào năm 1995. Khác với phần lớn ngôn ngữ lập trình thông thường, thay
vì biên dịch mã nguồn thành mã máy hoặc thông dịch mã nguồn khi chạy, Java
được thiết kế để biên dịch mã nguồn thành bytecode, bytecode sau đó sẽ được môi
trường thực thi (runtime environment) chạy.

15
Hình 1. 4 Ngôn ngữ Java

1.4.1.2 Đặc điểm của ngôn ngữ lập trình Java

Là một ngôn ngữ lập trình hướng đối tượng vì vậy Java cũng có 4 đặc điểm chung
sau đây:

 Tính trừu tượng (Abstraction): là tiến trình xác định và nhóm các thuộc tính,
các hành động liên quan đến một thực thể đặc thù, xét trong mối tương quan
với ứng dụng đang phát triển.
 Tính đa hình (Polymorphism): cho phép một phương thức có các tác động
khác nhau trên nhiều loại đối tượng khác nhau. Với tính đa hình, nếu cùng một
phương thức ứng dụng cho các đối tượng thuộc các lớp khác nhau thì nó đưa
đến những kết quả khác nhau. Bản chất của sự việc chính là phương thức này
bao gồm cùng một số lượng các tham số.
 Tính kế thừa (Inheritance): điều này cho phép các đối tượng chia sẻ hay mở
rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại.
 Tính đóng gói (Encapsulation): là tiến trình che giấu việc thực thi những chi
tiết của một đối tượng đối với người sử dụng đối tượng ấy.
 Ngoài ra Java còn có một số đặc điểm sau:

16
 Đơn giản: Học Java thật sự dễ hơn nhiều so với C/C++, nếu ta đã quen với các
ngôn ngữ lập trình hướng đối tượng thì việc học Java sẽ dễ dàng hơn. Java trở
nên đơn giản hơn so với C/C++ do đã loại bỏ tính đa kế thừa và phép toán con
trỏ từ C/C++.
 Bảo mật: Java hỗ trợ bảo mật rất tốt bởi các thuật toán mã hóa như mã hóa một
chiều (one way hashing) hoặc mã hóa công cộng (public key)…
 Thông dịch: Java là một ngôn ngữ lập trình vừa biên dịch vừa thông dịch.
Chương trình nguồn viết bằng ngôn ngữ lập trình Java có đuôi *.java và được
biên dịch thành tập tin có đuôi *.class sau đó được trình thông dịch thông dịch
thành mã máy.
 Đa luồng: Với tính năng đa luồng Java có thể viết chương trình có thể thực thi
nhiều task cùng một lúc. Tính năng này thường được sử dụng rất nhiều trong
lập trình game.
 Hướng đối tượng: Hướng đối tượng trong Java tương tự như C++ nhưng Java
là một ngôn ngữ lập trình hướng đối tượng hoàn toàn. Tất cả mọi thứ đề cập
đến trong Java đều liên quan đến các đối tượng được định nghĩa trước, thậm
chí hàm chính của một chương trình viết bằng Java (đó là hàm main) cũng phải
đặt bên trong một lớp. Hướng đối tượng trong Java không có tính đa kế thừa
(multi inheritance) như trong C++ mà thay vào đó Java đưa ra khái niệm
interface để hỗ trợ tính đa kế thừa.
 Hiệu suất cao: Nhờ vào trình thu gom rác (garbage collection), giải phóng bộ
nhớ đối với các đối tượng không được dùng đến.
 Linh hoạt: Java được xem là linh hoạt hơn C/C ++ vì nó được thiết kế để thích
ứng với nhiều môi trường phát triển.

1.4.2 Điểm mạnh của ngôn ngữ Java

 Hầu hết các nền tảng chéo kể từ khi nó được thiết kế cho nó và Sun tạo ra JRE
và JDK cho hầu hết các nền tảng.
 Tất cả mọi thứ được truyền bằng tham chiếu ngoại trừ các loại giá trị, theo mặc
định.

17
 Rõ ràng java 6 chạy (một số?) Công cụ nhanh hơn một chút so với c ++ (mã
kiểm tra được chuyển từ c ++ chạy nhanh hơn mặc dù phải làm những việc có
vẻ lãng phí!).
 Chương trình được biên dịch và tối ưu hóa cho nền tảng, nếu cần?
 Dễ dàng tạo nhiều luồng và ta có thể khai báo các chức năng được đồng bộ hóa
để chỉ một luồng có thể có trong một luồng (IIRC)
 Ta có thể sử dụng Wait () và notifyAll () và thông báo () để tạm dừng các
luồng để chờ tín hiệu và đánh thức chúng lại.
 Các IDE miễn phí khác nhau có sẵn trên tất cả các nền tảng, chẳng hạn như
Eclipse.
 Nếu chương trình gặp sự cố, nó sẽ báo cho người dùng biết mã trong đó ở đâu
và tại sao, hiển thị dấu vết ngăn xếp bao gồm số dòng (nếu biểu tượng gỡ lỗi
được bật hoặc một cái gì đó tương tự) hoặc có thể được đổ vào tệp nhật ký lỗi.
 Các chương trình có thể được đóng gói thành các tệp jar với các tệp dữ liệu
khác nhau trong các tệp jar khác nhau và được người dùng truy cập bằng Java
WebStart, sẽ tự động cập nhật chương trình và mọi tệp jar cần thiết khác lên
phiên bản mới nhất, chỉ tải xuống các tệp jar đã thay đổi.
 Mạng dễ dàng hơn / nhiều nền tảng hơn c ++.
 Các tệp được đọc và ghi dưới dạng big endian trên tất cả các nền tảng (là thứ tự
byte mạng) đảm bảo rằng giao tiếp giữa các chương trình java và tải tệp không
bao giờ yêu cầu hoán đổi thứ tự byte (trừ khi nói chuyện với chương trình
không phải java hoặc sử dụng tệp được viết bởi một ).

1.5 Giới thiệu về công nghệ WebSockets

1.5.1 Tổng quan về WebSockets

1.5.1.1 Khái niệm

WebSoket là công nghệ hỗ trợ giao tiếp hai chiều giữa client và server bằng cách
sử dụng một TCP socket để tạo một kết nối hiệu quả và ít tốn kém. Mặc dù được

18
thiết kế để chuyên sử dụng cho các ứng dụng web, lập trình viên vẫn có thể đưa
chúng vào bất kì loại ứng dụng nào.

1.5.1.2 Giao thức bắt tay của WebSockets

Để thực hiện kết nối, client phải gửi một WebSocket handshake request đến server.
Server sẽ gửi trả lại WebSocket handshake response như bên dưới:

Client request:

GET /mychat HTTP/1.1


Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

Server response:(Server Architecture)

HTTP/1.1 101 Switching Protocols


Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Để xác nhận việc kết nối, client sẽ gửi một giá trị Sec-WebSocket-Key được mã
hóa bằng Based64 đến server. Sau đó bên server sẽ thực hiện:

- Nối thêm chuỗi cố định là “258EAFA5-E914-47DA-95CA-


C5AB0DC85B11″ vào Sec-WebSocket-Key để được chuỗi mới là :

“x3JJHMbDL1EzLkh9GBhXDw==258EAFA5-E914-47DA-95CA-
C5AB0DC85B11″.

19
- Thực hiện mã hóa SHA-1 chuỗi trên để được:

“1d29ab734b0c9585240069a6e4e3e91b61da1969″.

- Mã hóa kết quả vừa nhận được bằng Base64 để được:

“HSmrc0sMlYUkAGmm5OPpG2HaGWk=”.

Gửi response lại client kèm với giá trị Sec-WebSocket-Accept chính là chuỗi kết
quả vừa tạo ra.

Client sẽ kiểm tra status code (phải bằng 101) và Sec-WebSocket-Accept xem có
đúng với kết quả mong đợi không và thực hiện kết nối.

1.5.2 Ưu nhược điểm của WebSockets

1.5.2.1 Ưu điểm

 WebSockets cung cấp khả năng giao tiếp hai chiều mạnh mẽ, có độ trễ thấp
và dễ xử lý lỗi. Không cần phải có nhiều kết nối như phương pháp Comet
long-polling và cũng không có những nhược điểm như Comet streaming.
 API cũng rất dễ sử dụng trực tiếp mà không cần bất kỳ các tầng bổ sung nào,
so với Comet, thường đòi hỏi một thư viện tốt để xử lý kết nối lại, thời gian
chờ timeout, các Ajax request (yêu cầu Ajax), các tin báo nhận và các dạng
truyền tải tùy chọn khác nhau (Ajax long-polling và jsonp polling).

1.5.2.2 Nhược điểm

 WebSockets là một đặc tả mới của HTML5, nên nó vẫn chưa được tất cả các
trình duyệt hỗ trợ.
 Không có phạm vi yêu cầu nào. Do WebSocket là một TCP socket chứ
không phải là HTTP request, nên không dễ sử dụng các dịch vụ có phạm vi-
yêu cầu, như SessionInViewFilter của Hibernate. Hibernate là một
framework kinh điển cung cấp một bộ lọc xung quanh một HTTP request.
Khi bắt đầu một request, nó sẽ thiết lập một contest (chứa các transaction và
liên kết JDBC) được ràng buộc với luồng request. Khi request đó kết thúc,
bộ lọc hủy bỏ contest này.

20
1.6 Cài đặt môi trường lập trình Java

Tải JDK để cài đặt môi trường Java. Ta sẽ tải tại trang theo đường link:

https://www.oracle.com/java/technologies/downloads/

Ta có thể lập trình Java bằng IDE: Intelij, Netbeans, Eclipse,…

21
CHƯƠNG 2. XÂY DỰNG CHƯƠNG TRÌNH MÃ HÓA VÀ GIẢI MÃ
MẬT MÃ DES BẰNG NGÔN NGỮ JAVA

2.1 Mô tả thuật toán

DES là thuật toán mã hóa khối, nó xử lý từng khối thông tin của bản rõ có độ dài
xác định là 64 bit. Trước khi đi vào 16 chu trình chính, khối dữ liệu cần bảo mật
được “bẻ” ra từng khối 64 bit, và từng khối 64 bit này sẽ được lần lượt đưa vào 16
vòng mã hóa DES để thực hiện

Input: bản rõ M = m1m2 … m64, là một khối 64 bit, khóa 64 bit K = k1k2 . . . k64
( bao gồm cả 8 bit chẵn lẻ )

Output: bản mã 64 bit C = c1 c2 … c64

1. Sinh khóa con. Tính các khóa con theo thuật toán sinh khóa con

2. (L0,R0)  IP (m1 m2 . . . m64) (sử dụng bản hoán vị IP để hoán vị các bit, kết quả
nhận được chia thành 2 nửa là L0, R0)

3. ( 16 vòng) for i= 1 to 16

Tính các Li và Ri theo công thức:

Li=Ri-1;

Ri=Li-1  f(Ri-1) trong đó f ( Ri-1, Ki )=P ( S ( E ( Ri-1 )  Ki ) );

Việc tính f ( Ri-1 ) = P ( S ( E ( Ri-1 )  Ki ) ) được thực hiện như sau:

 Mở rộng Ri-1 = r1r2 . . . r32 từ 32 bit thành 48 bit bằng cách sử dụng hoán vị mở
rộng E.

 T’  T  Ki. Biểu diễn T’ như là các xâu gồm 8 ký tự 6 bit

T’ = ( B1, . . . ,B8 )

 T’’  ( S1 ( B1 ) , S2 ( B2 ) , . . . , S8 ( B8 ) ) .  T’’’  P ( T’’) trong đó P là


hoán vị cố định để hoán vị 32 bit của

T’’ = t1 t2 . . . t32 sinh ra t16 t7 . . . t25

22
4. b1 b2 . . . b64  ( R16, L16) ( đổi vị trí các khối cuối cùng L16 , R16)

5. C  IP-1 ( b1 b2 . . . b64) ( Biến đổi sử dụng IP-1, C = b40 b8 . . . b25).

23
Hình 2. 1 Sơ đồ mã hóa DES

2.1.1 Quy trình mã hóa

Hình 2. 2 Sơ đồ một vòng DES

Chia làm 3 giai đoạn:

 Giai đoạn 1:

Với bản rõ cho trước x, 1 xâu x' sẽ được tạo ra bằng cách hoán vị các bit của
x theo hoán vị ban đầu IP:

x'=IP(x)=L0 R0

L0:32 bit đầu

R0:32 bit cuối

24
IP:

Bảng 1. Hoán vị IP

58 50 42 34 26 18 10 02
60 52 44 36 28 20 12 04
62 54 46 38 30 22 14 06
64 56 48 40 32 24 16 08
57 49 41 33 25 17 09 01
59 51 43 35 27 19 11 03
61 53 45 37 29 21 13 05
63 55 47 39 31 23 15 07

 Giai đoạn 2:

Tính toán 16 lần lập theo 1 hàm xác định. Ta sẽ tính LiRi (1≤ i ≤ 16) theo quy tắc:

Li=Ri-1
Ri = Li-1 f (Ri-1, Ki)

 là toán tử Xor

 Giai đoạn 3:

Áp dụng hoán vị ngược IP-1 cho xâu bit R16 L16 ta thu được bản mã y:
y = IP-1 (R16 L16). Chú ý vị trí của R16 và L16.

IP-1

Bảng 2. Hoán vị IP-1

25
40 8 48 16 56 24 64 32
39 7 47 15 55 23 63 31
38 6 46 14 54 22 62 30
37 5 45 13 53 21 61 29
36 4 44 12 52 20 60 28
35 3 43 11 51 19 59 27
34 2 42 10 50 18 58 26
33 1 41 9 49 17 57 25

2.1.2 Quy trình giải mã

Do là 1 thuật toán đối xứng nên quá trình giải mã và mã hóa cũng gần giống nhau
chỉ khác ở:

Li=Ri-1
Ri = Li-1 f (Ri-1, K16-i)

Khóa K của hàm F sẽ đi từ 16 ->0

2.1.3 Hàm F

Đầu vào hàm f có 2 biến:

Biến 1:R là xâu bit có độ dài 32 bit, biến 2:K là xâu bit có độ dài 48 bit.Đầu ra của
f là xâu bit có độ dài 32 bit.

- Tính E ( Ri-1 )  Ki và viết kết quả thành 8 xâu 6 bit B1B2B3B4B5B6B7B8

- Đưa khối 8 bit Bi vào 8 bảng S1, S2, … .S8 ( được gọi là các hộp S-Box). Mỗi hộp
S-Box là một bảng 4*16 cố định có các cột từ 0 đến 15 và các hàng từ 0 đến 3. Với
mỗi xâu 6 bit Bi = b1b2b3b4b5b6, ta tính được Si ( B i) như sau: hai bit b1b6 xác định
hàng r trong trong hộp Si, bốn bit b2b3b4b5 xác định cột c trong hộp SI. Khi đó, Si (Bi

26
) sẽ xác định phần tử Ci=Si ( r,c), phần tử này viết dưới dạng nhị phân 4 bit. Như
vậy, 8 khối 6 bit Bi ( 1  i  8 ) sẽ cho ra 8 khối 4 bit Ci với ( 1  i  8 )

- Xâu bit C = C1C2C3C4C5C6C7C8 có độ dài 32 bit được hoán vị theo phép toán
hoán vị P (hộp P-Box). Kết quả P(C) sẽ là kết quả của hàm f( R i-1, Ki), và cũng
chính Ri cho vòng sau.

Hình 2. 4 Sơ đồ hàm F

2.1.4 Quá trính tạo khóa con

- Mười sáu vòng lặp DES chạy cùng thuật toán như nhau nhưng với 16 khóa con
khác nhau. Các khóa con đều được sinh ra từ khóa chính của DES bằng một thuật
toán sinh khóa con.

27
Hình 2. 5 Sơ đồ tạo khóa con

PC-1

Bảng 3. Hoán vị PC-1

57 49 41 33 25 17 09
01 58 50 42 34 26 18
10 02 59 51 43 35 27
19 11 03 60 52 44 36
63 55 47 39 31 23 15
07 62 54 46 38 30 22
14 06 61 53 45 37 29
21 13 05 28 20 12
04

Ta chia PC-1 thành 2 phần: C0:28 bit đầu, D0:28 bit cuối

28
Mỗi phần sẽ được xử lý 1 cách độc lập.

Ci=LSi(Ci-1)
Di = LSi(Ci-1) với 1≤ i ≤ 16

+ LSi biểu diễn phép dịch bit vòng(cyclic shift) sang trái 1 hoặc 2 vị trí tuỳ thuộc
vào i. Cyclic shift sang trái 1 bit nếu i=1,2,9,16 hoặc sang trái 2 bit nếu i thuộc các vị
trí còn lại.

Ki=PC-2(CiDi).

Số bit dịch của các vòng:

Bảng 4. Bảng dịch bit tại các vòng lặp DES

+ PC-2 là hoán vị cố định sẽ hoán vị chuối CiDi 56 bit thành chuỗi 48 bit.
PC-2

Bảng 5. Hoán vị PC-2

14 17 11 24 01 05
03 28 15 06 21 10
23 19 12 04 26 08
16 07 27 20 13 02
41 52 31 37 47 55
30 40 51 45 33 48
44 49 39 56 34 53
46 42 50 36 29 32

2.1.5 Hàm (ánh xạ) mở rộng (E)

Hàm mở rộng (E) sẻ tăng độ dài từ Ri từ 32 bit lên 48 bit bằng cách thay đổi
các thứ tự của các bit cũng như lặp lại các bit.

29
Bảng 6. Hàm mở rộng E

2.1.6 Hộp S – Box

- Mỗi hàng trong mỗi hộp S là hoán vị của các số nguyên từ 0 đến 15

Bảng 7. 8 hộp S-Box

S1

14 04 13 01 02 15 11 08 03 10 06 12 05 9 0 07

00 15 07 04 14 02 13 01 10 06 12 11 09 05 3 08

04 01 14 08 13 06 02 11 15 12 09 07 03 10 5 00

15 12 08 02 4 09 01 07 05 11 03 14 10 00 6 13

…….

S8

13 02 08 04 06 15 11 01 10 09 03 14 05 00 12 07

01 15 13 08 10 03 07 04 12 05 06 11 00 14 09 02

07 11 04 01 09 12 14 02 00 06 10 13 15 03 05 08

02 01 14 07 04 10 08 13 15 12 09 00 03 05 06 11

2.1.7 Hộp P-Box

Việc hoán vị này mang tính đơn ánh, nghĩa là một bit đầu vào sẽ cho một bit
ở đầu ra, không bit nào được sử dụng 2 lần hay bị bỏ qua. Hộp P-Box thực chất chỉ
là chức năng sắp xếp đơn thuần theo bảng sau:

Bảng 8. Bảng hoán vị P

30
2.2 Triển khai lập trình

2.2.1 Các modules sử dụng trong quá trình mã hóa và giải mã


Hàm hoán vị
private static long permute(byte[] table, int srcWidth, long
src) {
long dst = 0;
for (int i = 0; i < table.length; i++) {
int srcPos = srcWidth - table[i];
long a = src >> srcPos & 0x01;
long b = dst << 1;
//dst = (dst << 1) | (src >> srcPos & 0x01);
dst = a | b;
}
return dst;
}

Hàm tạo Sub Key


private static long[] createSubkeys(/* 64 bits */ long key)
{
long subkeys[] = new long[16];
key = PC1(key);
int c = (int) (key >> 28);
int d = (int) (key & 0x0FFFFFFF);

for (int i = 0; i < 16; i++) {


if (rotations[i] == 1) {
c = ((c << 1) & 0x0FFFFFFF) | (c >> 27);
d = ((d << 1) & 0x0FFFFFFF) | (d >> 27);
} else {
c = ((c << 2) & 0x0FFFFFFF) | (c >> 26);
d = ((d << 2) & 0x0FFFFFFF) | (d >> 26);

31
}

long cd = (c & 0xFFFFFFFFL) << 28 | (d &


0xFFFFFFFFL);

subkeys[i] = PC2(cd);
}

return subkeys; /* 48-bit values */


}

Hàm Feistel
private static int feistel(int r, /* 48 bits */ long subkey)
{
// 1. expansion
long e = E(r);
// 2. key mixing
long x = e ^ subkey;
// 3. substitution
int dst = 0;
for (int i = 0; i < 8; i++) {
dst >>>= 4;
int s = S(8 - i, (byte) (x & 0x3F)); // 00111111
s = s<<28;
dst = dst | s;
//dst |= s << 28;
x >>= 6;
}
// 4. permutation
return P(dst);
}

32
2.2.2 Code mã hóa
Hàm mã hóa xâu theo từng 8bytes mỗi lần, nếu không đủ 8bytes thì bù vào bằng 0
public static byte[] encryptCBC(byte[] message, byte[]
key,int phanbu) {
int i;
long cipherBlock;
byte[] ciphertext = new
byte[message.length+phanbu+8];
long k = getLongFromBytes(key, 0);
long previousCipherBlock = IV;
long length = message.length;

for (i = 0; i < message.length + phanbu; i += 8) {


// get the message block to be encrypted (8bytes
= 64bits)
long messageBlock = getLongFromBytes(message,
i);

// XOR message block with previous cipherblock


and encrypt
// First previousCiphertext = Initial Vector
(IV)
cipherBlock = encryptBlock(messageBlock ^
previousCipherBlock, k);

// Store the cipherBlock in the correct position


in ciphertext
getBytesFromLongE(ciphertext, i, cipherBlock);

// Update previousCipherBlock
previousCipherBlock = cipherBlock;
}
cipherBlock = encryptBlock(length,k);
getBytesFromLongE(ciphertext,i,cipherBlock);
return ciphertext;
}

33
Hàm mã hóa xâu 8bytes với key 64bits
public static long encryptBlock(long m, long key) {
long[] subkeys = createSubkeys(key);
long ip = IP(m);
int l = (int) (ip >> 32);
int r = (int) (ip & 0xFFFFFFFFL);

for (int i = 0; i < 16; i++) {


int previous_l = l;
l = r;
r = previous_l ^ feistel(r, subkeys[i]);
}

long rl = (r & 0xFFFFFFFFL) << 32 | (l &


0xFFFFFFFFL);

long fp = FP(rl);
return fp;
}

2.2.3 Code giải mã


Hàm giải mã khối
public static byte[] decryptCBC(byte[] ciphertext, byte[]
key) {
long k = getLongFromBytes(key, 0);
long lengthBlock =
getLongFromBytes(ciphertext,ciphertext.length-8);
long length = decryptBlock(lengthBlock,k);
byte[] message = new byte[(int)length];

long previousCipherBlock = IV;

for (int i = 0; i < ciphertext.length; i += 8) {


// get the cipher block to be decrypted (8bytes
= 64bits)
long cipherBlock = getLongFromBytes(ciphertext,
i);

34
// Decrypt the cipher block and XOR with
previousCipherBlock
// First previousCiphertext = Initial Vector
(IV)
long messageBlock = decryptBlock(cipherBlock,
k);
messageBlock = messageBlock ^
previousCipherBlock;

// Store the messageBlock in the correct


position in message
getBytesFromLongD(message, i, messageBlock);

// Update previousCipherBlock
// previousCipherBlock = cipherBlock;
previousCipherBlock = cipherBlock;
}

return message;
}

Hàm giải mã xâu 8bytes với key 64bits


public static long decryptBlock(long c, /* 64 bits */ long
key) {
// generate the 16 subkeys
long[] subkeys = createSubkeys(key);

// perform the initial permutation


long ip = IP(c);

// split the 32-bit value into 16-bit left and


right halves.
int l = (int) (ip >> 32);
int r = (int) (ip & 0xFFFFFFFFL);

// perform 16 rounds
// NOTE: reverse order of subkeys used!

35
for (int i = 15; i > -1; i--) {
int previous_l = l;
// the right half becomes the new left half.
l = r;
// the Feistel function is applied to the old
left half
// and the resulting value is stored in the
right half.
r = previous_l ^ feistel(r, subkeys[i]);
}

// reverse the two 32-bit segments (left to right;


right to left)
long rl = (r & 0xFFFFFFFFL) << 32 | (l &
0xFFFFFFFFL);

// apply the final permutation


long fp = FP(rl);

// return the message


return fp;
}

36
KẾT QUẢ VÀ ĐÁNH GIÁ

3.1 Kết quả

 Giao diện gửi file

Hình 3. 1. Giao diện gửi file

 Giao diện gửi file mã hóa thành công

Hình 3. 2. Giao diện gửi file mã hóa thành công

37
 Giao diện khi nhập key sai

Hình 3. 3. Giao diện nhập key sai

 Giao diện nhận file mã hóa

Hình 3. 4. Giao diện nhận file mã hóa

38
 Giao diện nhận file mã hóa thành công

Hình 3. 5. Giao diện nhận file mã hóa thành công

3.2 Kết luận và đánh giá thuật toán DES

Có rất nhiều phương pháp mã hóa để đảm bảo an toàn dữ liệu. Để đánh giá
tính ưu việt một giải thuật mã hóa, người ta thường dựa vào các yếu tố: Tính bảo
mật, độ phức tạp, tốc độ thực hiện giải thuật và vấn đề phân khóa trong môi trường
nhiều người sử dụng.

Hiện nay phương pháp mã hóa DES được sử dụng rộng rãi nhất. Các chip
chuyên dung DES được thiết kế nhằm tăng tốc độ xử lí của DES. Rất nhiều nhà
toán học, tin học đã bỏ nhiều công nghiên cứu trong nhiều năm nhằm tìm cách phá
vỡ DES (tức là tìm ra cách giải mã trong khoảng thời gian ngắn hơn thời gian cần
để thử lần lượt tất cả các khóa). Ngoại trừ việc tìm ra 4 khóa yếu và 12 khóa tương
đối yếu cho tới nay chưa có một thông báo nào về việc tì ra cách phá vỡ phương
pháp mã hóa này. Để phá vỡ DES bằng phương pháp “ vét cạn” thử tất cả các khóa
trong không gian khóa cần có một khoản tiền lớn và đòi hỏi một khoảng thời gian
dài.

Nhược điểm của DES: nó là thuật toán mã hóa đối xứng. Khi phương pháp
này mới được tìm ra ý tưởng thực hiện 50000 tỷ phép mã hóa cần thiết để vượt mặt
DES bằng cách thử lần lượt các khóa có thể là điếu không thể làm được nhưng
ngày nay với sự phát triển mạnh của phần cứng liệu độ dài 56 bit đã đủ chưa? Và

39
các phép thay thế đã đủ phức tạp chưa? Để đạt được độ an toàn thông tin như
mong muốn, đó là vấn đề người ta vẫn đang bàn luận. Tuy vậy, DES đã được phân
tích kĩ lưỡng và công nhận là vững chắc. Các hạn chế của nó đã được hiểu rõ và có
thể xem xét trong quá trình thiết kế và để tăng độ an toàn hơn, ngày nay các hệ
thống mã hóa sử dụng DES mở rộng ( 3DES ), được ứng dụng rộng dãi. Với DES
mở rộng khóa có thể là 128 bit,…độ lớn khối có thể là 128 bit. Do vậy độ an toàn
mở rộng của DES cao hơn rất nhiều.

3.3 Hướng phát triển tiếp theo


Với những kết quả đạt được qua đề tài, nhóm chúng em có thêm một số phương
hướng phát triển sản phẩm:
- Phát triển dịch vụ lưu trữ đám mây với khả năng mã hóa dữ liệu, tránh thông tin bị
lộ gây nguy hiểm cho các cá nhân.
- Xây dựng giao diện chạy trên cả nền tảng web và mobile giúp thuận tiện hơn cho
người sử dụng cũng như hoàn thiện giao diện trên PC.
- Bổ sung các tính năng như đăng nhập, tìm kiếm file, truyền file cho cá nhân được
xác định,…

40
TÀI LIỆU THAM KHẢO

[1] Giáo trình AT&BMTT TS. NGUYỄN ĐÀO TRƯỜNG

[2] https://viblo.asia/p/encryption-des-Qpmleq27lrd

[3] https://magenest.com/vi/ngon-ngu-lap-trinh-java/

41
PHỤ LỤC

Code Server

Main.java
package org.example;

import org.example.controller.ServerController;

public class Main {

public static void main(String[] args) {


ServerController controller = new ServerController();
controller.showServerView();
}
}

…\src\main\java\org\example\service

DESService.java
package org.example.service;

public class DESService {


private static long IV;

public static long getIv() {


return IV;
}

public static void setIv(long iv) {


IV = iv;
}

/** Input permutation */


private static final byte[] IP = {
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
};
/** Final permutation */
private static final byte[] FP = {

42
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};
/**Expansion Permutation, expand from 32 bit to 48 bit*/
private static final byte[] E = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};
/** S-Box */
private static final byte[][] S = {{
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
}, {
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
}, {
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
}, {
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
}, {
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
}, {
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,

43
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
}, {
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
}, {
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}};
/**Permutation, result from The Feistel will use it to make Right
for next round */
private static final byte[] P = {
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};
/** PC1 make key from 64bit to 56bit */
private static final byte[] PC1 = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
/**
* PC2 Permutation. The subkey generation process applies this
* permutation to transform its running 56-bit keystuff value
into
* the final set of 16 48-bit subkeys.
*/
private static final byte[] PC2 = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32

44
};
/**cyclic shift rotate bit left for each of 16steps */
private static final byte[] rotations = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
private static long IP(long src) {
return permute(IP, 64, src);
} // 64-bit output

private static long FP(long src) {


return permute(FP, 64, src);
} // 64-bit output

private static long E(int src) {


return permute(E, 32, src & 0xFFFFFFFFL);
} // 48-bit output

private static int P(int src) {


return (int) permute(P, 32, src & 0xFFFFFFFFL);
} // 32-bit output

private static long PC1(long src) {


return permute(PC1, 64, src);
} // 56-bit output

private static long PC2(long src) {


return permute(PC2, 56, src);
} // 48-bit output

/**Permute an input value "src" of srcWidth bits according to the


// * supplied permutation table. */
private static long permute(byte[] table, int srcWidth, long src)
{
long dst = 0;
for (int i = 0; i < table.length; i++) {
int srcPos = srcWidth - table[i];
long a = src >> srcPos & 0x01;
long b = dst << 1;
//dst = (dst << 1) | (src >> srcPos & 0x01);
dst = a | b;
}
return dst;
}
/** get Value from S-box*/
private static byte S(int boxNumber, byte src) {
// The first aindex based on the following bit shuffle:
// abcdef => afbcde
// src = (byte) (src & 0x20 | ((src & 0x01) << 4) | ((src &

45
0x1E) >> 1));
int a = src &0x20; // 0010000
int b = (src & 0x01 ) <<4; // 000000001 >> 4 => 0001000
int c = ((src & 0x1E) >> 1); // 00001110 >>1 => 00000111
src = (byte)(a|b|c);
return S[boxNumber - 1][src];
}

/**convert 8bytes ([array]) into a single 64-bit ( inline)


*/
private static long getLongFromBytes(byte[] ba, int offset) {
long l = 0;
for (int i = 0; i < 8; i++) {
byte value;
if ((offset + i) < ba.length) {
// and last bits determine which 16-value row to
// reference, so we transform the 6-bit input into an
// absolute
value = ba[offset + i];
} else {
value = 0;
}
l = l << 8 | (value & 0xFFL);
}
return l;
}
/** convert 64bit to 8bytes [array] */
private static void getBytesFromLongE(byte[] ba, int offset, long
l) {
for (int i = 7; i > -1; i--) {
if ((offset + i) < ba.length) {
ba[offset + i] = (byte) (l & 0xFF);
l = l >> 8;
}
}
}
private static void getBytesFromLongD(byte[] ba, int offset, long
l) {
for (int i = 7; i > -1; i--) {
if ((offset + i) < ba.length) {
ba[offset + i] = (byte) (l & 0xFF);
l = l >> 8;
} else {
l = l >> 8;
}
}
}
/**
* The Feistel function is the heart of DES.
*/

46
private static int feistel(int r, /* 48 bits */ long subkey) {
// 1. expansion
long e = E(r);
// 2. key mixing
long x = e ^ subkey;
// 3. substitution
int dst = 0;
for (int i = 0; i < 8; i++) {
dst >>>= 4;
int s = S(8 - i, (byte) (x & 0x3F)); // 00111111
s = s<<28;
dst = dst | s;
//dst |= s << 28;
x >>= 6;
}
// 4. permutation
return P(dst);
}
/**
* Generate 16 48-bit subkeys based on the provided 64-bit key
* value.
*/
private static long[] createSubkeys(/* 64 bits */ long key) {
long subkeys[] = new long[16];

// perform the PC1 permutation


key = PC1(key);

// split into 28-bit left and right (c and d) pairs.


int c = (int) (key >> 28);
int d = (int) (key & 0x0FFFFFFF);

// for each of the 16 needed subkeys, perform a bit


// rotation on each 28-bit keystuff half, then join
// the halves together and permute to generate the
// subkey.
for (int i = 0; i < 16; i++) {
// rotate the 28-bit values
if (rotations[i] == 1) {
// rotate by 1 bit
c = ((c << 1) & 0x0FFFFFFF) | (c >> 27);
d = ((d << 1) & 0x0FFFFFFF) | (d >> 27);
} else {
// rotate by 2 bits
c = ((c << 2) & 0x0FFFFFFF) | (c >> 26);
d = ((d << 2) & 0x0FFFFFFF) | (d >> 26);
}

// join the two keystuff halves together.


long cd = (c & 0xFFFFFFFFL) << 28 | (d & 0xFFFFFFFFL);

47
// perform the PC2 permutation
subkeys[i] = PC2(cd);
}

return subkeys; /* 48-bit values */


}
/** Encrypt 8bytes one time with key if not enough 8byte, it is
padded with zeros */
public static byte[] encryptCBC(byte[] message, byte[] key,int
phanbu) {
int i;
long cipherBlock;
byte[] ciphertext = new byte[message.length+phanbu+8];
long k = getLongFromBytes(key, 0);
long previousCipherBlock = IV;
long length = message.length;

for (i = 0; i < message.length + phanbu; i += 8) {


// get the message block to be encrypted (8bytes =
64bits)
long messageBlock = getLongFromBytes(message, i);

// XOR message block with previous cipherblock and


encrypt
// First previousCiphertext = Initial Vector (IV)
cipherBlock = encryptBlock(messageBlock ^
previousCipherBlock, k);

// Store the cipherBlock in the correct position in


ciphertext
getBytesFromLongE(ciphertext, i, cipherBlock);

// Update previousCipherBlock
previousCipherBlock = cipherBlock;
}
cipherBlock = encryptBlock(length,k);
getBytesFromLongE(ciphertext,i,cipherBlock);
return ciphertext;
}
/**
* Encrypt a 64-bit block of plaintext message into a 64-bit
* ciphertext.
*/

public static long encryptBlock(long m, /* 64 bits */ long key) {


// generate the 16 subkeys
long[] subkeys = createSubkeys(key);

// perform the initial permutation

48
long ip = IP(m);

// split the 32-bit value into 16-bit left and right halves.
int l = (int) (ip >> 32);
int r = (int) (ip & 0xFFFFFFFFL);

// perform 16 rounds
for (int i = 0; i < 16; i++) {
int previous_l = l;
// the right half becomes the new left half.
l = r;
// the Feistel function is applied to the old left half
// and the resulting value is stored in the right half.
r = previous_l ^ feistel(r, subkeys[i]);
}

// reverse the two 32-bit segments (left to right; right to


left)
long rl = (r & 0xFFFFFFFFL) << 32 | (l & 0xFFFFFFFFL);

// apply the final permutation


long fp = FP(rl);

// return the ciphertext


return fp;
}
private static int charToNibble(char c) {
if (c >= '0' && c <= '9') {
return (c - '0');
} else if (c >= 'a' && c <= 'f') {
return (10 + c - 'a');
} else if (c >= 'A' && c <= 'F') {
return (10 + c - 'A');
} else {
return 0;
}
}

private static byte[] parseBytes(String s) {


s = s.replace(" ", "");
int a = s.length();
if (s.length() % 2 > 0) {
s = s + '0';
}
byte[] ba = new byte[s.length() / 2];

int m = s.length();
for (int i = 0; i < s.length(); i += 2) {
//ba[i / 2] = (byte) (charToNibble(s.charAt(i)) << 4 |
charToNibble(s.charAt(i + 1)));

49
int c = charToNibble(s.charAt(i));
c= c << 4;
int d = charToNibble((s.charAt(i+1)));
ba[i / 2] = (byte) (c|d);
}
return ba;
}

private static String hex(byte[] bytes) {


StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(String.format("%02X ", bytes[i]));
}
return sb.toString();
}
public static String convertStringToHex(String str) {
char[] chars = str.toCharArray();
StringBuilder hex = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
hex.append(String.format("%02X ", (int) chars[i]));
}
return hex.toString();
}

/** convert from Hex to String */


private static String hexToAscii(String hexStr) {
hexStr = hexStr.replace(" ", "");
StringBuilder output = new StringBuilder("");

for (int i = 0; i < hexStr.length(); i += 2) {


String str = hexStr.substring(i, i + 2);
output.append((char) Integer.parseInt(str,16));
}

return output.toString();
}

public static String encryptText(String plainText, String key) {


int phanbu = 8 - plainText.length() % 8;
String encryptedKey = convertStringToHex(key);
String convertedText = convertStringToHex(plainText);
byte[] keyByte = parseBytes(encryptedKey);
byte[] convertedTextByte = parseBytes(convertedText);

String result = hex(encryptCBC(convertedTextByte, keyByte,


phanbu));
return hexToAscii(result);
}
}
ServerService.java

50
package org.example.service;

import org.example.model.Message;
import org.example.model.TextModel;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerService {


private final Integer SOCKET_PORT = 9098;

public TextModel encryptFile(String filePath, String key) throws


IOException {
File myFile = new File(filePath);
byte[] byteArray = new byte[(int) myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(byteArray);
String plainText = new String(byteArray);
String encryptedText = DESService.encryptText(plainText,
key);
return new TextModel(plainText, encryptedText);
}

public void sendFile(String encryptedText, String key) throws


IOException {
ServerSocket serverSocket = new ServerSocket(SOCKET_PORT);
Socket socket = serverSocket.accept();
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(new Message(encryptedText, key));
os.flush();

os.close();
socket.close();
serverSocket.close();
}
}
Code Client

Main.java
package org.example;

import org.example.controller.ClientController;

public class Main {

51
public static void main(String[] args) {
ClientController controller = new ClientController();
controller.showClientView();
}
}

…\src\main\java\org\example\service

DESService.java
package org.example.service;

public class DESService {


private static long IV;

public static long getIv() {


return IV;
}

public static void setIv(long iv) {


IV = iv;
}

/** Input permutation */


private static final byte[] IP = {
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
};
/** Final permutation */
private static final byte[] FP = {
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};
/**Expansion Permutation, expand from 32 bit to 48 bit*/

52
private static final byte[] E = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};
/** S-Box */
private static final byte[][] S = {{
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
}, {
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
}, {
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
}, {
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
}, {
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
}, {
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
}, {
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
}, {
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,

53
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}};
/**Permutation, result from The Feistel will use it to make Right
for next round */
private static final byte[] P = {
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};
/** PC1 make key from 64bit to 56bit */
private static final byte[] PC1 = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
/**
* PC2 Permutation. The subkey generation process applies this
* permutation to transform its running 56-bit keystuff value
into
* the final set of 16 48-bit subkeys.
*/
private static final byte[] PC2 = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
/**cyclic shift rotate bit left for each of 16steps */
private static final byte[] rotations = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
private static long IP(long src) {
return permute(IP, 64, src);
} // 64-bit output

private static long FP(long src) {

54
return permute(FP, 64, src);
} // 64-bit output

private static long E(int src) {


return permute(E, 32, src & 0xFFFFFFFFL);
} // 48-bit output

private static int P(int src) {


return (int) permute(P, 32, src & 0xFFFFFFFFL);
} // 32-bit output

private static long PC1(long src) {


return permute(PC1, 64, src);
} // 56-bit output

private static long PC2(long src) {


return permute(PC2, 56, src);
} // 48-bit output

/**Permute an input value "src" of srcWidth bits according to the


// * supplied permutation table. */
private static long permute(byte[] table, int srcWidth, long src)
{
long dst = 0;
for (int i = 0; i < table.length; i++) {
int srcPos = srcWidth - table[i];
long a = src >> srcPos & 0x01;
long b = dst << 1;
//dst = (dst << 1) | (src >> srcPos & 0x01);
dst = a | b;
}
return dst;
}
/** get Value from S-box*/
private static byte S(int boxNumber, byte src) {
// The first aindex based on the following bit shuffle:
// abcdef => afbcde
// src = (byte) (src & 0x20 | ((src & 0x01) << 4) | ((src &
0x1E) >> 1));
int a = src &0x20; // 0010000
int b = (src & 0x01 ) <<4; // 000000001 >> 4 => 0001000
int c = ((src & 0x1E) >> 1); // 00001110 >>1 => 00000111
src = (byte)(a|b|c);
return S[boxNumber - 1][src];
}

/**convert 8bytes ([array]) into a single 64-bit ( inline)


*/

55
private static long getLongFromBytes(byte[] ba, int offset) {
long l = 0;
for (int i = 0; i < 8; i++) {
byte value;
if ((offset + i) < ba.length) {
// and last bits determine which 16-value row to
// reference, so we transform the 6-bit input into an
// absolute
value = ba[offset + i];
} else {
value = 0;
}
l = l << 8 | (value & 0xFFL);
}
return l;
}
/** convert 64bit to 8bytes [array] */
private static void getBytesFromLongE(byte[] ba, int offset, long
l) {
for (int i = 7; i > -1; i--) {
if ((offset + i) < ba.length) {
ba[offset + i] = (byte) (l & 0xFF);
l = l >> 8;
} else {
continue;
}
}
}
private static void getBytesFromLongD(byte[] ba, int offset, long
l) {
for (int i = 7; i > -1; i--) {
if ((offset + i) < ba.length) {
ba[offset + i] = (byte) (l & 0xFF);
l = l >> 8;
} else {
l = l >> 8;
continue;
}
}
}
/**
* The Feistel function is the heart of DES.
*/
private static int feistel(int r, /* 48 bits */ long subkey) {
// 1. expansion
long e = E(r);
// 2. key mixing
long x = e ^ subkey;
// 3. substitution
int dst = 0;

56
for (int i = 0; i < 8; i++) {
dst >>>= 4;
int s = S(8 - i, (byte) (x & 0x3F)); // 00111111
s = s<<28;
dst = dst | s;
//dst |= s << 28;
x >>= 6;
}
// 4. permutation
return P(dst);
}
/**
* Generate 16 48-bit subkeys based on the provided 64-bit key
* value.
*/
private static long[] createSubkeys(/* 64 bits */ long key) {
long subkeys[] = new long[16];

// perform the PC1 permutation


key = PC1(key);

// split into 28-bit left and right (c and d) pairs.


int c = (int) (key >> 28);
int d = (int) (key & 0x0FFFFFFF);

// for each of the 16 needed subkeys, perform a bit


// rotation on each 28-bit keystuff half, then join
// the halves together and permute to generate the
// subkey.
for (int i = 0; i < 16; i++) {
// rotate the 28-bit values
if (rotations[i] == 1) {
// rotate by 1 bit
c = ((c << 1) & 0x0FFFFFFF) | (c >> 27);
d = ((d << 1) & 0x0FFFFFFF) | (d >> 27);
} else {
// rotate by 2 bits
c = ((c << 2) & 0x0FFFFFFF) | (c >> 26);
d = ((d << 2) & 0x0FFFFFFF) | (d >> 26);
}

// join the two keystuff halves together.


long cd = (c & 0xFFFFFFFFL) << 28 | (d & 0xFFFFFFFFL);

// perform the PC2 permutation


subkeys[i] = PC2(cd);
}

return subkeys; /* 48-bit values */


}

57
private static int charToNibble(char c) {
if (c >= '0' && c <= '9') {
return (c - '0');
} else if (c >= 'a' && c <= 'f') {
return (10 + c - 'a');
} else if (c >= 'A' && c <= 'F') {
return (10 + c - 'A');
} else {
return 0;
}
}

private static byte[] parseBytes(String s) {


s = s.replace(" ", "");
int a = s.length();
if (s.length() % 2 > 0) {
s = s + '0';
}
byte[] ba = new byte[s.length() / 2];

int m =s.length();
for (int i = 0; i < s.length(); i += 2) {
//ba[i / 2] = (byte) (charToNibble(s.charAt(i)) << 4 |
charToNibble(s.charAt(i + 1)));
int c = charToNibble(s.charAt(i));
c= c << 4;
int d = charToNibble((s.charAt(i+1)));
ba[i / 2] = (byte) (c|d);
}
return ba;
}

private static String hex(byte[] bytes) {


StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(String.format("%02X ", bytes[i]));
}
return sb.toString();
}
public static String convertStringToHex(String str) {
char[] chars = str.toCharArray();
StringBuilder hex = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
hex.append(String.format("%02X ", (int) chars[i]));
}
return hex.toString();
}

public static long decryptBlock(long c, /* 64 bits */ long key) {

58
// generate the 16 subkeys
long[] subkeys = createSubkeys(key);

// perform the initial permutation


long ip = IP(c);

// split the 32-bit value into 16-bit left and right halves.
int l = (int) (ip >> 32);
int r = (int) (ip & 0xFFFFFFFFL);

// perform 16 rounds
// NOTE: reverse order of subkeys used!
for (int i = 15; i > -1; i--) {
int previous_l = l;
// the right half becomes the new left half.
l = r;
// the Feistel function is applied to the old left half
// and the resulting value is stored in the right half.
r = previous_l ^ feistel(r, subkeys[i]);
}

// reverse the two 32-bit segments (left to right; right to


left)
long rl = (r & 0xFFFFFFFFL) << 32 | (l & 0xFFFFFFFFL);

// apply the final permutation


long fp = FP(rl);

// return the message


return fp;
}
/** Function decrypt */
public static byte[] decryptCBC(byte[] ciphertext, byte[] key) {
long k = getLongFromBytes(key, 0);
long lengthBlock =
getLongFromBytes(ciphertext,ciphertext.length-8);
long length = decryptBlock(lengthBlock,k);
byte[] message = new byte[(int)length];

long previousCipherBlock = IV;

for (int i = 0; i < ciphertext.length; i += 8) {


// get the cipher block to be decrypted (8bytes = 64bits)
long cipherBlock = getLongFromBytes(ciphertext, i);

// Decrypt the cipher block and XOR with


previousCipherBlock
// First previousCiphertext = Initial Vector (IV)
long messageBlock = decryptBlock(cipherBlock, k);
messageBlock = messageBlock ^ previousCipherBlock;

59
// Store the messageBlock in the correct position in
message
getBytesFromLongD(message, i, messageBlock);

// Update previousCipherBlock
// previousCipherBlock = cipherBlock;
previousCipherBlock = cipherBlock;
}

return message;
}
/** convert from Hex to String */
private static String hexToAscii(String hexStr) {
hexStr = hexStr.replace(" ", "");
StringBuilder output = new StringBuilder("");

for (int i = 0; i < hexStr.length(); i += 2) {


String str = hexStr.substring(i, i + 2);
output.append((char) Integer.parseInt(str,16));
}

return output.toString();
}

public static String decryptText(String encryptedText, String


key)
{
String convertedEncryptedText =
convertStringToHex(encryptedText);
byte [] encryptedTextByte =
parseBytes(convertedEncryptedText);
String encryptedKey = convertStringToHex(key);
byte[] keyByte = parseBytes(encryptedKey);
String decryptedResult = hex(decryptCBC(encryptedTextByte,
keyByte));
return hexToAscii(decryptedResult);
}
}
ClientService.java
package org.example.service;

import org.example.model.Message;
import org.example.model.TextModel;

import java.io.*;
import java.net.Socket;

public class ClientService {

60
private final Integer SOCKET_PORT = 9098;
private final String SERVER = "127.0.0.1";
private final String FILE_TO_RECEIVED =
"C:/Users/Thieu/Downloads/DecryptedText.txt";

public TextModel decryptTextAndSaveFile() throws IOException,


ClassNotFoundException {
Socket socket = new Socket(SERVER, SOCKET_PORT);

InputStream is = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
Message receiveObject = (Message) ois.readObject();
FileOutputStream fos = new
FileOutputStream(FILE_TO_RECEIVED);
BufferedOutputStream bos = new BufferedOutputStream(fos);
String decryptedText =
DESService.decryptText(receiveObject.getEncryptedText(),
receiveObject.getKey());
bos.write(decryptedText.getBytes());

bos.flush();
fos.close();
is.close();
socket.close();

return new TextModel(receiveObject.getEncryptedText(),


decryptedText);
}
}

61

You might also like