From:
http://blog.csdn.net/noliyo/article/details/9166365@import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
本文以使用DES對稱加密算法為例使用jdk對數據進行加密解密。
首先需要了解Provider類,它是jdk引入的密碼服務提供者概念,實現了Java安全性的一部分或者全部。Provider 可能實現的服務包括:
算法(如DES、RSA、MD5);密鑰的生成、轉換和管理。
通常java運行時環境至少安裝了一個名字為“SUN”的預設Provider,如果查看本機支持的Provider類型可以通過以下代碼:
- for(Provider p : Security.getProviders()){
- System.out.println(p.getName()+":"+p.getInfo());
- }
我本機運行結果為:
- SUN:SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS keystore; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; JavaLoginConfig Configuration)
- SunRsaSign:Sun RSA signature provider
- SunJSSE:Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)
- SunJCE:SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)
- SunJGSS:Sun (Kerberos v5, SPNEGO)
- SunSASL:Sun SASL provider(implements client mechanisms for: DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5; server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)
- XMLDSig:XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory)
- SunPCSC:Sun PC/SC provider
- SunMSCAPI:Sun's Microsoft Crypto API provider
從結果中可以看到名稱為“SunJCE”的Provider提供DES、Triple DES(即3DES), AES、RSA、Diffie-Hellman等算法的實現,下面使用此Provider完成對稱加密。
KeyGenerator類提供(對稱)密鑰生成器的功能,使用getInstance 類方法構造,代碼如下:
- KeyGenerator kg = KeyGenerator.getInstance("DES","SunJCE");
SecretKey類是對稱密鑰的封裝類,它不包含方法或常量,其唯一目的是分組對稱密鑰(并為其提供類型安全),從kg中獲取
- SecretKey key = kg.generateKey();
以上是產生密鑰的過程,真正實現對數據加解密功能的類是Cipher,此類為加密和解密提供密碼功能,它構成了 Java Cryptographic Extension (JCE) 框架的核心。
為創建 Cipher 對象,應用程序調用 Cipher 的 getInstance 方法并將所請求“轉換”的名稱傳遞給它,還可以指定Provider的名稱,本文中采用“SunJCE”。
“轉換”是一個字符串,它描述為產生某種輸出而在給定的輸入上執行的操作(或一組操作)。轉換始終包括加密算法的名稱(例如,DES),后面可能跟有一個反饋模式和填充方案(反饋模式和填充方案可以理解為 加密前對數據的預處理)
“轉換”具有以下兩種形式:“算法/模式/填充”或“算法”(這種情況,使用模式和填充方案特定于Provider的默認值)。本例中采用以下有效的轉換:
- Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding","SunJCE");
使用CBC反饋模式需要一個初始化向量,由類IvParameterSpec來完成,它需要是一個長度為8的byte數組。
Cipher的init方法負責初始化,初始化需要指定模式和密鑰,密鑰本文采用上面已經生成的key,模式有四種ENCRYPT_MODE、DECRYPT_MODE、WRAP_MODE、UNWRAP_MODE分別表示加密、解密、密鑰包裝或密鑰解包。
如果加密則采用方法init(Cipher.ENCRYPT_MODE, key);
如果解密則采用方法init(Cipher.DECRYPT_MODE, key);
WRAP_MODE、UNWRAP_MODE模式是用來實現數字信封用的,本文不作介紹。
通常對數據進行加解密,使用方法doFinal(byte[] input),傳入參數是byte數組。
為了在http協議下快速傳輸數據,且某些系統中只能使用ASCII字符,通常采用Base64編碼。Base64就是用來將非ASCII字符的數據轉換成ASCII字符的一種方法。還可以提高可視性。
通過以上分析可以得到以下代碼:
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.security.InvalidAlgorithmParameterException;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.security.NoSuchProviderException;
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.KeyGenerator;
- import javax.crypto.NoSuchPaddingException;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.IvParameterSpec;
- import sun.misc.BASE64Decoder;
- import sun.misc.BASE64Encoder;
-
- public class SecurityTest {
-
-
- private KeyGenerator kg;
-
-
- private SecretKey key;
-
-
- private IvParameterSpec iv;
-
-
- private Cipher c;
-
-
- public SecurityTest() throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, UnsupportedEncodingException{
- kg = KeyGenerator.getInstance("DES","SunJCE");
- key = kg.generateKey();
- iv = new IvParameterSpec("12345678".getBytes("UTF-8"));
- c = Cipher.getInstance("DES/CBC/PKCS5Padding","SunJCE");
- }
-
-
-
-
- public String encrypt(String src) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException{
-
- c.init(Cipher.ENCRYPT_MODE, key, iv);
- byte[] srcByte = src.getBytes();
-
- byte[] targetByte = c.doFinal(srcByte);
-
- String targetString = new BASE64Encoder().encode(targetByte);
- return targetString;
- }
-
-
-
-
- public String decrypt(String srcString) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidAlgorithmParameterException {
-
- c.init(Cipher.DECRYPT_MODE, key, iv);
-
- byte[] srcByte = new BASE64Decoder().decodeBuffer(srcString);
-
- byte[] targetByte = c.doFinal(srcByte);
- return new String(targetByte);
- }
-
- public static void main(String[] args) throws Exception {
- SecurityTest test = new SecurityTest();
- String src = "使用JKD進行加解密--DES算法測試!__小印";
- System.out.println("原文:" + src);
- String secret = test.encrypt(src);
- System.out.println("密文:" + secret);
- String target = test.decrypt(secret);
- System.out.println("解密得到原文:" + target);
- }
我本機運行結果為:
- 原文:使用JKD進行加解密--DES算法測試!__小印
- 密文:P8Xi4Jfvq9Eus0c1OTE32wK60rjHwPxZ8tRiElxOd5m69+vI37IGtw==
- 解密得到原文:使用JKD進行加解密--DES算法測試!__小印
注意:本文采用的是隨機密鑰,所以每次運行得到的密文是不一樣的,jdk也提供自定義的密鑰 ^_^