You are on page 1of 32

HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG

KHOA CÔNG NGHỆ THÔNG TIN

Học phần: Các kỹ thuật giấu tin

Bài báo cáo bài tập lớn:


Phương pháp hoán vị giả ngẫu nhiên

Giảng viên hướng dẫn: TS. Đỗ Xuân Chợ


Sinh viên thực hiện:
Nguyễn Hoàng Đức B17DCAT046
Trần Quốc Định B17DCAT038
Bùi Trần Quốc Cường B17DCAT026
Phạm Tuấn Nam B17DCAT134
Phạm Hoàng Thịnh B17DCAT174
Đỗ Tuấn Sơn B17DCAT154

Hà Nội 2021
Mục lục
DANH MỤC HÌNH ẢNH..................................................................................................3
Chương 1: Phương pháp LSB............................................................................................4
1.1. Tổng quan về phương pháp thay thế LSB................................................................4
1.2. Phương pháp giấu tin và tách tin trên k bit LSB......................................................6
1.2.1. Phương pháp giấu tin........................................................................................6
1.2.2. Phương pháp tách tin........................................................................................7
1.3. Phương pháp giấu tin và tách tin trên k bit LSB nâng cao.......................................7
1.3.1. Phương pháp giấu tin........................................................................................7
1.3.2. Phương pháp tách tin........................................................................................9
1.4. Đánh giá phương pháp LSB...................................................................................10
Chương 2: Tạo số giả ngẫu nghiên...................................................................................11
2.1. Giới thiệu...............................................................................................................11
2.2. Thuật toán tạo ra các số giả ngẫu nhiên.................................................................11
2.2.1 Phương pháp cơ bản.........................................................................................11
2.2.2 Phương pháp dựa trên mật mã học nguyên thuỷ...............................................18
2.2.3 Phương pháp dựa trên lý thuyết số học.............................................................18
2.2.4 Phương pháp đặc biệt.......................................................................................19
Chương 3: Phương pháp hoán vị giả ngẫu nhiên và Demo..............................................22
3.1. Ý tưởng thực hiện..................................................................................................22
3.2. Quá trình giấu tin...................................................................................................23
3.3. Quá trình giải tin....................................................................................................24
3.4. Đánh giá.................................................................................................................24
3.5. Demo..................................................................................................................... 25
Thuật toán giấu tin.....................................................................................................25
Thuật toán tách tin.....................................................................................................30
Tài liệu tham khảo............................................................................................................ 32

2
DANH MỤC HÌNH ẢNH
Y
Hình 1: Bit có trọng số thấp LSB.......................................................................................4
Hình 2: Quá trình giấu tin..................................................................................................5
Hình 3: Quá trình lấy thông tin ra khỏi ảnh.......................................................................5
Hình 4: Sơ đồ nhúng và tách tin của phương pháp hoán vị giả ngẫu nhiên......................23

3
Chương 1: Phương pháp LSB

1.1. Tổng quan về phương pháp thay thế LSB


Ý tưởng cơ bản của kỹ thuật này là tiến hành giấu tin vào vị trí các bit ít quan
trọng LSB đối với mỗi phần tử trong bảng màu.

Đây là phương pháp giấu tin đơn giản nhất, thông điệp dưới dạng nhị phân sẽ
được giấu (nhúng) vào các bit LSB – là bit có ảnh hưởng ít nhất tới việc quyết định tới
màu sắc của mỗi điểm ảnh. Vì vậy khi ta thay đổi bit ít quan trọng của một điểm ảnh thì
màu sắc của mỗi điểm ảnh mới sẽ tương đối gần với điểm ảnh cũ. Ví dụ đối với ảnh 16
bit thì 15 bit là biểu diễn 3 màu RGB của điểm ảnh còn bit cuối cùng không dùng đến thì
ta sẽ tách bit này ra ở mỗi điểm ảnh để giấu tin…

Ví dụ: Tách bit cuối cùng trong 8 bit biểu diễn mỗi điểm ảnh của ảnh 256

Hình : Bit có trọng số thấp LSB

Trong phép tách này ta coi bit cuối cùng là bit ít quan trọng nhất, thay đổi giá trị
của bit này thì sẽ thay đổi giá trị của điểm ảnh lên hoặc xuống đúng một đơn vị, với sự
thay đổi nhỏ đó ta hi vọng là cấp độ màu của điểm ảnh sẽ không bị thay đổi nhỉều.

4
Hình : Quá trình giấu tin

Hình : Quá trình lấy thông tin ra khỏi ảnh

5
1.2. Phương pháp giấu tin và tách tin trên k bit LSB

1.2.1. Phương pháp giấu tin


Đầu vào của phương pháp bao gồm:

 Ảnh gốc C làm môi trường để giấu.


 Thông tin bí mật M.
Đầu ra: Ảnh đã được giấu thông tin mật.

Quá trình giấu tin vào trong ảnh sử dụng k bit LSB như sau:

- Với C là ảnh nguyên bản 8-bit màu xám, kích thước 𝑀𝑐 × 𝑁𝑐 điểm ảnh. Người
giấu tin sẽ thực hiện biểu diễn ma trận điểm ảnh về dạng số thập phân. Công thức biến
đổi tổng quát như sau:

C = {𝑥𝑖𝑗 | 0 ≤ i ≤ 𝑀𝑐, 0 ≤ j ≤ 𝑁𝑐, 𝑥𝑖𝑗 = {0, 1, 2, …, 255}}

- Sau khi ảnh C đã được chuyển thành ma trận điểm ảnh thì tiếp tục chuyển ma trận
điểm ảnh này về mảng 1 chiều I với i phần tử, sau đó chuyển các điểm ảnh về dạng nhị
phân.

- thông điệp M chiều dài n bit sẽ chuyển về dạng nhị phân:

M = {𝑚𝑖 | 0 ≤ I < 𝑛, 𝑚𝑖{0,1}}

- Cứ 8 bit ảnh tách bỏ số bit LSB ngoài cùng bên phải và ghép phần còn lại với k bit
nhị phân đầu của thông điệp (k có thể là 2 hoặc 4 bit), kết quả thu được đưa về dạng thập
phân rồi gán ngược lại vào I(i). Cuối cùng chuyển đổi ảnh giá trị nhị phân trong mảng I
từ mảng một chiều về mảng 2 chiều 𝑀𝑐× 𝑁𝑐 phần tử, ta được ảnh mới đã giấu tin.

Ví dụ minh họa quy trình giấu tin:

Giả sử có 4 điểm ảnh đầu tiên là:

12 98 150 200

Chuyển các điểm ảnh về dạng nhị phân thu được kết quả như sau:

00001100 01100010 10010110 11001000

Thông điệp bí mật M là chữ ‘b’ có mã ASCII là 98, biểu diễn dưới dạng nhị phân
như sau: 01100010

6
Quy trình giấu thông tin: Cứ 8 bit ảnh, lấy 6 bit đầu của điểm ảnh (từ vị trí I0 đến
I5) ghép với 2 bit thông điệp (từ vị trí a0 đến a1) sẽ được:

00001101 01100010 10010100 11001010

Như vậy, ảnh sau khi giấu thông điệp M có điểm ảnh dạng nhị phân như sau:

00001101 01100010 10010100 11001010

1.2.2. Phương pháp tách tin


Cũng tương tự như quá trình giấu tin trong ảnh, quá trình tách tin trong ảnh cũng
được thực hiện theo các giai đoạn tương tự.

 Đầu vào: Ảnh mang tin.


 Đầu ra: Ảnh đã tách tin và thông tin bí mật.

Quá trình thực hiện như sau:

