Mã hóa và giải mã dữ liệu trong Java (Bài 9)

Mã hóa và giải mã dữ liệu trong java. Mã hoá là thao tác chuyển đổi văn bản hoặc dữ liệu ban đầu thành một hình thức mã hóa hay các bản mã bằng cách áp dụng các biến đổi toán học. Ngược lại với thao tác này là giải mã. Giải mã truy xuất dữ liệu gốc từ các bản mã sử dụng một khóa giải mã. Và việc mã hoá dữ liệu nhằm nâng cao khả năng bảo mật, xác thực và tính toàn vẹn của thông tin được truyền trên các phương tiện truyền thông.

Mã hóa và giải mã dữ liệu trong java – Cách thức hoạt động

Giả sử B muốn gửi thông điệp m sang cho A. B sẽ dùng khoá công khai (public key) mà A cung cấp để mã hoá dữ liệu và gửi. Khi nhận A được thông điệp từ B, A sẽ dùng khoá riêng (private key) của mình để giải mã và đọc. Trong tình huống này, A sẽ phải tạo ra cặp khoá gồm Public key và Private key.

mã hoá và giải mã dữ liệu trong java

Mã hóa và giải mã dữ liệu trong java – Các thuật toán mã hoá

Có nhiều thuật toán mã hóa được phổ biến rộng rãi và được sử dụng trong an ninh thông tin. Chúng được phân loại gồm mã hoá khoá đối xứng và mã hoá khoá không đối xứng. Trong mã hóa khóa đối xứng chỉ có một khoá (key) được sử dụng để mã hóa và giải mã dữ liệu. Trong mã hoá khóa bất đối xứng sử dụng hai khoá là khóa riêng và khoá công khai. Trong đó khóa công khai được sử dụng để mã hóa và khóa riêng được sử dụng để giải mã. Bảng bên dưới trình bày các thuật toán mã hoá.

AES DES RSA
Developed 2000 1977 1978
Key Size 128, 192, 256 bits 56 bits >1024 bits
Algorithm Đối xứng (Symmetric) Đối xứng (Symmetric) Bất đối xứng (Asymmetric)

Mã hóa và giải mã dữ liệu trong java – Thuật toán mã hoá bất đối xứng

Người nhận (Receiver): Tạo cặp khoá

SecureRandom sr = new SecureRandom();
// Thuật toán phát sinh khóa - Rivest Shamir Adleman (RSA)
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048, sr);

// Phát sinh cặp khóa
KeyPair kp = kpg.genKeyPair();

// PublicKey
PublicKey pubKey = kp.getPublic();
// PrivateKey
PrivateKey priKey = kp.getPrivate();

// Lưu public key và private key vào tập tin
// ...

Người gửi (Sender): Mã hoá dữ liệu

// Đọc file chứa public key
FileInputStream fis = new FileInputStream("fileName");
byte[] b = new byte[fis.available()];
fis.read(b);
fis.close();

// Tạo public key
X509EncodedKeySpec spec = new X509EncodedKeySpec(b);
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pubKey = factory.generatePublic(spec);

// Sử dụng public key để mã hoá dữ liệu 
Cipher c = Cipher.getInstance("RSA");
c.init(Cipher.ENCRYPT_MODE, pubKey);
byte encryptOut[] = c.doFinal("Dữ liệu cần mã hoá");

//strEncrypt chứa dữ liệu sau khi mã hoá
String strEncrypt = Base64.encode(encryptOut);

Người nhận (Reveiver): Giải mã dữ liệu nhận được

// Đọc file chứa private key
FileInputStream fis = new FileInputStream("fileName");
byte[] b = new byte[fis.available()];
fis.read(b);
fis.close();

// Tạo private key
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b);
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey priKey = factory.generatePrivate(spec);

// Giải mã dữ liệu 
Cipher c = Cipher.getInstance("RSA");
c.init(Cipher.DECRYPT_MODE, priKey);

// decryptOut chứa dữ liệu sau khi giải mã
byte decryptOut[] = c.doFinal(Base64.decode(txtMessage.getText()));

Mã hóa và giải mã dữ liệu trong java – Chương trình mẫu

Tạo cặp khoá

package swing_pkg.basic.cryptography_signature.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;

/**
 *
 * @author giasutinhoc.vn
 */
public class KeyPairGenerate {

