Xây dựng hệ mật mã RSA thử nghiệm [1], [2], [4], [6], [7], [8]

Một phần của tài liệu Số học số lớn cho mật mã luận án thạc sĩ (Trang 60 - 70)

6. Ý nghĩa khoa học và thực tiễn cửa đề tài

3.2 Xây dựng hệ mật mã RSA thử nghiệm [1], [2], [4], [6], [7], [8]

Việc xây dựng hệ mã RSA muốn thành công thì phải giải quyết các bài toán ở trên, các bài toán ở trên đƣợc cài đặt nhƣ sau:

Hàm kiểm tra tính nguyên tố Cú pháp

bool Prime(BigNum p); Input: số p

Output: true nếu p là số nguyên tố; false ngoài ra. Thí dụ Prime( 1) = false; Prime(0) = false; Prime(1) = false; Prime(2) = true; Prime(5) = true; Prime(120) = false; Thuật toán

Nếu p là số lẻ thì chỉ cần kiểm tra xem p có ƣớc lẻ hay không (1). Số nguyên tố chẵn duy nhất là số 2.

Số p là nguyên tố khi và chỉ khi p không có ƣớc nguyên tố nào trong khoảng 2..

Nếu đã biết dãy k số nguyên tố q1 = 2, q2, …, qk thì chỉ cần xét xem p có ƣớc qi nào trong khoảng 2.. .

Thuật toán AKS của ba nhà toán học India Manindra Agrawal, Neeraj Kayal, và Nitin Saxena Đại học Indian Institute of Technology Kanpur (đề xuất tháng 8 năm 2002) có thể kiểm tra tính nguyên tố trong thời gian đa thức.

Input: integer p > 1.

Output: true nếu p là số nguyên tố; false, ngoài ra. If n = ab a, b nguyên > 1 then return false.

Tìm số nguyên dương nhỏ nhất r thỏa or(n) > (log n)2. If tồn tại a ≤ r thỏa 1 < ucln(a,n) < n then return false;

If n ≤ r then return true. For a = 1 to do

if (X+a)n ≠ Xn+a (mod xr−1,n) then return false; return true.

log tính theo cơ số 2. (r) là hàm Euler = số lƣợng các số nguyên dƣơng < r và nguyên tố cùng nhau với r. or(n) là bậc nhân tử của n theo modulo r.

Cài đặt theo định nghĩa (1).

bool Prime(BigNum p){ if (p < 2) return 0; if (p < 4) return 1;

if (EVEN(p)) return 0; // so chan BigNum can = BigNum(sqrt(p)); BigNum d = 3;

while(d<=can) { if (p % d == 0) return 0; d+=2; } return 1; }

Hàm sinh các số nguyên tố trong khoảng 1.. n

Cú pháp

Long Sieve(const char * fn, int n);

Input: - fn: tên file fn ghi các số nguyên tố sẽ sinh ra. - n giới hạn tìm kiếm.

Output: file fn chứa các số nguyên tố trong khoảng 1.. n.

Thí dụ: Long Sieve(“prime.dat”, 100);

Sinh và ghi các số nguyên tố trong khoảng 1..100 vào file prime.dat, mỗi số một dòng. 2 3 5 … 97

Thuật toán: Sàng Eratosthenes Viết dãy số 1.. n;

Xóa số 1. for i = 2..

if (số i chƣa bị xóa) then

Xóa các bội của i kể từ i2 .. n; endif

Ghi các số chƣa bị xóa vào file fn.

Cài đặt: Dùng mảng a đánh dấu, a[i] = 0 i là số nguyên tố (không bị xóa);

a[i] = 1 i là hợp số (xóa);