- Biểu diễn ma trận điểm ảnh về dạng số thập phân với 𝑀𝑐 × 𝑁𝑐 phần tử. Chuyển
đổi ma trận ảnh 𝑀𝑐 × 𝑁𝑐 phần tử về mảng 1 chiều I với i phần tử.

- Chuyển các bit ảnh về dạng nhị phân, cứ 8 bit ảnh tách lấy k bit (k có thể là 2 hoặc
4 bit) ngoài cùng bên phải rồi ghép các kết quả này lại với nhau.

- Kết quả thu được sử dụng hàm chuyển đổi từ chuỗi số nhị phân về chuỗi kí tự. Sau
khi lặp lại quá trình trên số lần bằng số lần duyệt, thu được nội dung thông điệp.

Ví dụ minh họa quy trình tách tin:

Lấy 2 bit ngoài cùng bên phải trong mỗi điểm ảnh mới:

00001101 01100010 10010100 11001010

Ghép lại với nhau được chuỗi nhị phân thông điệp, chính là chữ ‘b’: 01100010

1.3. Phương pháp giấu tin và tách tin trên k bit LSB nâng cao

1.3.1. Phương pháp giấu tin


Đầu vào:
- Ảnh gốc cấp xám.

7
- Thông điệp bí mật.
- Khóa (8 bit).
- Số bit LSB cần mã hóa trên mỗi điểm ảnh (2 hoặc 4 bit).
Đầu ra:
- Ảnh mang tin.
- Khóa.
- Số bit thông điệp cần mã hóa.
Các bước thực hiện:

- Biểu diễn ma trận điểm ảnh về dạng số thập phân với m x n phần tử. Chuyển đổi
ma trận ảnh m x n phần tử về mảng 1 chiều I với i phần tử.

- Biểu diễn thông tin giấu dưới dạng chuỗi nhị phân.

- Sử dụng một khóa 8 bit bất kỳ (khóa là kí tự, chuyển khóa về dạng mảng như với
thông điệp) đem mã hóa với chuỗi thông điệp bí mật bằng phép XOR: cứ 8 bit khóa đem
XOR với 8 bit đầu vào của thông điệp. Thực hiện lại bước này cho đến khi nội dung
thông điệp được mã hóa hết.

- Thông điệp đã mã hóa đem giấu vào ảnh tương tự như phương pháp thay thế k
bit LSB cổ điển: Là tách lấy 6 bit đầu của bit ảnh đem ghép với 2 bit đầu trong thông điệp
rồi chuyển về dạng thập phân và gán ngược lại vào ảnh.

- Thực hiện cho đến khi lấy hết các bit của chuỗi nhị phân thông điệp để ghép với
các bit ảnh. Chuyển đổi ảnh I từ mảng một chiều về mảng 2 chiều m x n phần tử, ta được
ảnh mới đã giấu tin.

Ví dụ minh họa: Giả sử có 4 điểm ảnh đầu tiên là:

12 98 150 200

Chuyển các điểm ảnh về dạng nhị phân thu được kết quả như sau:

00001100 01100010 10010110 11001000

Thông điệp bí mật M là chữ ‘c’ có mã ASCII là 97, biểu diễn dưới dạng nhị phân
như sau: 01100011

8
Nhập khóa, cũng là 1 kí tự 8 bit, giả sử là chữ ‘b’, có dạng nhị phân như sau:
01100010

Mã hóa thông điệp chính là dùng phép XOR(a, b) sẽ được: 00000001

Cứ 8 bit ảnh, ta lấy 6 bit đầu của điểm ảnh ghép với 2 bit thông điệp đã mã hóa sẽ
được: 00001100 01100000 10010100 11001001

1.3.2. Phương pháp tách tin


Đầu vào:

- Ảnh đã giấu tin.


- Khóa (8 bit).
- Số lần duyệt.
- Số bit thông điệp cần mã hóa.
Đầu ra:
- Ảnh đã tách tin
- Thông điệp.
Các bước thực hiện:

- Biểu diễn ma trận điểm ảnh về dạng số thập phân với m x n phần tử. Chuyển đổi ma
trận ảnh m x n phần tử về mảng 1 chiều I với i phần tử.

- Chuyển các bit ảnh về dạng nhị phân, cứ 8 bit ảnh tách lấy 2 bit ngoài cùng bên phải.
Đem ghép các kết quả này lại với nhau.

- Kết quả thu được sử dụng hàm chuyển đổi từ chuỗi số nhị phân về chuỗi kí tự. Sau khi
lặp lại quá trình trên số lần bằng số lần duyệt, ta thu được nội dung thông điệp đã mã hóa.

- Sử dụng hàm giải mã thực hiện giải mã thông điệp bằng khóa 8 bit, ta thu được kết quả
là nội dung gốc của thông điệp.

- Trường hợp chuyển đổi thông điệp về bảng mã đã được quy ước sẵn: Tương tự như
trường hợp chuyển đổi kí tự về mã nhị phân của nó, nhưng ở đây khi giấu tin ta sử dụng
bảng quy đổi các kí tự và chữ số theo một chuẩn do người lập trình tự định nghĩa. Đến
bước tách ta lại quy đổi ngược lại về dạng kí tự và số ban đầu.

9
Ví dụ minh họa: Quy trình tách tin: Lấy 2 bit ngoài cùng bên phải trong mỗi điểm
ảnh mới: 00001100 01100000 10010100 11001001

Ghép lại với nhau được chuỗi nhị phân thông điệp nhưng đã bị mã hóa: 00000001

Sử dụng hàm mã hóa để lấy lại thông điệp gốc M, bằng cách XOR(M, b) ta được
nhị phân của chữ ‘c’: 01100011

1.4. Đánh giá phương pháp LSB


Ưu điểm:

 Chất lượng hình ảnh sau giấu tin hầu như không bị ảnh hưởng.
 Kỹ thuật LSB đơn giản, dễ cài đặt và phát huy hiệu quả tốt trong nhiều ứng dụng.
 Kỹ thuật LSB là nền tảng cơ bản cho nhiều kỹ thuật phức tạp sau này.

Nhược điểm:

 Tính bền vững thấp; thông tin mật dễ bị thay đổi do sự tác động vào hình ảnh.
 Phát hiện thông tin dễ dàng vì thuật toán đơn giản. Để giải quyết nhược điểm này
trong quá trình giấu tin thường sử dụng khóa bí mật để mã hóa thông tin cần giấu
trước khi sử dụng kỹ thuật LSB hoặc áp dụng phương thức Seed. Phương thức
Seed thông qua phép logarithm rời rạc để chọn ra các dãy pixel ngẫu nhiên thay
thế việc ánh xạ tuần tự mà LSB sử dụng. Điều này cũng giúp thông tin giấu được
an toàn hơn vì để có được thông điệp, kẻ tấn công cần nắm rõ thuật toán được sử
dụng trong phương thức Seed.

10
Chương 2: Tạo số giả ngẫu nghiên
2.1. Giới thiệu
Có rất nhiều phương pháp đáng tin cậy để sinh các số ngẫu nhiên cho việc mô
phỏng ngẫu nhiên thông qua các bộ sinh số ngẫu nhiên với cơ sở toán học vững chắc.
Chúng ta sẽ xem xét một số phương pháp tạo số ngẫu nhiên quan trọng.

