1 Java密码扩展(The Java Cryptography Extension),是JDK1.4的一个重要部分,基本上,他是由一些包构成的,这些包形成了一个框架并实现了 2 一些加密,密钥生成算法和协议,消息认证码等算法,这篇文章将想你介绍JCE的安装和使用。 3 值得注意的是,尽管JCE是JDK1.4的核心包的一部分,我们将首先用JDK1.2及高一点的版本向你演示一下如果安装配置JCE(静态安装)。稍后, 4 将向你介绍如何在不安装的情况下使用JCE(动态安装)。最后,将演示怎么生成密钥和密码,及如果进行基本的加密.解密。 5 提供者是什么? 6 提供者是特定加密算法的实现者,有的提供者(提供的加密技术)是免费的,有的不免费,IBM, Bouncy Castle, 和 RSA都是一些(加密)提供 7 者.在本文的后面,我们将考察一下来自Bouncy Castle的RSA算法。Sun 也向大家说明了如果实现自己的提供者(需要符合jDK的一些约定)。 8 静态安装 9 在安装和使用JCE之前,你需要从 Sun Web site(这里是以暗中sun的提供者为例).获得他的安装包,JCE有sun他自己的安全提供者-sunJCE, 10 为了吧sunJCE静态的安装到默认的提供者列表中,你需要修改安全属性文件: 11 •\jre\lib\security\java.security (Win32) 12 • /jre/lib/security/java.security (UNIX) 13 如果你把JDK安装在C:\jdk1.3,你需要编辑以下文件: 14 C:\jdk1.3\jre\lib\security\java.security 15 为了安装SunJCE,你需要在以上文件中加入: 16 security.provider.n=com.sun.crypto.provider.SunJCE 17 把n用你加入的提供者的优先级代替(注意:序号要保持递增,不能跳过,但可以调整前后顺序)。 18 Listing A 用于查看你安装过的提供者的信息,结果在Listing B中列出,显示提供者的能力,比如说可用的加密算法。 19 Listing A: ProviderInformation.java 20 import java.security.Provider; 21 import java.security.Security; 22 import java.util.Set; 23 import java.util.Iterator; 24 public class ProviderInformation { 25 public static void main(String[] args) { 26 Provider[] providers = Security.getProviders(); 27 for (int i = 0; i < providers.length; i++) { 28 Provider provider = providers[i]; 29 System.out.println("Provider name: " + provider.getName()); 30 System.out.println("Provider information: " + provider.getInfo()); 31 System.out.println("Provider version: " + provider.getVersion()); 32 Set entries = provider.entrySet(); 33 Iterator iterator = entries.iterator(); 34 while (iterator.hasNext()) { 35 System.out.println("Property entry: " + iterator.next()); 36 } 37 } 38 } 39 } 40 Listing B: ProviderInformation.java output 41 Provider name: SUN 42 Provider information: SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; 43 JKS keystore) 44 Provider version: 1.2 45 Property entry: Alg.Alias.KeyFactory.1.2.840.10040.4.1=DSA 46 Property entry: Alg.Alias.Signature.1.2.840.10040.4.3=SHA1withDSA 47 Property entry: Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1=DSA 48 Property entry: Signature.SHA1withDSA KeySize=1024 49 Property entry: Signature.SHA1withDSA ImplementedIn=Software 50 动态安装:Listing c 说明了如何在运行时动态加载安全提供者,要注意的是,当你用Security.addProvider(…)加载提供者时, 51 它是对整个JVM环境都有用的; 52 Listing C: DynamicProvider.java 53 import java.security.Security; 54 public class DynamicProvider { 55 public static void main(String[] args) { 56 // This is all there is to it! 57 Security.addProvider(new com.sun.crypto.provider.SunJCE()); 58 } 59 } 60 如前所述,当你安装一个提供者时,你用n来指明此提供者的优先级,但一个算法的实例被调用时,JVM将按照提供的优先级来在已经安装的提 61 供者中查找可用的实现,并使用他首先找到的可用算法。你也可用在调研时加上附加参数来指明要在那个提供者中寻找使用的算法。 62 63 实现细节: 64 JCE API包含了大量的为实现安全特性的类和接口,首先,我们做一个DES对称加密的例子。 65 66 生成密钥: 67 Listing D 展示了如果初时化密钥生成器来生成密钥; 68 Listing D: DESKeyGenerator.java 69 70 71 72 73 import javax.crypto.KeyGenerator; 74 import java.security.Key; 75 import java.security.NoSuchAlgorithmException; 76 import java.security.Security; 77 public class DESKeyGenerator { 78 public static void main(String[] args) { 79 Security.addProvider(new com.sun.crypto.provider.SunJCE()); 80 try { 81 KeyGenerator kg = KeyGenerator.getInstance("DES"); 82 Key key = kg.generateKey(); 83 System.out.println("Key format: " + key.getFormat()); 84 System.out.println("Key algorithm: " + key.getAlgorithm()); 85 } 86 catch (NoSuchAlgorithmException e) { 87 e.printStackTrace(); 88 } 89 } 90 } 91 92 93 为了生成密钥,我们首先要初始化密钥生成器,这一步可以通过调用KeyGenerator类的静态方法getInstance来实现。我们所用的vanilla DES算法 94 没有模式和填充模型。你同样可以(在getInstance(""))传入DES/ECB/PKCS5Padding来指明模式(ECB)和填充模式(PKCS5Padding);也可以传入另 95 外一个参数指明所用的提供者,不过这是可选的; 96 KeyGenerator kg = KeyGenerator.getInstance("DES"); 97 98 一旦我们有了特定的密钥生成对象,我们就可以用他得到密钥: 99 Key key = kg.generateKey(); 100 生成密码: 101 生成密码的过程跟生成密钥类似,需要调用Cipher类的getInstance方法,参数要跟生成密钥时用的参数保持一致; 102 Cipher cipher = Cipher.getInstance(“DES”); 103 104 Listing E 说明了如果操作: 105 Listing E: DESCipherGenerator.java 106 import javax.crypto.Cipher; 107 import javax.crypto.NoSuchPaddingException; 108 import java.security.Security; 109 import java.security.NoSuchAlgorithmException; 110 public class DESCipherGenerator { 111 public static void main(String[] args) { 112 Security.addProvider(new com.sun.crypto.provider.SunJCE()); 113 try { 114 Cipher cipher = Cipher.getInstance("DES"); 115 System.out.println("Cipher provider: " + cipher.getProvider()); 116 System.out.println("Cipher algorithm: " + cipher.getAlgorithm()); 117 } 118 catch (NoSuchAlgorithmException e) { 119 e.printStackTrace(); 120 } 121 catch (NoSuchPaddingException e) { 122 e.printStackTrace(); 123 } 124 } 125 } 126 127 128 加解密数据 129 加密是对字节的,所以保密行比较高,当你准备好了密钥和密码时,你已经做好了加密的准备,要注意的时,同一个算法要用相同的密钥和密码, 130 比如说,你不能用DESsede的密钥,用DES的密码,密码对象用同一个方法对数据进行加密和解密,所有你要首先初时化,让他知道你要干什么: 131 cipher.init(Cipher.ENCRYPT_MODE, key); 132 这就将初始化Cipher类,以准备好加密数据,.最简单的加密方法及时对传入的字节数组调用doFinal方法: 133 byte[] data = “Hello World!”.getBytes(); 134 byte[] result = cipher.doFinal(data); 135 Listing F 是详细的代码 136 Listing F: DESCryptoTest.java 137 import javax.crypto.Cipher; 138 import javax.crypto.KeyGenerator; 139 import javax.crypto.NoSuchPaddingException; 140 import javax.crypto.IllegalBlockSizeException; 141 import javax.crypto.BadPaddingException; 142 import java.security.Key; 143 import java.security.Security; 144 import java.security.NoSuchAlgorithmException; 145 import java.security.InvalidKeyException; 146 public class DESCryptoTest { 147 public static void main(String[] args) { 148 Security.addProvider(new com.sun.crypto.provider.SunJCE()); 149 try { 150 KeyGenerator kg = KeyGenerator.getInstance("DES"); 151 Key key = kg.generateKey(); 152 Cipher cipher = Cipher.getInstance("DES"); 153 154 byte[] data = "Hello World!".getBytes(); 155 System.out.println("Original data : " + new String(data)); 156 157 cipher.init(Cipher.ENCRYPT_MODE, key); 158 byte[] result = cipher.doFinal(data); 159 System.out.println("Encrypted data: " + new String(result)); 160 161 cipher.init(Cipher.DECRYPT_MODE, key); 162 byte[] original = cipher.doFinal(result); 163 System.out.println("Decrypted data: " + new String(original)); 164 } 165 catch (NoSuchAlgorithmException e) { 166 e.printStackTrace(); 167 } 168 catch (NoSuchPaddingException e) { 169 e.printStackTrace(); 170 } 171 catch (InvalidKeyException e) { 172 e.printStackTrace(); 173 } 174 catch (IllegalStateException e) { 175 e.printStackTrace(); 176 } 177 catch (IllegalBlockSizeException e) { 178 e.printStackTrace(); 179 } 180 catch (BadPaddingException e) { 181 e.printStackTrace(); 182 } 183 } 184 } 185 总结:JCE是个功能强大的API,提供了众多的加密方法和其他安全相关的属性,我们已经找到怎样动态和静态安装JCE,并用DES对一段简单的信息进 186 行了加密和解密,在本系列的第二部分,我们将把本文的知识用到现实的应用中去,将告诉大家如果写一个跟Socket配合使用的包装类(Wrapper), 187 用以加密你网上交易的重要信息。