Vấn đề bảo mật trong gói JAVA.SECURITY

Trong hơn 50 năm qua, các nhà toán học, tin học đã phát triển nhiều thuật toán rất tinh tế đảm bảo tính toàn vẹn của dữ liệu và chữ ký điện từ. Gói java.security đã cài đặt khá nhiều trong số các thuật toán đó. Rất may là ta không cần phải hiểu tường tận cơ sớ toán học mà vẫn có thể sù dụng được chủng. Sau đây chúng ta tìm hiểu cách để phát hiện ra những sự thay đổi trong các tệp dữ liệu và cách xác thực chữ ký số.

1. Dấu vết thông điệp

Tóm tắt đặc trưng của thông điệp là một dạng dấu vết tóm tắt của một khối dữ liệu, một thông điệp, gọi tắt là bản dấu vết thông điệp (message digest). Mỗi bản dấu vết thông điệp sẽ có hai đặc tính:

  1. Khi bản lưu trữ dữ liệu có một hay một số bit bị thay đổi thì bản tóm tắt dấu vêt cũng sẽ bị thay đổi,
  2. Rất khó (hầu như không thể) kiến thiết được một thông điệp mới (một vãn bản) có cùng một bản tóm tắt dấu vết như bản gốc.

Đặc tính thứ hai có thể thực hiện được một cách ngẫu nhiên, nhưng với một xác suất rất thấp.

Hiện nay có một số thuật toán nén dữ liệu để tạo ra bản dấu vết thông điệp. Hai thuật toán nổi tiếng nhất là SHA-1 (do National Insstitute of Standard and Tectnology đề xuất) nén . một một khối dữ liệu bắt kỳ thành dãy 160 bít (20 byte) và MD5 (cùa Ronald Rivest ờ MIT) 12]. ‘

Java cài đặt cả hai thuật toán trên. Lớp MessageDigest được xem như một cái máy sản xuất ra các đối tượng thực hiện các thuật toán xừ lý các tóm tắt dấu vết. Ví dụ, để nhận được đối tượng thực hiện thuật toán SHÄ.-1, ta viết

MessageDigest alg = MessageDigest.getlnstance(“SHA-1”),

Sau đó truyền các byte cùa một thông điệp cho đối tượng alg để nó tạo ra bản tóm tắt dấu vết. Ví dụ, muốn tạo ra bản tóm tắt dấu vết cho tệp có tên là fileHsme, ta thực hiện như sau.

Filelnputstream ìn = new Filelnputstream(fileName); int ch;