Một phương pháp chấp nhận được để tạo số giả ngẫu nhiên phải đạt được các yêu
cầu sau:
1. Các số được tạo ra phải tuân theo phân phối đều, bởi vì thực sự các sự kiện ngẫu
nhiên đều tuân theo phân phối này. Vì vậy, bất cứ một sự mô phỏng các sự kiện
ngẫu nhiên nào cũng tuân theo quy luật này hay ít nhất là xấp xỉ.
2. Các số được tạo ra cần phải độc lập, nghĩa là giá trị của một số trong dãy số ngẫu
nhiên không ảnh hưởng đến giá trị của số kế tiếp.
3. Dãy số ngẫu nhiên được tạo ra cần phải tái tạo lại được. Điều này cho phép lặp lại
thí nghiệm mô phỏng.
4. Dãy số không được lặp lại đối với bất cứ chiều dài nào. Theo lý thuyết thì không
thể có, nhưng vì mục đích thực tế thì khả năng lặp lại của một chu kỳ dài là phù
hợp. Chu kỳ lặp lại của một bộ số ngẫu nhiên được gọi là giai đoạn của nó.
5. Việc tạo các số ngẫu nhiên cần phải nhanh chóng vì trong các nghiên cứu mô
phỏng, đòi hỏi cần có nhiều số ngẫu nhiên, nếu việc tạo các số diễn ra chậm thì có
thể mất nhiều thời gian và tăng giá thành các nghiên cứu mô phỏng.
6. Trong việc taọ số ngẫu nhiên nên sử dụng càng ít bộ nhớ càng tốt. Mô hình mô
phỏng thường đòi hỏi bộ nhớ lớn, do bộ nhớ thường có hạn nên việc giảm tối đa
việc chiếm dụng bộ nhớ trở nên rất cần thiết trong việc tạo ra số ngẫu nhiên.
Chúng ta sẽ tìm hiểu một số phương pháp để tạo số ngẫu nhiên cơ bản. Dựa vào
những phương pháp này, chúng ta sẽ tiếp tục trong chương tiếp theo để xem xét những
phương pháp tạo những số ngẫu nhiên mà có một phân phối nhất định, như phân phối số
mũ, phân phối chuẩn,...

2.2. Thuật toán tạo ra các số giả ngẫu nhiên

2.2.1 Phương pháp cơ bản


a. Phương pháp nửa bình phương (Middle-square method)
Kỹ thuật nửa bình phương do John von Neuman phát triển vào những năm 40. Bắt
đầu từ số đầu tiên cho trước, ta bình phương nó lên và số giữa của số bình phương này

11
được dùng làm số thứ hai của dãy số. Kế tiếp, bình phương số thứ hai và lấy số giữa của
số bình phương này làm số thứ ba cho dãy số. Quá trình cứ lặp lại tiếp tục như vậy.
Ví dụ 1:
Giả sử số đầu x0 = 25, khi đó các số ngẫu nhiên có 2 chữ số gồm
(25)2 = 0625 ⇒ x1 = 62.
(62)2 = 3844 ⇒ x2 = 84.
(84)2 = 7056 ⇒ x3 = 05.
(05)2 = 0025 ⇒ x4 = 02.
(02)2 = 0004 ⇒ x5 = 00.
(00)2 = 0000 ⇒ x6 = 00.
Ví dụ 2:
Giả sử số đầu x0 = 3187, khi đó các số ngẫu nhiên có 4 chữ số gồm
(3187)2 = 10156969 ⇒ x1 = 1569.
(1569)2 = 02461761 ⇒ x2 = 4617.
(4617)2 = 21316689 ⇒ x3 = 3166.
(3166)2 = 10023556 ⇒ x4 = 0235.
(0235)2 = 00055225 ⇒ x5 = 0552.
(0552)2 = 00304704 ⇒ x6 = 3047.
(3047)2 = 09284209 ⇒ x7 = 2842.
Phương pháp nửa bình phương có một số tính chất sau:
 Các dãy số được tạo ra có chu kỳ ngắn.
 Bất kỳ lúc nào số 0 đều tạo ra các số bằng 0. (trường hợp ví dụ 1)

b. Phương pháp đồng dư bậc hai


Phương pháp này gần như tương đương với phương pháp nửa bình phương nhưng
có chu kỳ dài hơn. Mối quan hệ phép đệ quy cho phương pháp này được xác định bởi:
xn+1 = (xn(xn + 1)) mod m, với n  0, xo mod 4 =2, m= 2k
Ví dụ:
Với x0 = 2, m = 16 và tạo dãy số ngẫu nhiên sử dụng phương pháp đồng dư bậc hai.
x0 = 2
x1 = (x0(x0 + 1)) mod 16 = (2(2 + 1)) mod 16 = 6

12
x2 = (x1(x1 + 1)) mod 16 = (6(6 + 1)) mod 16 = 10
x3 = (x2(x2 + 1)) mod 16 = (10(10 + 1)) mod 16 = 14
x4 = (x3(x3 + 1)) mod 16 = (14(14 + 1)) mod 16 = 2
x5 = (x4(x4 + 1)) mod 16 = (2(2 + 1)) mod 16 = 6
x6 = (x5(x5 + 1)) mod 16 = (6(6 + 1)) mod 16 = 10
x7 = (x6(x6 + 1)) mod 16 = (10(10 + 1)) mod 16 = 14
x8 = (x7(x7 + 1)) mod 16 = (14(14 + 1)) mod 16 = 2

Dùng phần mềm R để tạo ra 50 số ngẫu nhiên theo phương pháp này ta có câu lệnh như
sau:
> x<-1
> for(j in 1:50){
+ x[0]<-2
+ x[j+1]<-(x[j]*(x[j]+1))%%16
+}
> print(x)

Ta có kết quả như sau:


[1] 1 2 6 10 14 2 6 10 14 2 6 10 14 2 6 10 14 2 6 10 14 2 6 10 14
[26] 2 6 10 14 2 6 10 14 2 6 10 14 2 6 10 14 2 6 10 14 2 6 10 14 2
[51] 6
Phương pháp đồng dư bậc hai được sử dụng khi m là lũy thừa của 2, và có chu kỳ
dài hơn phương pháp nửa bình phương.

c. Phương pháp đồng dư tuyến tính (Linear congruence algorithm)


Phương pháp đồng dư tuyến tính (Linear Congruential Generators – LCG) là
phương pháp được sử dụng thông dụng nhất, được đưa ra đầu tiên bởi Lehmer. Trạng thái
tại bước thứ n là một số nguyên xn và hàm chuyển T được định nghĩa như sau:
xn = (a xn-1 +c ) mod m, n ≥ 0
Trong đó: x0 là giá trị khởi đầu cho trước (0 ¿ xo ¿ m)
a là hằng số nhân (0 ¿ a ¿ m).
c là gia số (0 ¿ c ¿ m).

