Công nghệ mã hóa
Mã hóa và giải mã dữ liệu là kỹ thuật nhằm bảo mật dữ liệu, xác thực và đảm bảo 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 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ã.
Khi nói đến mã hóa, chúng ta dễ liên tưởng đến những bộ phim trình chiếu những đoạn mã số dài chạy nhấp nháy trên màn hình với những thông điệp khó hiểu. Hay cuộc chiến giữa Apple và FBI về vụ thông tin bị mã hóa mà chính phủ Mỹ buộc Apple phải giải mã thông tin trên chiếc iPhone của thủ phạm trong vụ xả súng ở San Bernardino, Mỹ. Nói đơn giản, mã hóa là một kỹ thuật làm cho nội dung không thể đọc được đối với bất kỳ ai không có chìa khóa. Ta có nghe thấy những thông tin như gián điệp sử dụng mã hóa để gửi thông tin bí mật, các tướng chỉ huy quân đội gửi nội dung mã hóa để phối hợp chiến đấu cho đồng bộ, còn tội phạm sử dụng mã hóa để trao đổi thông tin và lên kế hoạch hành động, tin nhắn của người dùng được mã hóa để kể cả quản trị tối cao của hệ thống cũng không đọc được…
Các hệ thống mã hóa cũng xuất hiện trong hầu hết mọi lĩnh vực liên quan đến công nghệ, không chỉ che dấu thông tin của tội phạm, kẻ thù hay gián điệp mà còn xác thực và làm rõ những thông tin rất cơ bản, rất cá nhân.
Mã hóa và giải mã dữ liệu trong java – Các thuật toán mã hoá cơ bản
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á phổ biến.
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) |
Tuy nhiên trong bài này mình sẽ sử dụng RSA để mô tả
Mã hóa và giải mã dữ liệu trong java(RSA) – Cách thức hoạt động
Thuật toán RSA có hai khóa: khóa công khai (public key) và khóa bí mật (private key). Mỗi khóa là những số cố định sử dụng trong quá trình mã hóa và giải mã. Khóa công khai được công bố rộng rãi cho mọi người và được dùng để mã hóa. Những thông tin được mã hóa bằng khóa công khai chỉ có thể được giải mã bằng khóa bí mật tương ứng. Nói cách khác, mọi người đều có thể mã hóa nhưng chỉ có người biết khóa cá nhân (bí mật) mới có thể giải mã được.
Ta có thể mô phỏng trực quan một hệ mật mã khoá công khai như sau: Bob muốn gửi cho Alice một thông tin mật mà Bob muốn duy nhất Alice có thể đọc được. Để làm được điều này, Alice gửi cho Bob một chiếc hộp có khóa đã mở sẵn và giữ lại chìa khóa. Bob nhận chiếc hộp, cho vào đó một tờ giấy viết thư bình thường và khóa lại (như loại khoá thông thường chỉ cần sập chốt lại, sau khi sập chốt khóa ngay cả Bob cũng không thể mở lại được-không đọc lại hay sửa thông tin trong thư được nữa). Sau đó Bob gửi chiếc hộp lại cho Alice. Alice mở hộp với chìa khóa của mình và đọc thông tin trong thư. Trong ví dụ này, chiếc hộp với khóa mở đóng vai trò khóa công khai, chiếc chìa khóa chính là khóa bí mật.
Ví dụ về mã hóa và giải mã(RSA) một chuỗi kí tự
- Tạo cặp khoá
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<span class="hljs-keyword"><span class="hljs-keyword">package</span></span> vuta.cryptography.demo; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.io.<span class="hljs-keyword">File</span>; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.io.FileOutputStream; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.io.IOException; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.KeyPair; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.KeyPairGenerator; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.PrivateKey; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.PublicKey; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.SecureRandom; <span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class"> <span class="hljs-title">SecurityKeyPairGenerator</span> </span>{ <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{ <span class="hljs-keyword"><span class="hljs-keyword">try</span></span> { SecureRandom sr = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> SecureRandom(); <span class="hljs-comment"><span class="hljs-comment">// Thuật toán phát sinh khóa - RSA</span></span> <span class="hljs-comment"><span class="hljs-comment">// Độ dài khóa 1024(bits), độ dài khóa này quyết định đến độ an toàn của khóa, càng lớn thì càng an toàn</span></span> <span class="hljs-comment"><span class="hljs-comment">// Demo chỉ sử dụng 1024 bit. Nhưng theo khuyến cáo thì độ dài khóa nên tối thiểu là 2048</span></span> KeyPairGenerator kpg = KeyPairGenerator.getInstance(<span class="hljs-string"><span class="hljs-string">"RSA"</span></span>); kpg.initialize(<span class="hljs-number"><span class="hljs-number">1024</span></span>, sr); <span class="hljs-comment"><span class="hljs-comment">// Khởi tạo cặp khóa</span></span> KeyPair kp = kpg.genKeyPair(); <span class="hljs-comment"><span class="hljs-comment">// PublicKey</span></span> PublicKey publicKey = kp.getPublic(); <span class="hljs-comment"><span class="hljs-comment">// PrivateKey</span></span> PrivateKey privateKey = kp.getPrivate(); <span class="hljs-keyword">File</span> publicKeyFile = createKeyFile(<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-keyword">File</span>(<span class="hljs-string"><span class="hljs-string">"C:/publicKey.rsa"</span></span>)); <span class="hljs-keyword">File</span> privateKeyFile = createKeyFile(<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-keyword">File</span>(<span class="hljs-string"><span class="hljs-string">"C:/privateKey.rsa"</span></span>)); <span class="hljs-comment"><span class="hljs-comment">// Lưu Public Key</span></span> FileOutputStream fos = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> FileOutputStream(publicKeyFile); fos.<span class="hljs-keyword">write</span>(publicKey.getEncoded()); fos.close(); <span class="hljs-comment"><span class="hljs-comment">// Lưu Private Key</span></span> fos = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> FileOutputStream(privateKeyFile); fos.<span class="hljs-keyword">write</span>(privateKey.getEncoded()); fos.close(); System.out.<span class="hljs-keyword">println</span>(<span class="hljs-string"><span class="hljs-string">"Generate key successfully"</span></span>); } <span class="hljs-keyword"><span class="hljs-keyword">catch</span></span> (Exception e) { e.printStackTrace(); } } <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">private</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span> <span class="hljs-keyword"><span class="hljs-function">File</span></span><span class="hljs-function"> <span class="hljs-title">createKeyFile</span><span class="hljs-params">(</span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params">File</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params">file</span></span></span><span class="hljs-function"><span class="hljs-params">)</span> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span><span class="hljs-function"> IOException </span>{ <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!<span class="hljs-keyword">file</span>.exists()) { <span class="hljs-keyword">file</span>.createNewFile(); } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> { <span class="hljs-keyword">file</span>.<span class="hljs-keyword">delete</span>(); <span class="hljs-keyword">file</span>.createNewFile(); } <span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-keyword">file</span>; } } |
- Mã hoá dữ liệu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<span class="hljs-keyword">package</span> vuta.cryptography.demo; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.io.FileInputStream; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.KeyFactory; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.PublicKey; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.spec.X509EncodedKeySpec; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.util.Base64; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> javax.crypto.Cipher; <span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Encrpytion</span> </span>{ <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> <span class="hljs-title">main</span><span class="hljs-params">(</span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params">String</span></span></span><span class="hljs-function"><span class="hljs-params">[] args)</span> </span>{ <span class="hljs-built_in"><span class="hljs-keyword">try</span></span> { <span class="hljs-comment"><span class="hljs-comment">// Đọc file chứa public key</span></span> FileInputStream fis = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> FileInputStream(<span class="hljs-string"><span class="hljs-string">"C:/publicKey.rsa"</span></span>); <span class="hljs-keyword"><span class="hljs-keyword">byte</span></span>[] b = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-keyword"><span class="hljs-keyword">byte</span></span>[fis.<span class="hljs-built_in">available</span>()]; fis.<span class="hljs-built_in">read</span>(b); fis.<span class="hljs-built_in">close</span>(); <span class="hljs-comment"><span class="hljs-comment">// Tạo public key</span></span> X509EncodedKeySpec spec = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> X509EncodedKeySpec(b); KeyFactory factory = KeyFactory.getInstance(<span class="hljs-string"><span class="hljs-string">"RSA"</span></span>); PublicKey pubKey = factory.generatePublic(spec); <span class="hljs-comment"><span class="hljs-comment">// Mã hoá dữ liệu</span></span> Cipher c = Cipher.getInstance(<span class="hljs-string"><span class="hljs-string">"RSA"</span></span>); c.init(Cipher.ENCRYPT_MODE, pubKey); <span class="hljs-keyword">String</span> msg = <span class="hljs-string"><span class="hljs-string">"helloworld"</span></span>; <span class="hljs-keyword"><span class="hljs-keyword">byte</span></span> encryptOut[] = c.doFinal(msg.getBytes()); <span class="hljs-keyword">String</span> strEncrypt = Base64.getEncoder().encodeToString(encryptOut); System.out.<span class="hljs-built_in">println</span>(<span class="hljs-string"><span class="hljs-string">"Chuỗi sau khi mã hoá: "</span></span> + strEncrypt); } <span class="hljs-built_in"><span class="hljs-keyword">catch</span></span> (Exception ex) { ex.printStackTrace(); } } } |
1 |
Chuỗi sau khi mã hoá: RR8WsVCiTUkm67vY8dSfv+eJ1h2JLEulXQZf4t7rxP8HynxMKrYcAmGvIYsrUb77ys4K8uUj48ayT3bSsM3wfnoJLtgww2idNB7r8UeIyIGe/UKoO0co5aJoptt8NwuKNCS0uf7fEEZnAfB1rszXqKQj0IxOdCtYLorO7DltwDM= |
Giải mã dữ liệu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<span class="hljs-keyword">package</span> vuta.cryptography.demo; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.io.FileInputStream; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.KeyFactory; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.PrivateKey; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.security.spec.PKCS8EncodedKeySpec; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> java.util.Base64; <span class="hljs-keyword"><span class="hljs-keyword">import</span></span> javax.crypto.Cipher; <span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Decryption</span> </span>{ <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> <span class="hljs-title">main</span><span class="hljs-params">(</span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params">String</span></span></span><span class="hljs-function"><span class="hljs-params">[] args)</span> </span>{ <span class="hljs-built_in"><span class="hljs-keyword">try</span></span> { <span class="hljs-comment"><span class="hljs-comment">// Đọc file chứa private key</span></span> FileInputStream fis = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> FileInputStream(<span class="hljs-string"><span class="hljs-string">"C:/privateKey.rsa"</span></span>); <span class="hljs-keyword"><span class="hljs-keyword">byte</span></span>[] b = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-keyword"><span class="hljs-keyword">byte</span></span>[fis.<span class="hljs-built_in">available</span>()]; fis.<span class="hljs-built_in">read</span>(b); fis.<span class="hljs-built_in">close</span>(); <span class="hljs-comment"><span class="hljs-comment">// Tạo private key</span></span> PKCS8EncodedKeySpec spec = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> PKCS8EncodedKeySpec(b); KeyFactory factory = KeyFactory.getInstance(<span class="hljs-string"><span class="hljs-string">"RSA"</span></span>); PrivateKey priKey = factory.generatePrivate(spec); <span class="hljs-comment"><span class="hljs-comment">// Giải mã dữ liệu</span></span> Cipher c = Cipher.getInstance(<span class="hljs-string"><span class="hljs-string">"RSA"</span></span>); c.init(Cipher.DECRYPT_MODE, priKey); <span class="hljs-keyword"><span class="hljs-keyword">byte</span></span> decryptOut[] = c.doFinal(Base64.getDecoder().decode( <span class="hljs-string"><span class="hljs-string">"RR8WsVCiTUkm67vY8dSfv+eJ1h2JLEulXQZf4t7rxP8HynxMKrYcAmGvIYsrUb77ys4K8uUj48ayT3bSsM3wfnoJLtgww2idNB7r8UeIyIGe/UKoO0co5aJoptt8NwuKNCS0uf7fEEZnAfB1rszXqKQj0IxOdCtYLorO7DltwDM="</span></span>)); System.out.<span class="hljs-built_in">println</span>(<span class="hljs-string"><span class="hljs-string">"Dữ liệu sau khi giải mã: "</span></span> + <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-keyword">String</span>(decryptOut)); } <span class="hljs-built_in"><span class="hljs-keyword">catch</span></span> (Exception ex) { ex.printStackTrace(); } } } |
Dữ liệu sau khi giải mã: helloworld
Qua bài viết này hy vọng có thể phần nào giúp các bạn học lập trình Java có cái nhìn cơ bản về mã hóa .