Java:使用JDK中的安全包对数据进行加解密

Java:使用JDK中的安全包对数据进行加解密
From:  http://blog.csdn.net/noliyo/article/details/9166365@import url(http://www.cppblog.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类型可以通过以下代码:
[java]  view plain copy print ?
  1. for(Provider p : Security.getProviders()){  
  2.     System.out.println(p.getName()+":"+p.getInfo());    
  3. }  

我本机运行结果为:
[java]  view plain copy print ?
  1. 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)  
  2. SunRsaSign:Sun RSA signature provider  
  3. SunJSSE:Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)  
  4. SunJCE:SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)  
  5. SunJGSS:Sun (Kerberos v5, SPNEGO)  
  6. SunSASL:Sun SASL provider(implements client mechanisms for: DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5; server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)  
  7. XMLDSig:XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory)  
  8. SunPCSC:Sun PC/SC provider  
  9. SunMSCAPI:Sun's Microsoft Crypto API provider  
从结果中可以看到名称为“SunJCE”的Provider提供DES、Triple DES(即3DES), AES、RSA、Diffie-Hellman等算法的实现,下面使用此Provider完成对称加密。

KeyGenerator类提供(对称)密钥生成器的功能,使用getInstance 类方法构造,代码如下:
[java]  view plain copy print ?
  1. KeyGenerator kg = KeyGenerator.getInstance("DES","SunJCE");  

SecretKey类是对称密钥的封装类,它不包含方法或常量,其唯一目的是分组对称密钥(并为其提供类型安全),从kg中获取 
[java]  view plain copy print ?
  1. SecretKey key = kg.generateKey();  

以上是产生密钥的过程,真正实现对数据加解密功能的类是Cipher,此类为加密和解密提供密码功能,它构成了 Java Cryptographic Extension (JCE) 框架的核心。
为创建 Cipher 对象,应用程序调用 Cipher 的 getInstance 方法并将所请求“转换”的名称传递给它,还可以指定Provider的名称,本文中采用“SunJCE”。
“转换”是一个字符串,它描述为产生某种输出而在给定的输入上执行的操作(或一组操作)。转换始终包括加密算法的名称(例如,DES),后面可能跟有一个反馈模式和填充方案(反馈模式和填充方案可以理解为 加密前对数据的预处理)
“转换”具有以下两种形式:“算法/模式/填充”或“算法”(这种情况,使用模式和填充方案特定于Provider的默认值)。本例中采用以下有效的转换:
[java]  view plain copy print ?
  1. Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding","SunJCE");//DES加密算法,CBC的反馈模式,PKCS5Padding的填充方案  

使用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字符的一种方法。还可以提高可视性。

通过以上分析可以得到以下代码: 
[java]  view plain copy print ?
  1. import java.io.IOException;  
  2. import java.io.UnsupportedEncodingException;  
  3. import java.security.InvalidAlgorithmParameterException;  
  4. import java.security.InvalidKeyException;  
  5. import java.security.NoSuchAlgorithmException;  
  6. import java.security.NoSuchProviderException;  
  7. import javax.crypto.BadPaddingException;  
  8. import javax.crypto.Cipher;  
  9. import javax.crypto.IllegalBlockSizeException;  
  10. import javax.crypto.KeyGenerator;  
  11. import javax.crypto.NoSuchPaddingException;  
  12. import javax.crypto.SecretKey;  
  13. import javax.crypto.spec.IvParameterSpec;  
  14. import sun.misc.BASE64Decoder;  
  15. import sun.misc.BASE64Encoder;  
  16.   
  17. public class SecurityTest {  
  18.   
  19.     //密钥生成器  
  20.     private KeyGenerator kg;   
  21.       
  22.     //对称密钥    
  23.     private SecretKey key;    
  24.       
  25.     //加解密时的初始化向量must be 8 bytes long  
  26.     private IvParameterSpec iv;  
  27.       
  28.     //Cipher,加解密主体实例  
  29.     private Cipher c;    
  30.       
  31.     //该构造方法初始化DES密钥和Cipher    
  32.     public SecurityTest() throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, UnsupportedEncodingException{  
  33.         kg = KeyGenerator.getInstance("DES","SunJCE");    
  34.         key = kg.generateKey();  
  35.         iv = new IvParameterSpec("12345678".getBytes("UTF-8"));  
  36.         c = Cipher.getInstance("DES/CBC/PKCS5Padding","SunJCE");//DES加密算法,CBC的反馈模式,PKCS5Padding的填充方案 ,SunJCE:Provider  
  37.     }    
  38.         
  39.     /**  
  40.      * DES加密 
  41.      */    
  42.     public String encrypt(String src) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException{    
  43.         //初始化-- ENCRYPT_MODE:加密模式, key:密钥,iv:初始化向量  
  44.         c.init(Cipher.ENCRYPT_MODE, key, iv);    
  45.         byte[] srcByte = src.getBytes();    
  46.         //加密  
  47.         byte[] targetByte = c.doFinal(srcByte);   
  48.         //Base64编码  
  49.         String targetString = new BASE64Encoder().encode(targetByte);  
  50.         return targetString;    
  51.     }    
  52.     
  53.     /**  
  54.      * DES解密  
  55.      */    
  56.     public String decrypt(String srcString) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidAlgorithmParameterException {    
  57.         //初始化-- DECRYPT_MODE:解密模式, key:密钥,iv:初始化向量  
  58.         c.init(Cipher.DECRYPT_MODE, key, iv);   
  59.         //Base64解码  
  60.         byte[] srcByte = new BASE64Decoder().decodeBuffer(srcString);  
  61.         //解密  
  62.         byte[] targetByte = c.doFinal(srcByte);    
  63.         return new String(targetByte);    
  64.     }    
  65.     
  66.     public static void main(String[] args) throws Exception {    
  67.         SecurityTest test = new SecurityTest();    
  68.         String src = "使用JKD进行加解密--DES算法测试!__小印";    
  69.         System.out.println("原文:" + src);  
  70.         String secret = test.encrypt(src);      
  71.         System.out.println("密文:" + secret);   
  72.         String target = test.decrypt(secret);  
  73.         System.out.println("解密得到原文:" + target);    
  74.     }   

我本机运行结果为:

[java]  view plain copy print ?
  1. 原文:使用JKD进行加解密--DES算法测试!__小印  
  2. 密文:P8Xi4Jfvq9Eus0c1OTE32wK60rjHwPxZ8tRiElxOd5m69+vI37IGtw==  
  3. 解密得到原文:使用JKD进行加解密--DES算法测试!__小印  

注意:本文采用的是随机密钥,所以每次运行得到的密文是不一样的,jdk也提供自定义的密钥 ^_^

你可能感兴趣的:(Java:使用JDK中的安全包对数据进行加解密)