13
m là modul (m > 0).
Chú ý :
1. Nếu a=1: phương pháp được gọi là phương pháp cộng.
2. Nếu c=0: phương pháp được gọi là phương pháp nhân (multiplicative congruential
random number generator).
3. Nếu c ¿ 0, phương pháp được gọi là phương pháp đồng dư hỗn tạp (mixed
congruential random number generator).
4. Các LCG nhân (c=0) nhanh hơn các LCG hỗn tạp (c ¿ 0) do chúng có ít phép toán
cộng hơn.
5. Trong thực tế phương pháp nhân được dùng nhiều hơn phương pháp cộng. Bởi vì theo
phương pháp này xi+1 được xác định bởi xi. Do (m+1) giá trị xo,x1,.., xm không thể phân
biệt, nên có ít nhất một giá trị xuất hiện 2 lần, ví dụ như xi và xi+k
Khi đó xi+k,…, xi+k-1 được lặp lại như xi+k,…, xi+2k-1 và như vậy dãy số xi tuần hoàn với
chu kỳ k<=m. Toàn bộ chu kì m luôn có thể đạt được với a=c=1.
Bên cạnh đó, sự lựa chọn các tham số a, c, m, xo rất quan trọng đối với chất lượng của
bộ sinh. Nếu chúng không được chọn chính xác, bộ sinh có thể sẽ không có chu kỳ lớn
nhất, hay các số được sinh ra có thể không thể hiện tính ngẫu nhiên tốt hay thậm chí bộ
sinh có thể không thực hiện hiệu quả. Đối với bộ số nhân lớn nhất là m-1 và nếu khi 0
xảy ra thì nó sẽ lặp lại không xác định.
6. Thông thường, ta nên chọn m để làm cho toán tử modul có hiệu lực và sau đó chọn a
và c để làm cho chu kỳ càng dài càng tốt.
7. Một chu kỳ đầy đủ (có độ dài m) có thể đạt được khi một số của điều kiện được thỏa
mãn như trong định lý sau.
Định lý :
Một bộ sinh đệ quy có chu kỳ đầy đủ m khi và chỉ khi nó thỏa các điều kiện sau:
(i). USCLN (c, m) = 1 (nghĩa là c và m luôn có ước số chung bằng 1).
(ii). a  1 mod p đối với mỗi ước nguyên tố p của m (nghĩa là mỗi ước số chung
của m cũng là ước số chung của a-1 ).
(iii). a  mod 4 nếu 4 chia hết cho m (nghĩa là, nếu m có bậc 4 thì 4 cũng là ước số
của a - 1) .
Định nghĩa:
Nếu m là nguyên tố thì a là số nguyên thủy đầu tiên của modul m nếu và chỉ nếu a n mod
m  1 với n=1, 2, 3, …, m-2.
Chú ý:

14
1. Nếu m là số nguyên tố thì chu kỳ đủ đạt được chỉ khi a = 1.
2. Ngay cả khi bộ sinh là chu kỳ đầy đủ vẫn không chắc chắn rằng các số được tạo ra là
số ngẫu nhiên. Chẳng hạn, nếu a = 1, m = 1 và c = 3 thì các điều kiện trên đều thỏa
mãn, nhưng với x0 = 0 toàn bộ dãy số được tạo ra là 4, 7, 10, 2, 5, 8, 0, 3, 6, 9, 1, 4,
7, ... chúng hầu như không phải là số ngẫu nhiên.
3. Việc lựa chọn hằng số nhân a ảnh hưởng đến độ lớn của chu kỳ và tính ngẫu nhiên của
chuỗi được sinh ra.
4. Khi m= 2n và c>0: chu kỳ tối đa là m có thể đạt được khi và chỉ khi a mod 4  1 và c
là số lẻ (thường được chọn bằng 1). Ví dụ, xét bộ sinh LCG (a, 1, 16, x 0): chu kỳ tối đa
là 16 có thể đạt được nếu và chỉ nếu a=1, 5, 9 hay 13. Khi a=3, hay 11 thì chu kỳ là 8;
khi a=7 thì chu kỳ là 4; và khi a=5 thì chu kỳ là 2. Chẳng hạn chuỗi các số nguyên giả
ngẫu nhiên sinh ra với LCG(5,1,16,1) là 1, 6, 15, 12, 13, 2, 11, 8, 9, 14, 7, 4, 5, 10, 3,
0, 1, 6, 15, 12, 13, 2, 11, 8, 9, 14,
5. Khi m=2n và c=0: chu kỳ tối đa là m/4 đạt được nếu và chỉ nếu a mod 8  1 hay a mod
8  5 (thường được chọn) và giá trị khởi đầu là số lẻ. Ví dụ, với bộ sinh LCG(a, 0, 16,
x0), chu kỳ tối đa là 4 đạt được nếu và chỉ nếu a=3, 5, 11 hay 13.
6. Khi m là số nguyên tố và a>1 (không quan tâm đến c = 0 hay không): chu kỳ tối đa là
m-1 đạt được khi và chỉ khi a là số nguyên thủy đầu tiên của modul m.
Như vậy, tham số quan trọng nhất của một LCG là modul m. Kích thước của nó
ràng buộc chu kỳ (m thường được chọn là số nguyên tố hoặc là lũy thừa của 2). Đối với
các bộ sinh đồng dư tuyến tính với modul là số nguyên tố, việc sử dụng gia số c≠0 không
tăng chu kỳ ngoại trừ khi a = 1. Thông thường, a phải lớn hơn 1 để chuỗi sinh ra có tính
ngẫu nhiên.
Ví dụ 1:
Xét bộ sinh LCG (a, 0, 13, 1), xét về tính ngẫu nhiên của chuỗi được sinh ra, a=6
hoặc a=11 tốt hơn a=2 hay a=7 mặc dù chúng sinh ra chu kì đầy đủ. Người ta thường
mong muốn các bộ sinh có chu kỳ đầy đủ hơn là các bộ sinh có chu kỳ ngắn.

15
a Chuỗi kết quả {xn} Chu kỳ
0 0, 0,… 1
1 1, 1,.. 1 Đối với
chu kỳ đầy đủ,
2 1, 2, 4, 8, 3, 6, 12, 11, 9, 5, 10, 7, 1,… 12
các sự lựa chọn
khác 3 1, 3, 9, 1 3 nhau
của giá 4 1, 4, 3, 12, 9, 10, 1,… 6 trị khởi
đầu chỉ 5 1, 5, 12, 8, 1 4 nhằm để
chuyển sang
6 1, 6, 10, 5, 9, 11, 12, 6, 3, 8, 4, 2, 1,.. 12
điểm khởi đầu
trong 7 1, 7, 10, 5, 9, 11, 12, 6, 3, 8, 4, 2, 1,… 12 chuỗi đã
xác định 8 1, 8, 12, 5, 1,.. 4 bởi a, c,
m. 9 1, 9, 3, 1,… 3 Chẳng
hạn như LCG(6,
10 1, 10, 9, 12, 3, 4, 1,.. 6
0, 13, x0) là bộ
sinh chu 11 1, 11, 4, 5, 3, 7, 12, 2, 9, 8, 10, 6, 1 12 kỳ đầy
đủ. Nếu 12 1, 12, 1,… 2 giá trị
khởi đầu xo =1, ta
có chuỗi kết quả là 1, 6, 10, 8, 9, 2, 12, 7, 3, 5, 4, 11, 1,…
Các giá trị khởi đầu giữa 1 và 12 không ảnh hưởng đến tính ngẫu nhiên của chuỗi
mà chỉ chuyển điểm khởi đầu của chuỗi. Tuy nhiên nếu bộ sinh không phải có chu kỳ đầy
đủ thì các giá trị khởi đầu khác nhau sẽ sinh ra các chuỗi kết quả khác nhau với các chu
kỳ khác nhau.
Ví dụ 2:
Nếu một LCG không phải là bộ sinh chu kỳ đầy đủ, thì các giá trị khởi đầu x o có
thể cho ra các chuỗi khác nhau và độ dài chu kỳ khác nhau. Chẳng hạn với LCG(3, 0, 16,
xo)
xo Chuỗi kết quả {xn} Chu kỳ
1, 3, 9 hoặc 11 …1, 3, 9, 11, 1,.. 4
5, 7, 13 hoặc 15 …5, 15, 13, 7, 5,… 4
2 hoặc 6 …2, 6, 2,… 2
4 hoặc 12 …4, 12, 4,… 2
10 hoặc 14 …10, 14,… 2
0 0, 0,… 1

16
8 8, 8,… 1

d. Phương pháp đồng dư cộng