while((ch = in.readO != -1) alg.update( (byte)ch);

 

java. security. MessagDigest      

  • static MessageDigest getlnstance(String alg)

Cho lại đối tượng củaMessageDigest cài đặt thuật toán alg.

  • void update(byte input)
  • void update(byte[] input)
  • void update(byte[] input, int offset, int len)

Cập nhật lại bản dấu vết đối với các byte đầu vào.

  • void reset ( ) : Tính lại bản dấu vết.

2. Chữ ký số

Trong phần trước ta đã tìm hiểu cách sinh ra bản tóm tắt dấu vết cho một thông điệp. Khi một thông điệp bị thay đổi thì bản tóm tắt dấu vết được sinh ra sẽ không tương thích với bản gốc, do vậy dễ dàng phát hiện ra là nó đã bị thay đổi. Nếu ta gửi đi một bản tin và bản tóm tắt dấu vết của nó một cách riêng biệt, người nhận có thể sử dụng bản dấu vết đó để kiểm tra xem bản tin minh nhận có phái là bản gốc hay không. Nhưng nếu những kẻ gian, bằng một cách nào đó có được cả bản tin và bản dấu vết, họ có thể dễ dàng sửa đổi bản tin, tính lại bản dấu vết tương ứng. Điều này hoàn toàn thực hiện được bởi vì các thuật toán tính bản dấu vết là công khai, hoàn toàn không có gì bí mật cả. Trong trường hợp này, người nhận bản tin đã bị sửa và khi tính bản dấu vết (cũng bị sửa theo) có thể sẽ không phát hiện dược là bản tin đó đã bị sữa.

Để chống lại nhũng sự tấn công nêu trên, ta có thể sử dụng thêm một số phương pháp bảo mật, xác thực khác, ví dụ sứ dụng chữ ký số.

Trước tiên ta cần tìm hiểu về việc xác thực được thục hiện như thể nào. Khi một thông điệp được xác thực, nghĩa là

  • Thông điệp đó không bị thay đổi
  • Thông diệp này là đúng của người gửi.

Nếu như cả bên gửi và bên nhận không có sự không thống nhất nào về xuất xứ cũng như nội dung của thông điệp, thì việc trao đổi như vậy được xác nhận là hoàn tất. Cả hai bên đều tin rằng, không có một người thứ ba can thiệp vào quá trình trao đổi tin này.

Tuy nhiên, có những đoạn tin gian lận xuất phát từ bên gửi hoặc do bên nhận tự tạo ra trong các giao dich thương mại, thanh toán, trao dổi trên mạng, v.v. Các tranh chấp có thể xảy ra và cũng có nhiều trường hợp người bị lừa khó mà nhận biết được, nếu không có biện pháp phòng ngừa và phát hiện hữu hiệu. Ngay cả khi dùng mật mã khóa bí mật mà cả hai bên gửi và nhận đều biết, người gửi có thể tự tạo thêm một mã để kiểm tra xem thông điệp nhận được có xác thực hay không.

Trong thực tế, các hoạt động thương mại, quản lý hành chính, hoạt động nghiệp vụ, các tài liệu trên giấy có giá trị cam kết giao hẹn với nhau (như ngân phiếu, hợp đồng) thì bên gửi là bên có khả năng làm giả nhiều nhất, Ngược lại, cũng có khi một số trường hợp phía bên nhận lại chối bỏ trách nhiệm cùa mình vì thấy những điều đó bất lợi cho mình. Trong các trường hợp đó, việc xác thực thường được dựa vào chữ ký cùa hai bên để xác nhận các điều khoản đã cam kết, giao kèo với nhau trên “giấy trắng mực đen”, và đó cũng là cơ sở pháp lý đồ giải quyết khi có tranh chấp.

Nhưng nếu các hoạt đông trên thực hiện trao đổi với nhau trên mạng truyền số liệu thì vấn đề phức tạp hơn nhiều. Ví dụ, nếu bên B mang đến Tòa án một tài liệu nhận được qua mạng truyền số liệu (Internet) và bên A lại chối bỏ trách nhiệm gửi của mình thi Tòa án cũng rất khó phàn xử rạch ròi. Bởi vì cũng có khả năng bên B làm giả đoạn tin và cũng có khi bên A có gửi thật nhưng lại chối bỏ trách nhiệm.

Vấn đề đặt ra là làm thế nào để phân xừ được trong những trường hợp như trên. Muốn giài quyết được vẩn đề xác thực thì cần phải cỏ một cơ chế nào đó giống như chữ ký tay để cả hai bên gửi và nhận cùng kiểm tra và không thể tạo giả mạo chữ ký đó. Một trong các biện pháp để thực hiện xác thực là sử dụng chữ ký số.

Để hiểu rõ về chữ ký số, ta cần nói rõ hơn về một số khái niệm liên quan đến mật mã khóa công khai. Mật mã khóa công khai dựa trên hai khái niệm: khóa công khai và khóa riêng. Khóa công khai thì có thể công bố cho mọi nguời biết. Khóa riêng thì chi người giữ nó được biết và điều quan trọng là không để người khác biết. Hai khóa này có mối quan hệ với nhau theo các quan hệ toán học, nhưng có thể tin rằng, thực tế không thể từ một khóa này tìm ra được khóa kia. Mặc dù đã biết khóa công khai, nhưng cả đời người cũng không tìm ra được khóa riêng, cho dù ta có dùng bao nhiêu máy tính, với loại máy tính nào đi nữa cũng không thực hiện được [2], Điều này có thể khó tin, song cho đến hiện nay chưa ai tìm được thuật toán để tính được khóa riêng từ khóa công khai trong thời gian chấp nhận được.

Đã có khá nhiều thuật toán được sử dụng để mã hoả và giải mã thông tin. Trong số đó thuật toán được nói tới nhiều là thuật toán RSA của Ri vest, Shamir và Adleman. Thuật toán này được xây dựng dựa ưên độ khó của việc phân tích các số lớn thành các thừa số, nhất là các thừa số nguyên tố. Phần lớn các nhà mật mã tin rằng những khóa với “Modulus” của số gồm 2000 bít hoặc lớn hon thl hoàn toàn yên tâm đối với mọi sự tấn công từ bên ngoài.

Có hai cặp khóa công khai và khóa riêng được sử dụng để mã hoá và chứng thực. Nểu một người gửi cho bạn một bân tin được mã hoá bằng khóa công khai thì bạn có thể giải mã bằng khóa riêng để đọc bản tin đó mà những người khác không làm được. Ngược lại, bạn có thể “ký” (đánh dấu) vào một bản tin bằng khóa chứng thực riêng, sau đó người nhận có thể kiểm tra tính xác thực của chữ ký bằng khóa công khai mà bạn cung cấp. Việc kiểm chứng này chì cần thực hiện được đối với những bản tin đã được đánh dấu (được ký) và nó sẽ thất bại nếu ai đó sử dụng khóa của họ để đánh dấu vào bản tin đó, nghĩa là làm thay đổi bản tin đã được kỷ.

Ta hãy tìm hiểu cách hoạt động của thuật toán DSAđể sinh ra cặp khóa công khai/riêng và cách sử dụng chúng như thế nào.

Giả sử rằng Nam muốn gửi cho Hoa một bản tin và Hoa muốn biết xem bản tin này có phải đúng do Nam gửi hay không. Nam viết bản tin rồi đánh dẩu (tạo ra bản dấu vết) bằng khóa riêng của mình. Hoa nhận được bàn copy cùa khóa công khai và sử dụng nó để kiểm tra tính xác thục cùa bản tin. Nếu việc kiểm chứng này thành công thì Hoa tin rằng.

  1. Bản tin gốc không bị thay đổi.
  2. Bản tin được ký bởi Nam.

Một chữ ký số cần phải phụ thuộc vào tất cả các bít của đoạn tin với mục đích là giữ sự bền vững của đoạn tin đó. Điều quan trọng ờ đây là, phài đảm bảo không một ai có thể làm thay đồi nội dung cùa bản tin rõ trong lúc phải giữ nguyên chữ ký số.

Quá trinh trao đổi và xác thực theo thuật toán DSA được mô tả như sau:

Tuy nhiên, về mặt lý thuyết sẽ không cỏ một giải pháp nào là tuyệt đối an toàn. Do vậy, chữ ký số cũng không phải là giải pháp toàn năng để chống lại sự già mạo và có thể phân xử được mọi tranh chấp, cho nên cần có cơ chế trọng tài. Chữ ký số có thể kết hợp với mật mã để tăng tính hiệu quả của vấn đề xác thực.

Gói bảo mật của Java đã cài đặt hai thuật toán DSA, SHA.-1 nêu trên. Nếu bạn muốn sử dụng RSA thì phải mua các lớp củ a RSA  www.rsa.coml.

Phần tiếp theo chúng ta tập trung khai thác DSA Có ba thuật toán được sử dụng.

  1. Thuật toán sinh ra cặp khóa
  2. Thuật toán ký (đánh dấu) thông điệp
  3. Thuật toán xác thực chữ ký.

 

  1. Tạo ra cặp khóa

Để sinh ra những cặp khóa một cách hoàn toàn ngẫu nhiên, người ta thường sử dụng bộ sinh số ngẫu nhiên cùa lóp SecureRandom. Lóp này phát sinh các số ngẫu nhiên hơn (đảm bảo an ninh hơn) các số sinh bời Random Ví dụ,

SecureRandom secrand = new SecureRandom () ;

byte[] b = new byte[20];

secrand. setSeed (b) ;

// Điền các bít một cách ngẫu nhiên

Trong Java, để tính một cặp khóa theo thuật toán DSA mới, ta sử dụng lớp KeyPairGenerator như sau:

KeyPairGenerator keygen = KeyPairGenerator.getInstance (“DSA”) ;

Nếu muốn sinh ra một khóa theo modulus của 5 12 bit thi hãy viết  keygen.initialize(512, secrand);

Sừ dụng tiếp các lóp KeỵPair, PublìcKey, PrivateKey để sinh ra cặp khóa công khai và khóa riêng.

KeyPair keys = keygen.generateKeyPair();

PublìcKey pubKey = keys.getPublic();

PrivateKey privKey = keys.getPrivate();

  1. Đánh dấu (ký xác nhận) thông điệp

Muốn đánh dấu (ký xác nhận) một thông điệp (đoạn tin), ta phải tạo ra đối tượng của lớp Signature

Signature sigalg = signature.getinstance(“DSA”);

Đối tương này dược sử dụng cho cà việc ký xác nhận lẫn việc xác thực thông điệp. Trước khi ký chứng thực, ta sử dụng phương thức initSign() và truyền khóa riêng cho nó.

sigalg.initsign(privKey);

Tiếp theo, sử dụng phương thức updated để dưa các byte của thông điệp (đọc theo từng byte) vào đối tượng đánh dấu.

while((ch – ìn.reado != -1)

sigalg.update((byte)ch);

Cuối cùng là chữ ký số. byte [ ] signature = sigalg. sign ();

  1. Xác thực chữ ký

Người nhận được thông điệp cũng sẽ nhận dược khóa công khai và cần phải kiểm tra xem tài liệu nhận được có đúng bản gốc của người gửi hay không.

Signature verifyAlg = Signature.getlnstance(“DSA”); verifyAlg.initVerify(pubKey);

while((ch = in.read()) != -1) //Truyền thông điệp vào đối tượng xác thực

verifyAlg.update((byte)ch); boolean check = verifyAlg. verify (signature); // Xác thực chữ ký

Neu check là true thì chữ ký là xác thưc, thông đíêp nhân là đoạn tin dã dược ký nhận hời một khóa riêng tương ứng. Nghĩa !à, cả người gửi và nôi dung thông điệp được xác thực.