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 sẽ trình bày hai thao tác liên quan đến bảo mật dữ liệu là mã hóa và giải mã. 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ã 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á
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)
Hiển thị thông báo xác nhận đã xử lý thành công
Câu 2: Mã hoá dữ liệu
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.
Dữ liệu sau khi mã hóa thành công
Câu 3: Giải mã dữ liệu
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
Dữ liệu sau khi giải mã