Phương pháp đồng dư cộng (Additive Congruential Generators) cũng tương tự
phương pháp đồng dư tuyến tính, tuy nhiên ở đây phép toán xor trong công thức được
thay thế bằng phép toán cộng:
Xj=(Xj-1 +…+ Xj-n) mod m,
Phương pháp này nhanh vì không cần phép nhân nào cả. Ngay cả khi chỉ dùng phép
cộng số nguyên thông thường, vẫn có thể tạo được các số ngẫu nhiên tốt
Ví dụ:
x1 = 1, x2 = 2, x3 = 4, x4 = 8, x5 = 6 .

x6 = (x5 + x1) mod 10 = (6+1) mod 10 = 7.


x7 = (x6 + x2) mod 10 = (7+2) mod 10 = 9.
x8 = (x7 + x3) mod 10 = (9+4) mod 10 = 3.
x9 = (x8 + x4) mod 10 = (8+8) mod 10 = 1.
x10 = (x9 + x5) mod 10 = (1+6) mod 10 = 7.
x11 = (x10 + x6) mod 10 = (7+7) mod 10 = 4.
x12 = (x11 + x7) mod 10 = (4+9) mod 10 = 3.
x13 = (x12 + x8) mod 10 = (3+3) mod 10 = 6.
x14 = (x13 + x9) mod 10 = (6+1) mod 10 = 7.
x15 = (x14 + x10) mod 10 = (7+7) mod 10 = 4.
Dùng phần mềm R ta có thể tạo 200 số ngẫu nhiên ta dùng câu lệnh như sau:
> x<-1
> for(j in 6:200){
+ x[1]<-1
+ x[2]<-2
+ x[3]<-4
+ x[4]<-8
+ x[5]<-6
+ x[j]<-(x[j-1]+x[j-5])%%10
+}

17
> print(x)
Từ đó ta có kết quả như sau:
[1] 1 2 4 8 6 7 9 3 1 7 4 3 6 7 4 8 1 7 4 8 6 7 4 8 6 2 9 3 1 7 9 8
[33] 1 2 9 8 6 7 9 8 6 2 9 8 6 2 4 3 1 7 9 3 6 7 4 3 6 2 9 3 6 2 4 3
[65] 6 2 4 8 1 7 9 3 1 2 9 8 1 2 4 3 1 2 4 8 1 2 4 8 6 7 9 3 1 7 4 3
[97] 6 7 4 8 1 7 4 8 6 7 4 8 6 2 9 3 1 7 9 8 1 2 9 8 6 7 9 8 6 2 9 8
[129] 6 2 4 3 1 7 9 3 6 7 4 3 6 2 9 3 6 2 4 3 6 2 4 8 1 7 9 3 1 2 9 8
[161] 1 2 4 3 1 2 4 8 1 2 4 8 6 7 9 3 1 7 4 3 6 7 4 8 1 7 4 8 6 7 4 8

2.2.2 Phương pháp dựa trên mật mã học nguyên thuỷ


a. Dựa trên mật mã khối
Một mật mã khối an toàn có thể được chuyển đổi thành CSPRNG bằng cách chạy
nó ở chế độ bộ đếm. Điều này được thực hiện bằng cách chọn một khóa ngẫu nhiên và
mã hóa số 0, sau đó mã hóa số 1, sau đó mã hóa số 2, v.v. Bộ đếm cũng có thể được bắt
đầu ở một số tùy ý khác 0. Tuy nhiên, khi được sử dụng một mình, nó không đáp ứng tất
cả các tiêu chí của CSPRNG (như đã nêu ở trên) vì nó không mạnh chống lại "các phần
mở rộng thỏa hiệp trạng thái": với kiến thức về trạng thái (trong trường hợp này là bộ
đếm và chìa khóa), bạn có thể dự đoán tất cả bằng các số trong quá khứ.

b. Dựa trên hàm băm


Một mã băm bảo mật mã hóa của bộ đếm cũng có thể hoạt động như một
CSPRNG tốt trong một số trường hợp. Trong trường hợp này, cũng cần thiết rằng giá trị
ban đầu của bộ đếm này là ngẫu nhiên và bí mật. Tuy nhiên, có rất ít nghiên cứu về các
thuật toán này để sử dụng theo cách này, và ít nhất một số tác giả cảnh báo chống lại việc
sử dụng này.

2.2.3 Phương pháp dựa trên lý thuyết số học


a. Blum Blum Shub
Blum Blum Shub (B.B.S.) là một bộ tạo số giả ngẫu nhiên được đề xuất vào năm
1986 bởi Lenore Blum, Manuel Blum và Michael Shub có nguồn gốc từ hàm một chiều
của Michael O. Rabin.

Công thức tạo số ngẫu nhiên: x n+1=x 2n mod M

Trong đó M là tích của 2 số nguyên tố lớn p và q

18
b. Blum–Micali algorithm
Thuật toán Blum – Micali là một trình tạo số giả ngẫu nhiên an toàn về mặt mật mã.
Thuật toán có được đảm bảo tính bảo mật bằng độ khó của các bài toán các logarit rời
rạc.

Công thức tạo số ngẫu nhiên: x n+1=g x mod p


i

Trong đó p là 1 số nguyên tố lẻ, g và p là 2 số được chọn trước

Thuật toán này đảm bảo không thể bị suy ngược nhờ độ phức tạp của thuật toán logarit
rời rạc

2.2.4 Phương pháp đặc biệt


a. Yarrow algorithm
Thuật toán Yarrow là một họ các bộ tạo số giả mật mã (CPRNG) được phát minh
bởi John Kelsey, Bruce Schneier và Niels Ferguson và được xuất bản vào năm 1999.
Thuật toán Yarrow rõ ràng là không có ký hiệu, miễn phí bản quyền và mã nguồn mở;
không cần giấy phép để sử dụng nó. Một thiết kế cải tiến từ Ferguson và Schneier,
Fortuna, được mô tả trong cuốn sách của họ, Mật mã thực tế Yarrow đã được sử dụng
trong FreeBSD, nhưng hiện được thay thế bởi Fortuna. Yarrow cũng được tích hợp trong
iOS và macOS cho các lập trình viên, nhưng Apple đã chuyển sang Fortuna kể từ năm
2020.

Yarrow-160 sử dụng Triple DES 3 khoá ở chế độ bộ đếm để tạo đầu ra. C là giá trị bộ
đếm n-bit; K là khóa. Để tạo khối đầu ra tiếp theo, Yarrow thực hiện theo các chức năng
được hiển thị ở đây.

C=( C+ 1 ) mod 2n

R=Ek (C)

K=k bit đầu ra của số sinhra

b. ChaCha20 algorithm
ChaCha20 có liên quan chặt chẽ là mật mã dòng được phát triển bởi Daniel J.
Bernstein. ChaCha20 được thiết kế vào năm 2005, sau đó được Bernstein đệ trình lên
eSTREAM. ChaCha là một sửa đổi của Salsa20 được xuất bản vào năm 2008. Nó sử
dụng một chức năng vòng mới giúp tăng độ khuếch tán và tăng hiệu suất trên một số kiến
trúc.

ChaCha20 gồm có 4 đầu vào và được coi như 4 khoá a,b,c,d

19
Công thức tạo số ngẫu nhiên

a+ ¿ b ; d∗¿ a ; d ≪16 ;

c +¿ d ; b∗¿ c ; b ≪ 12;

a+ ¿ b ; d∗¿ a ; d ≪ 8;

c +¿ d ; b∗¿ c ; b ≪ 7 ;

