ECN>> RSA>> 返回
项目作者: tanhtm

项目描述 :
RSA
高级语言: Python
项目地址: git://github.com/tanhtm/RSA.git
创建时间: 2018-10-31T05:34:44Z
项目社区:https://github.com/tanhtm/RSA

开源协议:

下载


Bài tập lớn - Số học thuật toán

Mã hóa RSA

1. Giới thiệu chung

  • Tác giả:
    • Sinh viên: Nguyễn Tú Anh
    • MSV: A29888
    • Trường: Đại học Thăng Long
  • Môn học và đề tài:
    • Môn học: Số học thuật toán
    • Giảng viên: GS. Hà Huy Khoái
    • Chủ đề: Mã hóa RSA
    • Ngôn ngữ lập trình: Python
    • Tài nguyên sử dụng: Tính toán trên số lớn có sẵn của python
    • Nội dung chính: Mã hóa văn bản (Tiếng Việt có dấu) với RSA và khóa tự sinh (1024 bits)

2. Giới thiệu chung cấu trúc bài tâp lớn

  • MyMath.py: Chứa hàm toán học

    • powMod(a, b, m): Trả về kết quả phép tính a^b mod m
    • GCD(a, b):Trả về UCLN(a, b)
    • GCD_extended(a, b): Trả về 3 số x,y,z thỏa mãn xa + yb = z = UCLN(a, b)
  • PrimeTest.py: Chứa hàm kiểm tra tính nguyên tố

    • Preprocessor(a): Kiểm tra loại bỏ các số chia hết cho 1000 số nguyên tố đầu tiên (Tiền xử lý)
    • Fermat(p,x): Kiểm tra số p sử dụng định lý Fermat nhỏ với x cơ sở
    • Miller_Rabin(p, x): Kiểm tra Miller- Rabin với x cơ sở
  • GenePrime.py: Chương trình sinh nguyên tố xác suất

    • Random (b): Hàm trả về số lẻ ngẫu nhiên b bits
    • getPrime(b): Hàm trả về số nguyên tố xác suất b bits
    • main(b): Hàm chạy chương trình sinh 2 số nguyên tố xác suất b bits
  • CreateKey.py: Tạo khóa cho mã hóa RSA

    • getPQ(file): Lấy 2 số nguyên tố xác suất p q từ file
    • getE(phi): Sinh số e là số nguyên tố cùng nhau với phi = (p-1)(q-1)
    • getD(e, phi): Lấy số d là số nghich đảo mudulo của phi của e
    • main(): Hàm chạy chương trình sinh khóa công khai(n,e) và khóa bí mật (n, d)
  • MyBase.py: Đổi cơ số

    • toBase(a, base): Đổi từ số a cơ 10 sang cơ base
    • toInt(r, base): Đổi từ số r cơ base sang cơ 10
  • encode.py: Chương trình mã hóa văn bản

    • getPublicKey (file): Hàm lấy khóa công khai (n,e) từ file
    • getPlaintext (file): Hàm lấy bản P rõ từ file
    • convertStringToInt(P, base): Chuyển đổi các ký tự trong P thành số theo mã UTF- 8
    • createBigInt(R, size_n): Ghép các số trong R với nhau thành 1 số có số các chữ số nhỏ hơn size_n
    • encode(n, e, P, file): Mã hóa bản rõ P với khóa (n, e) lưu vào file với cơ 64
    • main(): Hàm chạy chương trình mã hóa
  • decode.py: Chương trình giải mã văn bản

    • getPrivateKey (file): Lấy khóa mật (n,d) từ file
    • getCiphertext(file): Lấy văn bản mã hóa từ file
    • decode(n, d, C, base, fileOut): Giải mã bản mã C xuất ra bản rõ vào fileOut
    • main(): Chạy chương trình

3. MyMath - Hàm toán học

  • powMod(a, b, m)

    • Ý nghĩa: Trả về kết quả phép tính a^b mod m
    • Kiến thức: Bình phương liên tiếp
    • Code:

      1. def powMod(a, b, m):
      2. x = []
      3. while b != 0:
      4. x.append(b & 1)
      5. b = b >> 1
      6. sz = len(x)
      7. po = [a%m]
      8. for i in range(1,sz):
      9. p = (po[i-1]*po[i-1])%m
      10. po.append(p)
      11. r = 1
      12. for i in range(sz):
      13. if(x[i] != 0):
      14. r*= po[i]
      15. r%= m
      16. return r
  • GCD(a, b)
    • Ý nghĩa: Trả về UCLN(a, b)
    • Kiến thức: UCLN(a, b)= UCLN(b, a% b), Giải thuật Euclid
    • Code:
      1. def GCD(a, b):
      2. if b == 0:
      3. return a
      4. return GCD(b, a%b)
  • GCD_extended(a, b)
    • Ý nghĩa: Trả về 3 số x,y,z thỏa mãn x*a + y*b = z = UCLN(a, b)
    • Kiến thức: Giải thuật Euclid mở rộng
    • Code:
      1. def GCD_extended(a, b):
      2. u1, u2, u3 = 1, 0, a
      3. v1, v2, v3 = 0, 1, b
      4. while v3 != 0:
      5. q = u3//v3
      6. t1, t2, t3 = u1 - q*v1, u2 - q*v2, u3 - q*v3
      7. u1, u2, u3 = v1, v2, v3
      8. v1, v2, v3 = t1, t2, t3
      9. return u1, u2, u3