int LSieve(const char * fn, int n) { const char XOA = 1;

const char NGTO = 0; char * a = new char[n];

memset(a,NGTO,n*sizeof(char)); int i, j , can = int(sqrt(n)); for (i = 2; i <= can; ++i)

if (a[i] == NGTO) { // i ng to for (j = i*i; j <= n; j += i) a[j] = XOA; } ofstream f(fn); j = 0; for (i = 2; i <= n; ++i)

if (a[i] == NGTO) { f << i << endl; ++j; } f.close();

delete [] a; return j; }

Hàm sinh số nguyên tố sát sau số x. Cú pháp

BigNum NextPrime(BigNum x); Input: số x.

Output: số nguyên tố sát sau x.

Thí dụ:

p = NextPrime(p); // p = 101 Thuật toán

Nếu x < 2 return 2;

Duyệt các số lẻ sau x gặp số nguyên tố đầu tiên thì return. Cài đặt

BigNum NextPrime(BigNum x){ if (x < 2) return 2;

BingNum p = (Even(x)) ? x: x-1;

do{p += 2;}while(!Prime(p));//Kiểm tra số nguyên tố return p;

}

Hàm tính căn nguyên bậc n của a

Nhận xét: Nếu số n đƣợc biểu diễn trong hệ d thì số chữ số của n là Int(logdn) (Int cho phần nguyên dƣ).

Thí dụ, để biểu diễn a = 1026 Trong hệ 10 ta cần int(log101026) = 4 chữ số ; n = 102610. Trong hệ 2 ta cần int(log21026) = 11 chữ số ; n = 100000000102. Trong hệ 4 ta cần int(log41026) = 6 chữ số ; n = 1000024... Cú pháp int LBitCount(Long n) Input: Số nguyên dƣơng p

Output: Số bit biểu diễn p. Thí dụ int v = LBitCount(7); // v = 3 v = LBitCount(1026); // v = 11 Thuật toán Nếu tìm đƣợc k thỏa 2k > n thì k là đáp số. Cài đặt

// So bit bieu dien n int LBitCounter(Long n){ Long b = 2; int sb = 1; while (b <= n) { ++sb; b <<= 1; } return sb; }

Nhận xét 2: Để tính số chữ số s cần cho biểu diễn a trong hệ d ta đếm số lần nhân liên tiếp d cho đến khi vƣợt quá a:

s = 1; v = d;

while (va) { ++s; v = v d; }

Định lí Newton: Cho hàm liên tục f(x) và (ta giả thiết thêm là f(x) = 0 tức là đồ thị của f cắt trục hoành). Biết f(x1) > 0. Khi đó với x2 = x1 – f(x1)/f‟(x1) ta có

f(x2) < f(x1).

Để tính căn bậc n của a ta làm nhƣ sau:

Xét hàm f(x) = xn – a. Nếu tìm đƣợc trị x để f(x) = 0 ta có ngay kết quả. Ta có f‟(x) = nxn-1 . Khi đó

y = xf(x) / f‟(x) = x – (xn – a) / nxn 1 = (nxn – xn + a) / nxn 1 = x(n 1) / n + a / nxn 1 = (x(n 1) + a / nxn 1) / n.

Mọi kết quả trung gian đều là nguyên. Chọn điểm xuất phát x;

Lặp

y = xf(x)f‟(x) ;

Nếu y x thì cho kết quả x ;nếu không đặt lại x = y ;

Ta chọn giá trị xuất phát cho x đủ nhỏ thì tốt. Ta chọn x là giá trị nhỏ nhất thỏa

Từ đây suy ra phải chọn x thỏa xn a.

Lấy log cơ số 2 ta có: nlog x log a, hay log x log a/n. Đặt b = log a /

n, ta có:

log x b. Từ đây suy ra x 2b.

log a = số chữ số của a trong hệ 2 = số bít cần thiết để biểu diễn a.  Nhận xét 3: x.2k = x << k ; x / 2k = x >> k; x mod 2k = x and (2k – 1). Cài đặt

// Newton Method

Long LRoot(Long a, Long n){ if (a == 0) return 0; if (a < 0 || n <= 0) {

cout << "\n Error: Inputs must be positive numbers !"; cin.get(); exit(1); } Long x, y; x = 1 << ((LBitCount(a)+n-1)/n); // cout << "\n a = " << a << " x = " << x; while (1){ y = (x*(n-1)+a/LExp(x,n-1))/n; if (y >= x) return x; x = y; } }

Hàm kiểm tra dạng lũy thừa (proper power) của số p.

Số nguyên p > 1 gọi là số dạng thừa tồn tại hai số nguyên i, b > 1 thỏa: ab = p. Từ hệ thức trên suy ra ( )b = p với mọi b.

Có cần với mọi b hay không? Không. Ta chỉ cần chọn b sao cho > 1 . Max b = (số chữ số của p)/2.

Cú pháp

Long ProperPower(Long p); Input: số nguyên p > 1.

Output: b > 1 nếu ( )b = p; noài ra: 0. Thí dụ Long b = ProperPower(12*12*12); // b = 3 Thuật toán Cài đặt Long ProperPower(Long p){ Long sb = (LBitCount(p)+1)/2, b; for (b = 2; b < sb; ++b){ if (LExp(LRoot(p,b),b) == p) return b;} return 0; }  Tính ax mod n

Thuật toán bình phƣơng và nhân là thuật toán tính nhanh lũy thừa tự nhiên của một số (thực hoặc nguyên), trong trƣờng hợp cơ số là số nguyên có thể đƣợc rút gọn theo một modulo nào đó.

Tạo bảng:

x a d =1 (Khởi tạo)

Điền giá trị x Điền giá trị a

… … …

Thí dụ: 1535 mod 79 x a d Khởi tạo d = 1 35 15 15 x lẻ  tính lại d, x, a trong if d = d (a mod n) = 1 (15 mod 79) = 15 x >>=1 = 35 div 2 = 17 a = (a a) mod n = (15 15) mod 79 = 67 17 67 57 x lẻ  tính lại d, x, a tƣơng tự nhƣ trên

8 65 x chẵn  không tính lại d

vẫn tính lại x, a nhƣ trên 4 38 x chẵn  tƣơng tự nhƣ trên 2 22 x chẵn  tƣơng tự nhƣ trên 1 10 17 x chẵn  tƣơng tự nhƣ trên

0 x = 0  dừng tính, lấy d cuối cùng (d = 17) là kết quả Cài đặt: Input: a, x, n Output: ax mod n Algorithm: PowMod(a,x, n) d =1; While(x <> 0){

if(x mod 2 <> 0) d: = d * (a mod n); x >>=1;

a = (a*a) mod n; }

return d;

 Tìm phần từ nghịch đảo theo modulo p.

Số y là số nghịch đảo của x theo modulo p nếu x y mod p = 1 và 1 y < p.

Nếu y là số nghịch đảo của x theo modulo n thì ngƣợc lại, x là số nghịch đảo của y theo modulo n.

Cú pháp: Inv(Bignum a, BigNum p)

Input: Hai đối tƣợng số nguyên lớn a, p thoả (a, p) = 1

Output: x là số nghịch đảo của a theo modulo p, a x mod p = 1 Thí dụ: x = Inv(3,10) // x = 7 vì 3 7 mod 10 = 21 mod 10 = 1

x = Inv(4, 7); // x = 2 vì 4 2 mod 7 = 8 mod 7 = 1 Thuật toán:

Theo thuật toán Euclid với hai số ap tùy ý ta luôn tìm đƣợc hai số x

y thỏa:

ax + py = (a,p)

Vì (a,p) = 1 nên ax + ny = 1. Từ đây suy ra ax = 1 py và do đó ax mod p = 1 Cài đặt:

BigNum Inv(BigNum a, BigNum p) { BigNum x = Euclid(a,p);

return (x > 0) ? x: x+p; }

Thuật toán Euclid đầy đủ nhƣ sau:

// Cho a, b. Tim x, y thoa ax+by = (a,b)

void Euclid(BigNum a, BigNum b, BigNum &x, BigNum &y) { BigNum u, v, t, q, r; x = 0; y = 1; u = 1; v = 0; q = a/b; r = a - q*b; while (r > 0) { a = b; b = r; t = u; u = x; x = t - q*x;

t = v; v = y; y = t - q*y; q = a / b; r = a - q*b; }

}

Vì chỉ cần quan tâm số nghịch đảo, tức là chỉ cần tính x ta có thể bỏ qua y

và viết thuật toán gọn nhƣ sau:

// Cho a, p. Tim x thoa ax mod p = 1

Algorithm:Inv(Bignum a, BigNum p)

BigNum Inv(BigNum a, BigNum p) {

BigNum x = 0, u, t, q, r, n = p; u = 1; q = a/p; r = a - q p; while (r > 0) { a = p; p = r; t = u; u = x; x = t - q*x; q = a / p; r = a - q*p; } return (x > 0) ? x: x+n; }

Một phần của tài liệu Số học số lớn cho mật mã luận án thạc sĩ (Trang 60 - 70)