c. Fortuna algorithm
Fortuna là một công cụ tạo số giả ngẫu nhiên an toàn bằng mật mã (PRNG) do
Bruce Schneier và Niels Ferguson phát minh ra và được xuất bản vào năm 2003. Nó được
đặt theo tên Fortuna, nữ thần may mắn của La Mã. FreeBSD sử dụng Fortuna cho các lập
trình viên từ FreeBSD 11. Hệ điều hành của Apple đã chuyển sang Fortuna kể từ năm
2020

Bộ tạo dựa trên bất kỳ mật mã khối tốt nào. Mật mã thực tế gợi ý AES, Serpent
hoặc Twofish. Ý tưởng cơ bản là chạy mật mã ở chế độ bộ đếm, mã hóa các giá trị liên
tiếp của bộ đếm tăng dần. Khóa cũng được thay đổi sau mỗi lần yêu cầu dữ liệu (tuy
nhiên nhỏ), để sự xâm phạm khóa trong tương lai không gây nguy hiểm cho các đầu ra
của trình tạo trước đó. Thuộc tính này được mô tả là " Fast Key Erasure" hoặc Forward
secrecy.

20
d. CryptGenRandom
CryptGenRandom là một hàm tạo số giả ngẫu nhiên an toàn bằng mật mã nhưng đã
không được dùng trong Microsoft CryptoAPI. Trong các chương trình Win32, Microsoft
khuyến nghị sử dụng nó ở bất kỳ nơi nào cần tạo số ngẫu nhiên. Một bài báo năm 2007 từ
Đại học Hebrew đã đề xuất các vấn đề bảo mật trong việc triển khai CryptGenRandom
trên Windows 2000 (giả sử kẻ tấn công có quyền kiểm soát máy). Microsoft sau đó thừa
nhận rằng các vấn đề tương tự cũng tồn tại trong Windows XP, nhưng không phải trong
Vista. Microsoft đã phát hành bản sửa lỗi cho Windows XP Gói Dịch vụ 3 vào giữa năm
2008.

21
Chương 3: Phương pháp hoán vị giả ngẫu nhiên và
Demo
3.1. Ý tưởng thực hiện
Trong kỹ thuật LSB, các thông tin mật được giấu theo cách tuần tự vào các bit cố
định của các khối (các điểm ảnh) liên tiếp hoặc theo trật tự nhất định. Kỹ thuật này đơn
giản với người giấu tin, nhưng dễ bị tấn công vét cạn hoặc nhận dạng tự động.
Ý tưởng của giải pháp hoán vị ngẫu nhiên chính là việc giấu thông tin vào các vị trí
ngẫu nhiên, bất kỳ. Bên cạnh đó, mục đích của thuật toán cũng mong muốn tất cả các bit
của ảnh chứa tin đều có thể tham gia trong quá trình nhúng tin, và các bit của thông điệp
cũng được phân bố ngẫu nhiên trên toàn bộ miền không gian của ảnh chứa và không tuân
theo một thứ tự nào. Tuy nhiên, nếu thực hiện theo ý tưởng này thì cả người giấu tin và
người tách tin đều không biết được vị trí mà các bit thông được được giấu. Chính vì vậy,
phương pháp hoán vị ngẫu nhiên sẽ rất khó thực hiện.
Để giải quyết vấn đề này, các chuyên gia đề xuất giải pháp là hoán vị giả ngẫu
nhiên. Theo đó, hoán vị giả ngẫu nhiên sẽ vẫn dựa trên giải pháp hoán vị ngẫu nhiên
nhưng vị trí các bit được lựa chọn để nhúng thông điệp sẽ không phải là ngẫu nhiên nữa
mà là giả ngẫu nhiên. Có nghĩa là sẽ áp dụng một kỹ thuật hoặc một thuật toán nào đó để
sinh ra chuỗi ngẫu nhiên và chuỗi ngẫu nhiên này sẽ khác nhau sau mỗi lần giấu tin. Hình
dưới đây mô tả mô hình giấu tin và tách tin trong ảnh sử dụng phương pháp hoán vị giả
ngẫu nhiên. Trong đó những nét đứt của hình và mũi tên thể hiện những quy trình này có
thể sử dụng hoặc không sử dụng trong quy trình giấu tin và tách tin tùy theo người dùng
lựa chọn.
Bộ sinh số giả ngẫu nhiên (pseudorandom number generator - PRNG), còn được gọi
là bộ sinh bit ngẫu nhiên tất định (DRBG), là thuật toán sinh ra chuỗi các số có các thuộc
tính gần như thuộc tính của chuỗi số ngẫu nhiên [11, 12]. Chuỗi sinh ra từ bộ sinh số giả
ngẫu nhiên không thực sự là ngẫu nhiên, do nó hoàn toàn được xác định từ giá trị khởi
đầu, được gọi là nguồn (seed) của nó (mà giá trị này có thể hoàn toàn là ngẫu nhiên). Mặc
dù chuỗi gần ngẫu nhiên này gần giống với chuỗi được sinh ra bằng bộ sinh số ngẫu
nhiên từ phần cứng, bộ sinh số giả ngẫu nhiên có vai trò rất quan trọng trong thực tế vì
tốc độ trong quá trình tạo số và khả năng tái sử dụng của nó.

22
Hình : Sơ đồ nhúng và tách tin của phương pháp hoán vị giả ngẫu nhiên

3.2. Quá trình giấu tin


Theo sơ đồ tổng quan về quá trình giấu và tách tin, để thực hiện giấu tin và giải mã,
bên nhận và bên gửi cần thống nhất với nhau về việc sử dụng thuật toán sinh bộ số giả
ngẫu nhiên và giá trị khởi tạo ban đầu hoặc gửi giá trị khởi tạo qua kênh truyền an toàn.
Ngoài ra nếu thông điệp được mã hóa thì hai bên cũng cần thống nhất thuật toán mã hóa,
giải mã và gửi khóa qua kênh truyền an toàn.
Thuật toán giấu tin:
 Bước 1: Thông điệp được mã hóa (nếu cần) sau đó được chuyển sang thành dãy
nhị phân. Gọi 𝑙𝑚 là độ dài của thông điệp (ở dạng nhị phân) và tương ứng 𝑚𝑖 là
bit thứ i của thông điệp sau khi mã hóa và chuyển về dạng nhị phân.
 Bước 2: Trích xuất ma trận điểm ảnh trong ảnh, biến đổi các điểm ảnh về dạng nhị
phân và chuyển ma trận thành dãy nhị phân. Gọi 𝑙𝑐 là độ dài của ảnh sau khi
chuyển về dãy nhị phân và tương ứng 𝑐𝑖 là bit thứ i trong ảnh.
 Bước 3: Sử dụng bộ sinh số giả ngẫu nhiên và giá trị khởi tạo chọn trước, sinh dãy
số 𝑟1 , 𝑟2 , … , 𝑟𝑙𝑚
 Bước 4: Thay thế bit 𝑐𝑟𝑖 của ảnh bằng bit 𝑚𝑖 của thông điệp

23
3.3. Quá trình giải tin
Thuật toán tách tin:

 Bước 1: Trích xuất ma trận điểm ảnh trong ảnh, biến đổi các điểm ảnh về dạng nhị
phân và chuyển ma trận thành dãy nhị phân. Gọi 𝑙𝑐 là độ dài của ảnh sau khi
chuyển về dãy nhị phân và tương ứng 𝑐𝑖 là bit thứ i trong ảnh.
 Bước 2: Sử dụng bộ sinh số giả ngẫu nhiên và giá trị khởi tạo chọn trước, sinh dãy
số 𝑟1 , 𝑟2 , … , 𝑟𝑙𝑚
 Bước 3: Lần lượt lấy ra các bit bit 𝑐𝑟𝑖 của ảnh và ghép lại để được một dãy nhị