4. PrimeTest - Các hàm kiểm tra tính nguyên tố

  • Fermat(p,x):
    • Ý nghĩa: Kiểm tra số p sử dụng định lý Fermat nhỏ với x cơ sở.
    • Kiến thức:
      • Định lý Fermat nhỏ: a^(p-1) ≡ 1(mod p) (p: số nguyên tố và a không chia hết cho p)
      • Số giả nguyên tố cơ sở
    • Code:
      1. def Fermat(p,x):
      2. for i in range(x):
      3. a = sprime[i]
      4. if MyMath.powMod(a,p-1,p) != 1:
      5. return False
      6. return True
  • Miller_Rabin(p, x):

    • Ý nghĩa: Kiểm tra Miller- Rabin với x cơ sở
    • Kiến thức: n là số nguyên dương lẻ, n-1 =2^s*m, n trải qua Miller cơ sở b nếu b^t ≡ 1 mod n hoặc b^((2^j)t) ≡ -1 mod n với j nào đó 0 ≤ j ≤ s-1
    • Code:
    1. # Q(a,p,m,s) = 1 nếu p trải qua Miller-Rabin cơ sở a
    2. def Q(a, p, m, s):
    3. x = MyMath.powMod(a,m,p)
    4. if x == 1:
    5. return True
    6. for i in range(0,s+1):
    7. if x == p - 1:
    8. return True
    9. x *= x
    10. x %= p
    11. return False
    12. def Miller_Rabin(p, x):
    13. # x : the number of bases
    14. # p - 1 = m*2^s (m is odd)
    15. n = p - 1
    16. s = 0
    17. while n & 1 == 0:
    18. n = n >> 1
    19. s+= 1
    20. m = n
    21. for i in range(x):
    22. a = sprime[i]
    23. if Q(a,p,m,s) == False:
    24. return False
    25. return True

5. Mã hóa RSA

  • Tạo khóa
    • Lấy 2 số p,q
    • Gắn n = p*q, φ(n) = (p-1)(q-1)
    • Lấy e sao cho (e, φ(n)) = 1
    • Gắn d là nghịch đảo modulo phi của e, xử dụng GCD_extended
      1. def getD(e, phi):
      2. d = MyMath.GCD_extended(e,phi)[0] #[x,y,z] #d = x
      3. if d < 0:
      4. d+= phi
      5. return d
    • In kết quả ra file
  • Mã hóa
    • Lấy khóa công khai (n, e)
    • Lấy bản rõ P
    • Chuyển các kí tự trong P về số theo bản mã UTF-8 tạo thành mảng các số R
    • Ghép các số trong R thành số lớn nhỏ hơn n thành số Pi rồi mã hóa nó thành Ci với công thức: Ci ≡ Pi^e mod n
      1. def encode(n, e, P, file):
      2. fo = open(file,"w")
      3. C = ""
      4. R = convertStringToInt(P, 4)
      5. A = createBigInt(R, len(str(n)))
      6. for i in A:
      7. M = MyMath.powMod(i,e,n)
      8. M = MyBase.toBase(M,64)
      9. C+= M + ' '
      10. fo.write(M+' ')
      11. fo.close()
      12. return C
    • In mảng số mới ra file với cơ số 64
  • Giải mã

    • Lấy khóa bảo mật (n, d)
    • Lấy bản mã C trong file chuyển về cơ số 10
    • Lấy từ số trong C là Ci giải mã được Pi với công thức: Pi ≡ Ci^d mod n
    • Lấy kết quả tách số rồi chuyển về dạng kí tự
    • In kết quả ra file
      1. def decode(n, d, C, base, fileOut): # file PlanintextDecode
      2. fo = open(fileOut,"w")
      3. P = ""
      4. for i in C:
      5. m = MyMath.powMod(MyBase.toInt(i,64),d,n)
      6. c = str(m)
      7. while len(c) % base != 0:
      8. c = '0' + c
      9. x = 0
      10. while x != len(c):
      11. a = c[x:x+base]
      12. x+= base
      13. P+= chr(int(a))
      14. fo.write(chr(int(a)))
      15. fo.close()
      16. return P
  • Kiến thức

    • Tính nghịch đảo modulo bằng giải thuật Euclid mở rộng
    • Định lý Euler: a^φ(n) ≡ 1 mod n với (a,n) = 1