 public static void main(String[] args) {
  try {
   SecureRandom sr = new SecureRandom();
   //Thuật toán phát sinh khóa - Rivest Shamir Adleman (RSA)
   KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
   kpg.initialize(2048, sr);
 
   //Phát sinh cặp khóa
   KeyPair kp = kpg.genKeyPair();
   //PublicKey
   PublicKey pubKey = kp.getPublic();
   //PrivateKey
   PrivateKey priKey = kp.getPrivate();

   //Lưu Public Key
   FileOutputStream fos = new FileOutputStream("D:/file/pubKey.bin");
   fos.write(pubKey.getEncoded());
   fos.close();

   //Lưu Private Key
   fos = new FileOutputStream("D:/file/priKey.bin");
   fos.write(priKey.getEncoded());
   fos.close();

   System.out.println("Generate key successfully");
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

Mã hoá dữ liệu

package swing_pkg.basic.cryptography_signature.demo;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;

/**
 *
 * @author giasutinhoc.vn
 */
public class Encrpytion {

 public static void main(String[] args) {
  try {
   // Đọc file chứa public key
   FileInputStream fis = new FileInputStream("D:/file/pubKey.bin");
   byte[] b = new byte[fis.available()];
   fis.read(b);
   fis.close();
 
   // Tạo public key
   X509EncodedKeySpec spec = new X509EncodedKeySpec(b);
   KeyFactory factory = KeyFactory.getInstance("RSA");
   PublicKey pubKey = factory.generatePublic(spec);

   // Mã hoá dữ liệu
   Cipher c = Cipher.getInstance("RSA");
   c.init(Cipher.ENCRYPT_MODE, pubKey);
   String msg = "giasutinhoc.vn";
   byte encryptOut[] = c.doFinal(msg.getBytes());
   String strEncrypt = Base64.encode(encryptOut);
   System.out.println("Chuỗi sau khi mã hoá: " + strEncrypt);
 
  } catch (Exception ex) {
    ex.printStackTrace();
  }
 }
}

Chuỗi sau khi mã hoá

SIpP0Bnu/XSCOpOvsJWLcWOHzFQ8jipidewfghbPl0WoJC/i5OWJbzk5IfdqR3x8tRJ9a2tY7zuAFgdti0BGivxWpuHeSrRO9hDPakwTw1+7OYizDJDb0UCAEViEhJCB09FhZkNnxtTpG+o4UaSeSVG/5KGCA7oIIsG0/tYpdCqv8do6KdGODHDjmKMhTbmjcsA2ksK93gQVVkIi/QkSgUxbV12GtXRpxS9zKpImNxH6otUT08K4UYPIGigU/0T8JBxHiDdb0R0uphKGei8+UJ++pDwtcNkv9yurkNcLL7oHzv16yL7bJV0zK5uBm6+tmbpU4pMLrqlYcrxwnMBZEw==

Giải mã dữ liệu

package swing_pkg.basic.cryptography_signature.demo;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.Cipher;

/**
 *
 * @author giasutinhoc.vn
 */
public class Decryption {

 public static void main(String[] args) {
  try {
   // Đọc file chứa private key
   FileInputStream fis = new FileInputStream("D:/file/priKey.bin");
   byte[] b = new byte[fis.available()];
   fis.read(b);
   fis.close();
 
   // Tạo private key
   PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b);
   KeyFactory factory = KeyFactory.getInstance("RSA");
   PrivateKey priKey = factory.generatePrivate(spec);

   // Giải mã dữ liệu
   Cipher c = Cipher.getInstance("RSA");
   c.init(Cipher.DECRYPT_MODE, priKey);
   byte decryptOut[] = c.doFinal(Base64.decode("SIpP0Bnu/XSCOpOvsJWLcWOHzFQ8jipidewfghbPl0WoJC/i5OWJbzk5IfdqR3x8tRJ9a2tY7zuAFgdti0BGivxWpuHeSrRO9hDPakwTw1+7OYizDJDb0UCAEViEhJCB09FhZkNnxtTpG+o4UaSeSVG/5KGCA7oIIsG0/tYpdCqv8do6KdGODHDjmKMhTbmjcsA2ksK93gQVVkIi/QkSgUxbV12GtXRpxS9zKpImNxH6otUT08K4UYPIGigU/0T8JBxHiDdb0R0uphKGei8+UJ++pDwtcNkv9yurkNcLL7oHzv16yL7bJV0zK5uBm6+tmbpU4pMLrqlYcrxwnMBZEw=="));
   System.out.println("Dữ liệu sau khi giải mã: " + new String(decryptOut));
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }
}

Dữ liệu sau khi giải mã

giasutinhoc.vn

Mã hóa và giải mã dữ liệu trong java – Bài tập thực hành

Câu 1: Tạo cặp khoá

mã hoá và giải mã dữ liệu trong java

Khi người dùng chọn nút lệnh “Generate Key”, chương trình sẽ tạo cặp khóa Public Key và Private Key được dùng để mã hóa và giải mã dữ liệu. Sau khi tạo xong cặp khóa ,chương trình sẽ hiển thị hộp thoại cho phép người dùng lựa chọn thư mục lưu cặp khoá. Lưu ý thứ tự lưu: Public key lưu trước, Private key lưu sau (Thứ tự này do lập trình qui định, không có ý nghĩa về mặt mã hóa)

mã hoá và giải mã dữ liệu trong java

Hiển thị thông báo xác nhận đã xử lý thành công

mã hoá và giải mã dữ liệu trong java

Câu 2: Mã hoá dữ liệu

mã hoá và giải mã dữ liệu trong java

Sau khi người dùng nhập nội dung cần mã hóa tại Message và nhấn nút “Send”, chương trình sẽ yêu cầu cung cấp Public key để mã hóa dữ liệu.

mã hoá và giải mã dữ liệu trong java

Dữ liệu sau khi mã hóa thành công

mã hoá và giải mã dữ liệu trong java

Câu 3: Giải mã dữ liệu

mã hoá và giải mã dữ liệu trong java

Nhập thông tin cần mã hóa, sau đó chọn nút  “Decrypt”, chương trình sẽ yêu cầu cung cấp Private key được dùng để giải mã dữ liệu

mã hoá và giải mã dữ liệu trong java

Dữ liệu sau khi giải mã

mã hoá và giải mã dữ liệu trong java