phân. Đây chính là dãy nhị phân của thông điệp.

3.4. Đánh giá


Ưu điểm

 Độ an toàn cao: do kỹ thuật này sử dụng bộ sinh số giả ngẫu nhiên nên kẻ tấn công
khó tìm được quy luật giấu tin như LSB vì các bit của thông điệp được giấu vào
các bit ngẫu nhiên trong ảnh.

Nhược điểm:

 Dễ xảy ra việc xung đột trong quá trình nhúng khi chu kì của bộ sinh số giả ngẫu
nhiên không đủ lớn (nhỏ hơn hoặc bằng 𝑙𝑚) sẽ dẫn đến tính trạng có nhiều hơn 1
bit được giấu vào cùng 1 vị trí
 Ảnh sẽ bị thay đổi giá trị rất nhiều do các bit thông điểm được giấu vào các bit bất
kì chứ không phải chỉ bit LSB. Điều này dẫn đến kẻ tấn công dễ dàng phát hiện
ảnh đang chứa tin chỉ cần nhìn qua bằng mắt thường. Để giải quyết nhược điểm
này, trong thực tế các chuyên gia thường kết hợp giữa kỹ thuật LSB với kỹ thuật
hoán vị giả ngẫu nhiên. Theo đó, phương pháp hoán vị giả ngẫu nhiên sẽ sinh ra
các số ngẫu nhiên và các số ngẫu nhiên này sẽ được coi là các điểm ảnh. Sau đó sẽ
áp dụng kỹ thuật LSB vào để nhúng thông tin và các vị trí vừa tìm được.

24
3.5. Demo

Thuật toán giấu tin


Bước 1: Thông điệp được thêm “$end” vào cuối và mã hóa (nếu cần) sau đó được chuyển
sang thành dãy nhị phân. Gọi l m là độ dài của thông điệp (ở dạng nhị phân) và tương ứng
m i là bit thứ i của thông điệp sau khi mã hóa và chuyển về dạng nhị phân.

message += "$end"
b_message = ''.join([format(ord(i), "08b") for i in message])
req_pixels = len(b_message)

Ví dụ: ta có thông điệp đầu vào là “xinchao123” thông điệp sẽ được thêm chuỗi “$end”
vào cuối trở thành “xinchao123$end” và được mã hoá thành dạng nhị phân có dạng

(x) 120 = 0111 1000

(i) 105 = 0110 1001

(n) 110 = 0110 1110

(c) 099 = 0110 0011

(h) 104 = 0110 1000

(a) 097 = 0110 0001

(0) 111 = 0110 1111

(1) 049 = 0011 0001

(2) 050 = 0011 0010

(3) 051 = 0011 0011

($) 036 = 0010 0100

(e) 101 = 0110 0101

(n) 110 = 0110 1110

(d) 100 = 0110 0100

Ta thu được chuỗi:

25
“01111000011010010110111001100011011010000110000101101111001100010011001
00011001100100100011001010110111001100100”

Bước 2: Trích xuất ma trận điểm ảnh trong ảnh, biến đổi các điểm ảnh về dạng nhị phân
và chuyển ma trận thành dãy nhị phân. Gọi 𝑙𝑐 là độ dài của ảnh sau khi chuyển về dãy nhị
phân và tương ứng 𝑐𝑖 là bit thứ i trong ảnh.
img = Image.open(src, 'r')
width, height = img.size
array = np.array(list(img.getdata()))

Ví dụ: ta có một file ảnh có kích thước 512x512 px

Ta sẽ thu được 1 ma trận điểm ảnh gồm 512x512 = 262144 điểm ảnh. Mỗi điểm anh gồm
3 bit màu RGB nên ta sẽ thu được ma trận gồm 262144x3 phần tử

Bước 3: Sử dụng bộ sinh số giả ngẫu nhiên và giá trị khởi tạo chọn trước, sinh dãy số
r 1 , r 2 , … , r lm

Với mỗi phương pháp sinh số giả ngẫu nhiên khác nhau ta sẽ thu được một bộ số giả
ngẫu nhiên khác nhau:

a) Hoán vị giả ngẫu nhiên sử dụng phương pháp nửa bình phương (Middle-square
method):
def PRNG0(seed, total_pixels):
# phương pháp cơ bản
# Phương pháp nửa bình phương (Middle-square method)
return int(str(int(seed) ** 2).zfill(8)[2:6]) % total_pixels

Ví dụ: với seed ban đầu x 0=1234 và tổng điểm ảnh là p=262144

Ta có công thức tạo số giả ngẫu nhiên

x n+1=x 2n [ 2:6 ] mod p

Ta sẽ sinh được một chuỗi số giả ngẫu nhiên:

[5227, 3215, 3362, 3030, 1809, 2724, 4201, 6484, 422, 1780, 1684, 8358, 8561, 2907,
4506, 3040, 2416, 8370, 569, 3237, 4781, 8579, 5992, 9040, 7216, 706, 4984, 8402,
5936, 2360, 5696, 4444, 7491, 1150, 3225, 4006, 480, 2304]

26
b) Hoán vị giả ngẫu nhiên sử dụng phương pháp đồng dư bậc 2:
def PRNG0(seed, total_pixels):
# phương pháp cơ bản
# phương pháp đồng dư bậc 2 với n = 10
return int(int(seed) * (int(seed) + 1) % 2**10) % total_pixels

Ví dụ: với seed ban đầu x 0=1234 (thoả mãn x 0 mod 4=2), n=10 và tổng điểm ảnh là
p=262144

Ta có công thức tạo số giả ngẫu nhiên:

x n +1=( ( x n ( x n +1 ) ) mod n ) mod p , với n 0 , x o mod 4=2 , n=2k

Ta sẽ sinh được chuỗi số giả ngẫu nhiên:

[278, 762, 798, 674, 294, 714, 558, 626, 310, 154, 318, 66, 326, 106, 78, 18, 342, 570,
862, 482, 358, 522, 622, 434, 374, 986, 382, 898, 390, 938, 142, 850, 406, 378, 926, 290,
422, 330]

Vì chọn n = 10 nên các số giả ngẫu nhiên không vượt quá 210=1024

c) Hoán vị giả ngẫu nhiên sử dụng phương pháp đồng dư tuyến tính:
def PRNG0(seed, total_pixels):
# phương pháp cơ bản
# phương pháp đồng dư tuyến tính (Linear congruence algorithm)
# với c = 13, a = 17 và m = 10091
return int(17 * int(seed) + 13) % 10091 % total_pixels

Ví dụ: với seed ban đầu x 0=1234 , a=17 , c=13 , m=10091 và tổng điểm ảnh là p=262144

Ta có công thức tạo số giả ngẫu nhiên:

x n+1=( ( a x n +c ) mod m ) mod p


Trong đó a là hằng số nhân (0 a m)
c là gia số (0 c m)
m là modul (m>0) và m là 1 số nguyên tố đủ lớn
Ta sẽ sinh được chuỗi số giả ngẫu nhiên:
[809, 3675, 1942, 2754, 6467, 9042, 2362, 9894, 6755, 3847, 4866, 2007, 3859, 5070,
5475, 2269, 8313, 60, 1033, 7483, 6132, 3347, 6457, 8872, 9563, 1128, 9098, 3314,
5896, 9426, 8890, 9869, 6330, 6713, 3133, 2819, 7572, 7645]

27
d) Hoán vị giả ngẫu nhiên sử dụng phương pháp Blum Blum Shub:
def PRNG0(seed, total_pixels):
# phương pháp dựa trên lý thuyết số học
# Blum Blum Shub algorithm với p = 21169 và q = 22189
return int(int(seed) ** 2 % (21169 * 22189)) % total_pixels

Ví dụ: với seed ban đầu x 0=1234 , p=21169 , q=22189 và tổng điểm ảnh là p=262144

Ta có công thức tạo số giả ngẫu nhiên:


x n+1=( x ¿ ¿ n2 mod M ) mod p ¿

Trong đó M là tích của 2 số nguyên tố lớn p và q

Ta sẽ sinh được chuỗi số giả ngẫu nhiên


[212036, 159437, 21771, 63196, 53288, 63634, 30300, 104819, 248462, 168301, 8093,
222793, 86380, 222045, 227329, 215691, 247234, 108874, 211727, 26526, 77287,
60181, 10862, 18244, 182800, 259189, 216262, 214893, 6735, 9313, 224449, 248546,
236077, 117131, 42160, 258601, 61819, 136241]
Các số giả ngẫu nhiên được sinh ra rất lớn và khó tìm được quy luật
e) Hoán vị giả ngẫu nhiên sử dụng phương pháp Blum–Micali:
def PRNG0(seed, total_pixels):
# phương pháp dựa trên lý thuyết số học
# Blum–Micali algorithm với g = 173 và p = 20173
return int(173 ** int(seed) % 20173) % total_pixels

Ví dụ: với seed ban đầu x 0=1234 , g=173 , p=20173 và tổng điểm ảnh là p=262144

Ta có công thức tạo số giả ngẫu nhiên:

x n+1=g x mod p
i

Trong đó p là 1 số nguyên tố lẻ, g và p là 2 số được chọn trước

Ta sẽ sinh được chuỗi số giả ngẫu nhiên:


[9423, 11801, 4538, 14001, 11699, 18853, 18975, 5654, 2598, 13726, 14698, 4452,
6276, 6867, 10729, 11754, 19778, 18453, 13377, 11041, 2248, 14232, 6614, 4113,
13947, 14996, 11081, 17001, 8642, 4907, 6376, 14172, 17252, 18626, 11785, 3651,
10658, 3005]

28
Các số giả ngẫu nhiên đảm bảo không bị suy ngược nhờ độ phức tạp của thuật toán
logarit rời rạc

f) Hoán vị giả ngẫu nhiên sử dụng hàm băm SHA-256


def PRNG0(seed, total_pixels):
# phương pháp dựa trên mật mã học nguyên thuỷ
# phương pháp sử dụng hàm băm SHA-256
return int.from_bytes(hashlib.sha256(str(seed).encode()).digest(),
"little") % total_pixels

Ví dụ: với seed ban đầu x 0=1234 và tổng điểm ảnh là p=262144

Ta sẽ sinh được chuỗi số giả ngẫu nhiên:

[240643, 200651, 198388, 236782, 42214, 241223, 90407, 176037, 77272, 135002,
156638, 137593, 155992, 210886, 232588, 160102, 51987, 255003, 107611, 105326,
46577, 35091, 225885, 134914, 84470, 73777, 141160, 50811, 187919, 86072, 155519,
6803, 89714, 4682, 234435, 8576, 70037, 38238]

g) Hoán vị giả ngẫu nhiên sử dụng phương pháp ChaCha20 algorithm


def PRNG0(seed, total_pixels):
# phương pháp đặc biệt
# ChaCha20 algorithm
key =
55528940176513310056720497386431866891917161321970637298210495689590489365111
cipher = ChaCha20.new(key=key.to_bytes(32, "little"),
nonce=int(seed).to_bytes(8, "little"))
ciphertext = cipher.encrypt(int(123).to_bytes(32,"little"))
return int.from_bytes(ciphertext, "little") % total_pixels

Ví dụ: với seed ban đầu x 0=1234 và tổng điểm ảnh là p=262144

Ta cần biết thêm khoá bí mật 256 bit để sinh được bộ sinh số giả ngẫu nhiên. Giả sử cả
bên gửi và bên nhận đều đã thống nhất về khoá bí mật này. Ta sử dụng seed để thay cho
nonce ở bộ sinh số này. Nếu nonce của thuật toán khác nhau sẽ sinh ra những bộ sinh số
khác nhau.

Ta sẽ sinh được chuỗi số giả ngẫu nhiên:

[237468, 11764, 213735, 195031, 174641, 246614, 115117, 139541, 118712, 151109,
28205, 198598, 224109, 256496, 124127, 193299, 131077, 30894, 247803, 74571,

29
27630, 174312, 132494, 179632, 192509, 208457, 131028, 65463, 152140, 97760,
143613, 44140, 135539, 56799, 75974, 201161, 7715, 230191]

Bước 4: Thay thế bit c r của ảnh bằng bit m i của thông điệp
i

Ta sẽ kiểm tra nếu độ dài của thông điệp lớn hơn số điểm ảnh hoặc chuỗi số từ thuật toán
sinh số giả ngẫu nhiên không đủ ta sẽ thông báo lỗi để người nhập thay đổi đầu vào của
thuật toán.
if req_pixels > total_pixels:
print("ERROR: Need larger file size")
else:
index=0
already_seen = list()
while index < req_pixels:
seed = PRNG0(seed, total_pixels)
if seed not in already_seen:
already_seen.append(seed)
for i in range(0, 3):
if index < req_pixels:
array[seed][i] = int(bin(array[seed][i])[2:9] +
b_message[index], 2)
index += 1
else:
print("ERROR: Need another key")
break

Bước 5: Từ ma trận điểm ảnh sau khi giấu thông điệp ta chuyển về dạng hình ảnh và xuất
ra kết quả:
array = array.reshape(height, width, n)
enc_img = Image.fromarray(array.astype('uint8'), img.mode)
enc_img.save(dest)

Thuật toán tách tin


Bước 1: Trích xuất ma trận điểm ảnh trong ảnh, biến đổi các điểm ảnh về dạng nhị phân
và chuyển ma trận thành dãy nhị phân. Gọi 𝑙𝑐 là độ dài của ảnh sau khi chuyển về dãy nhị
phân và tương ứng 𝑐𝑖 là bit thứ i trong ảnh.
img = Image.open(src, 'r')
array = np.array(list(img.getdata()))

Bước 1 của thuật toán tách tin giống với bước 2 của thuật toán giấu tin.

30
Bước 2: Sử dụng bộ sinh số giả ngẫu nhiên và giá trị khởi tạo chọn trước, sinh dãy số
r 1 , r 2 , …và lần lượt lấy ra các bit c r của ảnh.
i

while 1:
hidden_bits = ""
temp_seed = seed
for p in range(start):
temp_seed = PRNG0(temp_seed, total_pixels)
for q in range(0, 3):
hidden_bits += (bin(array[temp_seed][q])[2:][-1])

hidden_bits = [hidden_bits[i:i+8] for i in range(0, len(hidden_bits), 8)]

Bước 3: ghép các ký tự thu được cho đến khi gặp chuỗi “$end” thì dừng. Bỏ chuỗi
“$end” ở cuối chuỗi ký tự thu được ta nhận được thông điệp ban đầu
for i in range(len(hidden_bits)):
if message[-4:] == "$end":
break
else:
message += chr(int(hidden_bits[i], 2))
if "$end" in message:
print("Hidden Message:", message[:-4])
break

31
Tài liệu tham khảo

[1] Đ. X. Chợ, Bài Giảng Các Kỹ Thuật Giấu Tin, Hà Nội: Học viện Công nghệ Bưu
chính Viễn thông, 2018.

[2] N. T. Liệu, "Tiểu luận học phần Mô phỏng giả ngẫu nhiên," Đại học Huế Trường Đại
học Khoa học, Huế, 2009.

32

You might also like