当前位置: 首页 > news >正文

兰溪网站建设公司长沙外贸网站建设

兰溪网站建设公司,长沙外贸网站建设,网站设计与建设系统,石家庄品牌网站建设2019独角兽企业重金招聘Python工程师标准 如基本的单向加密算法#xff1a; BASE64 严格地说#xff0c;属于编码格式#xff0c;而非加密算法MD5(Message Digest algorithm 5#xff0c;信息摘要算法)SHA(Secure Hash Algorithm#xff0c;安全散列算法)H… 2019独角兽企业重金招聘Python工程师标准   如基本的单向加密算法  BASE64 严格地说属于编码格式而非加密算法MD5(Message Digest algorithm 5信息摘要算法)SHA(Secure Hash Algorithm安全散列算法)HMAC(Hash Message Authentication Code散列消息鉴别码)    复杂的对称加密DES、PBE、非对称加密算法  DES(Data Encryption Standard数据加密算法)PBE(Password-based encryption基于密码验证)RSA(算法的名字以发明者的名字命名Ron Rivest, AdiShamir 和Leonard Adleman)DH(Diffie-Hellman算法密钥一致协议)DSA(Digital Signature Algorithm数字签名)ECC(Elliptic Curves Cryptography椭圆曲线密码编码学)    本篇内容简要介绍BASE64、MD5、SHA、HMAC几种方法。     MD5、SHA、HMAC这三种加密算法可谓是非可逆加密就是不可解密的加密方法。我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。 BASE64 按照RFC2045的定义Base64被定义为Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable. 常见于邮件、http加密截取http信息你就会发现登录操作的用户名、密码字段通过BASE64加密的。  通过java代码实现如下 /*** BASE64解密* * param key* return* throws Exception*/public static byte[] decryptBASE64(String key) throws Exception {return (new BASE64Decoder()).decodeBuffer(key);}/*** BASE64加密* * param key* return* throws Exception*/public static String encryptBASE64(byte[] key) throws Exception {return (new BASE64Encoder()).encodeBuffer(key);} 主要就是BASE64Encoder、BASE64Decoder两个类我们只需要知道使用对应的方法即可。另BASE加密后产生的字节位数是8的倍数如果不够位数以符号填充。 MD5 MD5 -- message-digest algorithm 5 信息-摘要算法缩写广泛用于加密和解密技术常用于文件校验。校验不管文件多大经过MD5后都能生成唯一的MD5值。好比现在的ISO校验都是MD5校验。怎么用当然是把ISO经过MD5后产生MD5的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD5的串。就是用来验证文件是否一致的。  通过java代码实现如下 /*** MD5加密* * param data* return* throws Exception*/public static byte[] encryptMD5(byte[] data) throws Exception {MessageDigest md5  MessageDigest.getInstance(KEY_MD5);md5.update(data);return md5.digest();} 通常我们不直接使用上述MD5加密。通常将MD5产生的字节数组交给BASE64再加密一把得到相应的字符串。 SHA SHA(Secure Hash Algorithm安全散列算法数字签名等密码学应用中重要的工具被广泛地应用于电子商务等信息安全领域。虽然SHA与MD5通过碰撞法都被破解了 但是SHA仍然是公认的安全加密算法较之MD5更为安全。  通过java代码实现如下 /*** SHA加密* * param data* return* throws Exception*/public static byte[] encryptSHA(byte[] data) throws Exception {MessageDigest sha  MessageDigest.getInstance(KEY_SHA);sha.update(data);return sha.digest();} } HMAC HMAC(Hash Message Authentication Code散列消息鉴别码基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是用公开函数和密钥产生一个固定长度的值作为认证标识用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块即MAC并将其加入到消息中然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。  通过java代码实现如下 /*** 初始化HMAC密钥* * return* throws Exception*/public static String initMacKey() throws Exception {KeyGenerator keyGenerator  KeyGenerator.getInstance(KEY_MAC);SecretKey secretKey  keyGenerator.generateKey();return encryptBASE64(secretKey.getEncoded());}/*** HMAC加密* * param data* param key* return* throws Exception*/public static byte[] encryptHMAC(byte[] data, String key) throws Exception {SecretKey secretKey  new SecretKeySpec(decryptBASE64(key), KEY_MAC);Mac mac  Mac.getInstance(secretKey.getAlgorithm());mac.init(secretKey);return mac.doFinal(data);} 给出一个完整类如下 import java.security.MessageDigest;import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey;import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder;/*** 基础加密组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class Coder {public static final String KEY_SHA  SHA;public static final String KEY_MD5  MD5;/*** MAC算法可选以下多种算法* * pre* HmacMD5 * HmacSHA1 * HmacSHA256 * HmacSHA384 * HmacSHA512* /pre*/public static final String KEY_MAC  HmacMD5;/*** BASE64解密* * param key* return* throws Exception*/public static byte[] decryptBASE64(String key) throws Exception {return (new BASE64Decoder()).decodeBuffer(key);}/*** BASE64加密* * param key* return* throws Exception*/public static String encryptBASE64(byte[] key) throws Exception {return (new BASE64Encoder()).encodeBuffer(key);}/*** MD5加密* * param data* return* throws Exception*/public static byte[] encryptMD5(byte[] data) throws Exception {MessageDigest md5  MessageDigest.getInstance(KEY_MD5);md5.update(data);return md5.digest();}/*** SHA加密* * param data* return* throws Exception*/public static byte[] encryptSHA(byte[] data) throws Exception {MessageDigest sha  MessageDigest.getInstance(KEY_SHA);sha.update(data);return sha.digest();}/*** 初始化HMAC密钥* * return* throws Exception*/public static String initMacKey() throws Exception {KeyGenerator keyGenerator  KeyGenerator.getInstance(KEY_MAC);SecretKey secretKey  keyGenerator.generateKey();return encryptBASE64(secretKey.getEncoded());}/*** HMAC加密* * param data* param key* return* throws Exception*/public static byte[] encryptHMAC(byte[] data, String key) throws Exception {SecretKey secretKey  new SecretKeySpec(decryptBASE64(key), KEY_MAC);Mac mac  Mac.getInstance(secretKey.getAlgorithm());mac.init(secretKey);return mac.doFinal(data);} } 再给出一个测试类 import static org.junit.Assert.*;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class CoderTest {Testpublic void test() throws Exception {String inputStr  简单加密;System.err.println(原文:\n  inputStr);byte[] inputData  inputStr.getBytes();String code  Coder.encryptBASE64(inputData);System.err.println(BASE64加密后:\n  code);byte[] output  Coder.decryptBASE64(code);String outputStr  new String(output);System.err.println(BASE64解密后:\n  outputStr);// 验证BASE64加密解密一致性assertEquals(inputStr, outputStr);// 验证MD5对于同一内容加密是否一致assertArrayEquals(Coder.encryptMD5(inputData), Coder.encryptMD5(inputData));// 验证SHA对于同一内容加密是否一致assertArrayEquals(Coder.encryptSHA(inputData), Coder.encryptSHA(inputData));String key  Coder.initMacKey();System.err.println(Mac密钥:\n  key);// 验证HMAC对于同一内容同一密钥加密是否一致assertArrayEquals(Coder.encryptHMAC(inputData, key), Coder.encryptHMAC(inputData, key));BigInteger md5  new BigInteger(Coder.encryptMD5(inputData));System.err.println(MD5:\n  md5.toString(16));BigInteger sha  new BigInteger(Coder.encryptSHA(inputData));System.err.println(SHA:\n  sha.toString(32));BigInteger mac  new BigInteger(Coder.encryptHMAC(inputData, inputStr));System.err.println(HMAC:\n  mac.toString(16));} } 控制台输出 原文: 简单加密 BASE64加密后: 566A5Y2V5Yqg5aGBASE64解密后: 简单加密 Mac密钥: uGxdHC6ylRDaikleFtGwiMbuYUJ6mqHWyhSgF4trVkVBBSQvY/a22xU8XT1RUemdCWW155Bke pBIpkd7QHgMD5: -550b4d90349ad4629462113e7934de56 SHA: 91k9vo7p400cjkgfhjh0ia9qthsjagfn HMAC: 2287d192387e95694bdbba2fa941009a 注意 编译时可能会看到如下提示  引用 警告sun.misc.BASE64Decoder 是 Sun 的专用 API可能会在未来版本中删除 import sun.misc.BASE64Decoder;                ^ 警告sun.misc.BASE64Encoder 是 Sun 的专用 API可能会在未来版本中删除 import sun.misc.BASE64Encoder;                ^  BASE64Encoder和BASE64Decoder是非官方JDK实现类。虽然可以在JDK里能找到并使用但是在API里查不到。JRE 中 sun 和 com.sun 开头包的类都是未被文档化的他们属于 java, javax 类库的基础其中的实现大多数与底层平台有关一般来说是不推荐使用的。     BASE64的加密解密是双向的可以求反解。     MD5、SHA以及HMAC是单向加密任何数据加密后只会产生唯一的一个加密串通常用来校验数据在传输过程中是否被修改。其中HMAC算法有一个密钥增强了数据传输过程中的安全性强化了算法外的不可控因素。     单向加密的用途主要是为了校验数据在传输过程中是否被修改。     接下来我们介绍对称加密算法最常用的莫过于DES数据加密算法。 DES DES-Data Encryption Standard,即数据加密算法。是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。   DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位。 通过java代码实现如下Coder类见 import java.security.Key; import java.security.SecureRandom;import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec;/*** DES安全编码组件* * pre* 支持 DES、DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)* DES           key size must be equal to 56* DESede(TripleDES)  key size must be equal to 112 or 168* AES           key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available* Blowfish      key size must be multiple of 8, and can only range from 32 to 448 (inclusive)* RC2           key size must be between 40 and 1024 bits* RC4(ARCFOUR)  key size must be between 40 and 1024 bits* 具体内容 需要关注 JDK Document http://.../docs/technotes/guides/security/SunProviders.html* /pre* * author 梁栋* version 1.0* since 1.0*/ public abstract class DESCoder extends Coder {/*** ALGORITHM 算法 br* 可替换为以下任意一种算法同时key值的size相应改变。* * pre* DES           key size must be equal to 56* DESede(TripleDES)  key size must be equal to 112 or 168* AES           key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available* Blowfish      key size must be multiple of 8, and can only range from 32 to 448 (inclusive)* RC2           key size must be between 40 and 1024 bits* RC4(ARCFOUR)  key size must be between 40 and 1024 bits* /pre* * 在Key toKey(byte[] key)方法中使用下述代码* codeSecretKey secretKey  new SecretKeySpec(key, ALGORITHM);/code 替换* code* DESKeySpec dks  new DESKeySpec(key);* SecretKeyFactory keyFactory  SecretKeyFactory.getInstance(ALGORITHM);* SecretKey secretKey  keyFactory.generateSecret(dks);* /code*/public static final String ALGORITHM  DES;/*** 转换密钥br* * param key* return* throws Exception*/private static Key toKey(byte[] key) throws Exception {DESKeySpec dks  new DESKeySpec(key);SecretKeyFactory keyFactory  SecretKeyFactory.getInstance(ALGORITHM);SecretKey secretKey  keyFactory.generateSecret(dks);// 当使用其他对称加密算法时如AES、Blowfish等算法时用下述代码替换上述三行代码// SecretKey secretKey  new SecretKeySpec(key, ALGORITHM);return secretKey;}/*** 解密* * param data* param key* return* throws Exception*/public static byte[] decrypt(byte[] data, String key) throws Exception {Key k  toKey(decryptBASE64(key));Cipher cipher  Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, k);return cipher.doFinal(data);}/*** 加密* * param data* param key* return* throws Exception*/public static byte[] encrypt(byte[] data, String key) throws Exception {Key k  toKey(decryptBASE64(key));Cipher cipher  Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, k);return cipher.doFinal(data);}/*** 生成密钥* * return* throws Exception*/public static String initKey() throws Exception {return initKey(null);}/*** 生成密钥* * param seed* return* throws Exception*/public static String initKey(String seed) throws Exception {SecureRandom secureRandom  null;if (seed ! null) {secureRandom  new SecureRandom(decryptBASE64(seed));} else {secureRandom  new SecureRandom();}KeyGenerator kg  KeyGenerator.getInstance(ALGORITHM);kg.init(secureRandom);SecretKey secretKey  kg.generateKey();return encryptBASE64(secretKey.getEncoded());} } 延续上一个类的实现我们通过MD5以及SHA对字符串加密生成密钥这是比较常见的密钥生成方式。 再给出一个测试类 import static org.junit.Assert.*;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class DESCoderTest {Testpublic void test() throws Exception {String inputStr  DES;String key  DESCoder.initKey();System.err.println(原文:\t  inputStr);System.err.println(密钥:\t  key);byte[] inputData  inputStr.getBytes();inputData  DESCoder.encrypt(inputData, key);System.err.println(加密后:\t  DESCoder.encryptBASE64(inputData));byte[] outputData  DESCoder.decrypt(inputData, key);String outputStr  new String(outputData);System.err.println(解密后:\t  outputStr);assertEquals(inputStr, outputStr);} } 得到的输出内容如下 原文: DES 密钥: f3wEtRrV6q0加密后: C6qe9oNIzRY解密后: DES     由控制台得到的输出我们能够比对加密、解密后结果一致。这是一种简单的加密解密方式只有一个密钥。     其实DES有很多同胞兄弟如DESede(TripleDES)、AES、Blowfish、RC2、RC4(ARCFOUR)。这里就不过多阐述了大同小异只要换掉ALGORITHM换成对应的值同时做一个代码替换SecretKey secretKey new SecretKeySpec(key, ALGORITHM);就可以了此外就是密钥长度不同了。  /*** DES          key size must be equal to 56* DESede(TripleDES) key size must be equal to 112 or 168* AES          key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available* Blowfish     key size must be multiple of 8, and can only range from 32 to 448 (inclusive)* RC2          key size must be between 40 and 1024 bits* RC4(ARCFOUR) key size must be between 40 and 1024 bits**/     除了DES我们还知道有DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)等多种对称加密方式其实现方式大同小异这里介绍对称加密的另一个算法——PBE PBE     PBE——Password-based encryption基于密码加密。其特点在于口令由用户自己掌管不借助任何物理媒体采用随机数这里我们叫做盐杂凑多重加密等方法保证数据的安全性。是一种简便的加密方式。 通过java代码实现如下Coder类见  import java.security.Key; import java.util.Random;import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec;/*** PBE安全编码组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class PBECoder extends Coder {/*** 支持以下任意一种算法* * pre* PBEWithMD5AndDES * PBEWithMD5AndTripleDES * PBEWithSHA1AndDESede* PBEWithSHA1AndRC2_40* /pre*/public static final String ALGORITHM  PBEWITHMD5andDES;/*** 盐初始化* * return* throws Exception*/public static byte[] initSalt() throws Exception {byte[] salt  new byte[8];Random random  new Random();random.nextBytes(salt);return salt;}/*** 转换密钥br* * param password* return* throws Exception*/private static Key toKey(String password) throws Exception {PBEKeySpec keySpec  new PBEKeySpec(password.toCharArray());SecretKeyFactory keyFactory  SecretKeyFactory.getInstance(ALGORITHM);SecretKey secretKey  keyFactory.generateSecret(keySpec);return secretKey;}/*** 加密* * param data 数据* param password 密码* param salt  盐* return* throws Exception*/public static byte[] encrypt(byte[] data, String password, byte[] salt)throws Exception {Key key  toKey(password);PBEParameterSpec paramSpec  new PBEParameterSpec(salt, 100);Cipher cipher  Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);return cipher.doFinal(data);}/*** 解密* * param data  数据* param password 密码* param salt  盐* return* throws Exception*/public static byte[] decrypt(byte[] data, String password, byte[] salt)throws Exception {Key key  toKey(password);PBEParameterSpec paramSpec  new PBEParameterSpec(salt, 100);Cipher cipher  Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);return cipher.doFinal(data);} } 再给出一个测试类  import static org.junit.Assert.*;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class PBECoderTest {Testpublic void test() throws Exception {String inputStr  abc;System.err.println(原文:   inputStr);byte[] input  inputStr.getBytes();String pwd  efg;System.err.println(密码:   pwd);byte[] salt  PBECoder.initSalt();byte[] data  PBECoder.encrypt(input, pwd, salt);System.err.println(加密后:   PBECoder.encryptBASE64(data));byte[] output  PBECoder.decrypt(data, pwd, salt);String outputStr  new String(output);System.err.println(解密后:   outputStr);assertEquals(inputStr, outputStr);}} 控制台输出  原文: abc 密码: efg 加密后: iCZ0uRtaAhE解密后: abc     后续我们会介绍非对称加密算法如RSA、DSA、DH、ECC等。      接下来我们介绍典型的非对称加密算法——RSA RSA     这种算法1978年就出现了它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作也很流行。算法的名字以发明者的名字命名Ron Rivest, AdiShamir 和Leonard Adleman。     这种加密算法的特点主要是密钥的变化上文我们看到DES只有一个密钥。相当于只有一把钥匙如果这把钥匙丢了数据也就不安全了。RSA同时有两把钥匙公钥与私钥。同时支持数字签名。数字签名的意义在于对传输过来的数据进行校验。确保数据在传输工程中不被修改。 流程分析  甲方构建密钥对儿将公钥公布给乙方将私钥保留。甲方使用私钥加密数据然后用私钥对加密后的数据签名发送给乙方签名以及加密后的数据乙方使用公钥、签名来验证待解密数据是否有效如果有效使用公钥对数据解密。乙方使用公钥加密数据向甲方发送经过加密后的数据甲方获得加密数据通过私钥解密。按如上步骤给出序列图如下  通过java代码实现如下Coder类见 import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;import java.util.HashMap; import java.util.Map;import javax.crypto.Cipher;/*** RSA安全编码组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class RSACoder extends Coder {public static final String KEY_ALGORITHM  RSA;public static final String SIGNATURE_ALGORITHM  MD5withRSA;private static final String PUBLIC_KEY  RSAPublicKey;private static final String PRIVATE_KEY  RSAPrivateKey;/*** 用私钥对信息生成数字签名* * param data*            加密数据* param privateKey*            私钥* * return* throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes  decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec  new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory  KeyFactory.getInstance(KEY_ALGORITHM);// 取私钥匙对象PrivateKey priKey  keyFactory.generatePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名Signature signature  Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(priKey);signature.update(data);return encryptBASE64(signature.sign());}/*** 校验数字签名* * param data*            加密数据* param publicKey*            公钥* param sign*            数字签名* * return 校验成功返回true 失败返回false* throws Exception* */public static boolean verify(byte[] data, String publicKey, String sign)throws Exception {// 解密由base64编码的公钥byte[] keyBytes  decryptBASE64(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec  new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory  KeyFactory.getInstance(KEY_ALGORITHM);// 取公钥匙对象PublicKey pubKey  keyFactory.generatePublic(keySpec);Signature signature  Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常return signature.verify(decryptBASE64(sign));}/*** 解密br* 用私钥解密* * param data* param key* return* throws Exception*/public static byte[] decryptByPrivateKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes  decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec  new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory  KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey  keyFactory.generatePrivate(pkcs8KeySpec);// 对数据解密Cipher cipher  Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 解密br* 用私钥解密* * param data* param key* return* throws Exception*/public static byte[] decryptByPublicKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes  decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec  new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory  KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey  keyFactory.generatePublic(x509KeySpec);// 对数据解密Cipher cipher  Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 加密br* 用公钥加密* * param data* param key* return* throws Exception*/public static byte[] encryptByPublicKey(byte[] data, String key)throws Exception {// 对公钥解密byte[] keyBytes  decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec  new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory  KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey  keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher  Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 加密br* 用私钥加密* * param data* param key* return* throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes  decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec  new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory  KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey  keyFactory.generatePrivate(pkcs8KeySpec);// 对数据加密Cipher cipher  Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 取得私钥* * param keyMap* return* throws Exception*/public static String getPrivateKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PRIVATE_KEY);return encryptBASE64(key.getEncoded());}/*** 取得公钥* * param keyMap* return* throws Exception*/public static String getPublicKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PUBLIC_KEY);return encryptBASE64(key.getEncoded());}/*** 初始化密钥* * return* throws Exception*/public static MapString, Object initKey() throws Exception {KeyPairGenerator keyPairGen  KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(1024);KeyPair keyPair  keyPairGen.generateKeyPair();// 公钥RSAPublicKey publicKey  (RSAPublicKey) keyPair.getPublic();// 私钥RSAPrivateKey privateKey  (RSAPrivateKey) keyPair.getPrivate();MapString, Object keyMap  new HashMapString, Object(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;} } 再给出一个测试类 import static org.junit.Assert.*;import org.junit.Before; import org.junit.Test;import java.util.Map;/*** * author 梁栋* version 1.0* since 1.0*/ public class RSACoderTest {private String publicKey;private String privateKey;Beforepublic void setUp() throws Exception {MapString, Object keyMap  RSACoder.initKey();publicKey  RSACoder.getPublicKey(keyMap);privateKey  RSACoder.getPrivateKey(keyMap);System.err.println(公钥: \n\r  publicKey);System.err.println(私钥 \n\r  privateKey);}Testpublic void test() throws Exception {System.err.println(公钥加密——私钥解密);String inputStr  abc;byte[] data  inputStr.getBytes();byte[] encodedData  RSACoder.encryptByPublicKey(data, publicKey);byte[] decodedData  RSACoder.decryptByPrivateKey(encodedData,privateKey);String outputStr  new String(decodedData);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);assertEquals(inputStr, outputStr);}Testpublic void testSign() throws Exception {System.err.println(私钥加密——公钥解密);String inputStr  sign;byte[] data  inputStr.getBytes();byte[] encodedData  RSACoder.encryptByPrivateKey(data, privateKey);byte[] decodedData  RSACoder.decryptByPublicKey(encodedData, publicKey);String outputStr  new String(decodedData);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);assertEquals(inputStr, outputStr);System.err.println(私钥签名——公钥验证签名);// 产生签名String sign  RSACoder.sign(encodedData, privateKey);System.err.println(签名:\r  sign);// 验证签名boolean status  RSACoder.verify(encodedData, publicKey, sign);System.err.println(状态:\r  status);assertTrue(status);}} 控制台输出 公钥: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/I0z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvXbBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm 1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVzo6FbAZCyHBd7wIDAQAB私钥 MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3 GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV /MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU9tyumJakDKodQ3Jf2zQtNr5ZdEPl uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnuyBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4dxCWn0/1FrkWl2G329Ucewm3 QU9CKu4D7KqdjHa3lXP8F0Etaaapi7EfkRUpukn2ItZV/AkEAlkI0iphxT1rCB0Q5CjWDY5S Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpPHEBj1nStMH9u2/IGEwJA fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01X nfpFpBJ2dw公钥加密——私钥解密 加密前: abc解密后: abc 公钥: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF 9rwbuEh3iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB私钥 MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4TL9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr mbJro4JeFIJ3CiVDpXR9FluIgI4SXm7ioGKF2NOMA9LR5Fu82WpLfpTN2y2SaLYWEDZyp53BxY j9gUxaxi1MQsC1ZgDF2xmECQQDy70bQntbRfysPppCtd56YRnES1Tyekw0wryS2trivQJl7JF gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPNaOsWymaRh 9jA/Wc0wp29SbGTh5CcMuGpXm1g0MFKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW 9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5tUV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Cov5WzLMpzJBYXK6PAtqIhxbuPEc2 I2k1Afmrwyw私钥加密——公钥解密 加密前: sign解密后: sign 私钥签名——公钥验证签名 签名: ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIKd20FCkHCqh9djP3h94iWnIUY0ifU mbJkhAl/i5krExOE0hknOnPMcEPlZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn i3wwbYWs9wSzIf0UjlM状态: true     简要总结一下使用公钥加密、私钥解密完成了乙方到甲方的一次数据传递通过私钥加密、公钥解密同时通过私钥签名、公钥验证签名完成了一次甲方到乙方的数据传递与验证两次数据传递完成一整套的数据交互 类似数字签名数字信封是这样描述的 数字信封   数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。 流程     信息发送方采用对称密钥来加密信息然后再用接收方的公钥来加密此对称密钥这部分称为数字信封再将它和信息一起发送给接收方接收方先用相应的私钥打开数字信封得到对称密钥然后使用对称密钥再解开信息。     接下来我们分析DH加密算法一种适基于密钥一致协议的加密算法。 DH Diffie-Hellman算法(D-H算法)密钥一致协议。是由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成一致的、可以共享的密钥。换句话说就是由甲方产出一对密钥公钥、私钥乙方依照甲方公钥产生乙方密钥对公钥、私钥。以此为基线作为数据传输保密基础同时双方使用同一种对称加密算法构建本地密钥SecretKey对数据加密。这样在互通了本地密钥SecretKey算法后甲乙双方公开自己的公钥使用对方的公钥和刚才产生的私钥加密数据同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方可以扩展为多方共享数据通讯这样就完成了网络交互数据的安全通讯该算法源于中国的同余定理——中国馀数定理。  流程分析 1.甲方构建密钥对儿将公钥公布给乙方将私钥保留双方约定数据加密算法乙方通过甲方公钥构建密钥对儿将公钥公布给甲方将私钥保留。 2.甲方使用私钥、乙方公钥、约定数据加密算法构建本地密钥然后通过本地密钥加密数据发送给乙方加密后的数据乙方使用私钥、甲方公钥、约定数据加密算法构建本地密钥然后通过本地密钥对数据解密。 3.乙方使用私钥、甲方公钥、约定数据加密算法构建本地密钥然后通过本地密钥加密数据发送给甲方加密后的数据甲方使用私钥、乙方公钥、约定数据加密算法构建本地密钥然后通过本地密钥对数据解密。  通过java代码实现如下Coder类见 import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map;import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import javax.crypto.interfaces.DHPrivateKey; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec;/*** DH安全编码组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class DHCoder extends Coder {public static final String ALGORITHM  DH;/*** 默认密钥字节数* * pre* DH* Default Keysize 1024  * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).* /pre*/private static final int KEY_SIZE  1024;/*** DH加密下需要一种对称加密算法对数据加密这里我们使用DES也可以使用其他对称加密算法。*/public static final String SECRET_ALGORITHM  DES;private static final String PUBLIC_KEY  DHPublicKey;private static final String PRIVATE_KEY  DHPrivateKey;/*** 初始化甲方密钥* * return* throws Exception*/public static MapString, Object initKey() throws Exception {KeyPairGenerator keyPairGenerator  KeyPairGenerator.getInstance(ALGORITHM);keyPairGenerator.initialize(KEY_SIZE);KeyPair keyPair  keyPairGenerator.generateKeyPair();// 甲方公钥DHPublicKey publicKey  (DHPublicKey) keyPair.getPublic();// 甲方私钥DHPrivateKey privateKey  (DHPrivateKey) keyPair.getPrivate();MapString, Object keyMap  new HashMapString, Object(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}/*** 初始化乙方密钥* * param key*            甲方公钥* return* throws Exception*/public static MapString, Object initKey(String key) throws Exception {// 解析甲方公钥byte[] keyBytes  decryptBASE64(key);X509EncodedKeySpec x509KeySpec  new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory  KeyFactory.getInstance(ALGORITHM);PublicKey pubKey  keyFactory.generatePublic(x509KeySpec);// 由甲方公钥构建乙方密钥DHParameterSpec dhParamSpec  ((DHPublicKey) pubKey).getParams();KeyPairGenerator keyPairGenerator  KeyPairGenerator.getInstance(keyFactory.getAlgorithm());keyPairGenerator.initialize(dhParamSpec);KeyPair keyPair  keyPairGenerator.generateKeyPair();// 乙方公钥DHPublicKey publicKey  (DHPublicKey) keyPair.getPublic();// 乙方私钥DHPrivateKey privateKey  (DHPrivateKey) keyPair.getPrivate();MapString, Object keyMap  new HashMapString, Object(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}/*** 加密br* * param data*            待加密数据* param publicKey*            甲方公钥* param privateKey*            乙方私钥* return* throws Exception*/public static byte[] encrypt(byte[] data, String publicKey,String privateKey) throws Exception {// 生成本地密钥SecretKey secretKey  getSecretKey(publicKey, privateKey);// 数据加密Cipher cipher  Cipher.getInstance(secretKey.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, secretKey);return cipher.doFinal(data);}/*** 解密br* * param data*            待解密数据* param publicKey*            乙方公钥* param privateKey*            乙方私钥* return* throws Exception*/public static byte[] decrypt(byte[] data, String publicKey,String privateKey) throws Exception {// 生成本地密钥SecretKey secretKey  getSecretKey(publicKey, privateKey);// 数据解密Cipher cipher  Cipher.getInstance(secretKey.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, secretKey);return cipher.doFinal(data);}/*** 构建密钥* * param publicKey*            公钥* param privateKey*            私钥* return* throws Exception*/private static SecretKey getSecretKey(String publicKey, String privateKey)throws Exception {// 初始化公钥byte[] pubKeyBytes  decryptBASE64(publicKey);KeyFactory keyFactory  KeyFactory.getInstance(ALGORITHM);X509EncodedKeySpec x509KeySpec  new X509EncodedKeySpec(pubKeyBytes);PublicKey pubKey  keyFactory.generatePublic(x509KeySpec);// 初始化私钥byte[] priKeyBytes  decryptBASE64(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec  new PKCS8EncodedKeySpec(priKeyBytes);Key priKey  keyFactory.generatePrivate(pkcs8KeySpec);KeyAgreement keyAgree  KeyAgreement.getInstance(keyFactory.getAlgorithm());keyAgree.init(priKey);keyAgree.doPhase(pubKey, true);// 生成本地密钥SecretKey secretKey  keyAgree.generateSecret(SECRET_ALGORITHM);return secretKey;}/*** 取得私钥* * param keyMap* return* throws Exception*/public static String getPrivateKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PRIVATE_KEY);return encryptBASE64(key.getEncoded());}/*** 取得公钥* * param keyMap* return* throws Exception*/public static String getPublicKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PUBLIC_KEY);return encryptBASE64(key.getEncoded());} } 再给出一个测试类 import static org.junit.Assert.*;import java.util.Map;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class DHCoderTest {Testpublic void test() throws Exception {// 生成甲方密钥对儿MapString, Object aKeyMap  DHCoder.initKey();String aPublicKey  DHCoder.getPublicKey(aKeyMap);String aPrivateKey  DHCoder.getPrivateKey(aKeyMap);System.err.println(甲方公钥:\r  aPublicKey);System.err.println(甲方私钥:\r  aPrivateKey);// 由甲方公钥产生本地密钥对儿MapString, Object bKeyMap  DHCoder.initKey(aPublicKey);String bPublicKey  DHCoder.getPublicKey(bKeyMap);String bPrivateKey  DHCoder.getPrivateKey(bKeyMap);System.err.println(乙方公钥:\r  bPublicKey);System.err.println(乙方私钥:\r  bPrivateKey);String aInput  abc ;System.err.println(原文:   aInput);// 由甲方公钥乙方私钥构建密文byte[] aCode  DHCoder.encrypt(aInput.getBytes(), aPublicKey,bPrivateKey);// 由乙方公钥甲方私钥解密byte[] aDecode  DHCoder.decrypt(aCode, bPublicKey, aPrivateKey);String aOutput  (new String(aDecode));System.err.println(解密:   aOutput);assertEquals(aInput, aOutput);System.err.println( 反过来加密解密 );String bInput  def ;System.err.println(原文:   bInput);// 由乙方公钥甲方私钥构建密文byte[] bCode  DHCoder.encrypt(bInput.getBytes(), bPublicKey,aPrivateKey);// 由甲方公钥乙方私钥解密byte[] bDecode  DHCoder.decrypt(bCode, aPublicKey, bPrivateKey);String bOutput  (new String(bDecode));System.err.println(解密:   bOutput);assertEquals(bInput, bOutput);}} 控制台输出 甲方公钥: MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblCeUykAgIBgANDAAJAdAWBVmIzqcko Ej6qFjLDL2Y3FPq1iRbnOyOpDj71yKaK1KFhTv04B0zy4DKcvAASV7/Gv0WbgqdmffRkqrQ甲方私钥: MIHRAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblCeUykAgIBgAQyAjACJRfy1LyR eHyD4HfbxR0uoIGR1oL9i9Nk6g2AAuaDPgEVWHnQXID13yL/uDos乙方公钥: MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblCeUykAgIBgANDAAJAVEYSfBAI9nr dWw3OBv475CeBrWBBYqt0m6/eu4ptuDQHwV4MmUtKAC2wc2nNrdb1wmBhY1X8RnWkJ1XmdDbQ乙方私钥: MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblCeUykAgIBgAQzAjEAqaZiCdXp 2iNpdBlHRaO9ir70wo2n32xNlIzIX19VLSPCDdeUWkgRv4CEj/8k/yd原文: abc  解密: abc 反过来加密解密  原文: def  解密: def 如我所言甲乙双方在获得对方公钥后可以对发送给对方的数据加密同时也能对接收到的数据解密达到了数据安全通信的目的     接下来我们介绍DSA数字签名非对称加密的另一种实现。 DSA DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种被美国NIST作为DSS(DigitalSignature Standard)。简单的说这是一种更高级的验证方式用作数字签名。不单单只有公钥、私钥还有数字签名。私钥加密生成数字签名公钥验证数据及签名。如果数据和签名不匹配则认为验证失败数字签名的作用就是校验数据在传输过程中不被修改。数字签名是单向加密的升级  通过java代码实现如下Coder类见 import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map;/*** DSA安全编码组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class DSACoder extends Coder {public static final String ALGORITHM  DSA;/*** 默认密钥字节数* * pre* DSA * Default Keysize 1024  * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).* /pre*/private static final int KEY_SIZE  1024;/*** 默认种子*/private static final String DEFAULT_SEED  0f22507a10bbddd07d8a3082122966e3;private static final String PUBLIC_KEY  DSAPublicKey;private static final String PRIVATE_KEY  DSAPrivateKey;/*** 用私钥对信息生成数字签名* * param data*            加密数据* param privateKey*            私钥* * return* throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes  decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec  new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory  KeyFactory.getInstance(ALGORITHM);// 取私钥匙对象PrivateKey priKey  keyFactory.generatePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名Signature signature  Signature.getInstance(keyFactory.getAlgorithm());signature.initSign(priKey);signature.update(data);return encryptBASE64(signature.sign());}/*** 校验数字签名* * param data*            加密数据* param publicKey*            公钥* param sign*            数字签名* * return 校验成功返回true 失败返回false* throws Exception* */public static boolean verify(byte[] data, String publicKey, String sign)throws Exception {// 解密由base64编码的公钥byte[] keyBytes  decryptBASE64(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec  new X509EncodedKeySpec(keyBytes);// ALGORITHM 指定的加密算法KeyFactory keyFactory  KeyFactory.getInstance(ALGORITHM);// 取公钥匙对象PublicKey pubKey  keyFactory.generatePublic(keySpec);Signature signature  Signature.getInstance(keyFactory.getAlgorithm());signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常return signature.verify(decryptBASE64(sign));}/*** 生成密钥* * param seed*            种子* return 密钥对象* throws Exception*/public static MapString, Object initKey(String seed) throws Exception {KeyPairGenerator keygen  KeyPairGenerator.getInstance(ALGORITHM);// 初始化随机产生器SecureRandom secureRandom  new SecureRandom();secureRandom.setSeed(seed.getBytes());keygen.initialize(KEY_SIZE, secureRandom);KeyPair keys  keygen.genKeyPair();DSAPublicKey publicKey  (DSAPublicKey) keys.getPublic();DSAPrivateKey privateKey  (DSAPrivateKey) keys.getPrivate();MapString, Object map  new HashMapString, Object(2);map.put(PUBLIC_KEY, publicKey);map.put(PRIVATE_KEY, privateKey);return map;}/*** 默认生成密钥* * return 密钥对象* throws Exception*/public static MapString, Object initKey() throws Exception {return initKey(DEFAULT_SEED);}/*** 取得私钥* * param keyMap* return* throws Exception*/public static String getPrivateKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PRIVATE_KEY);return encryptBASE64(key.getEncoded());}/*** 取得公钥* * param keyMap* return* throws Exception*/public static String getPublicKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PUBLIC_KEY);return encryptBASE64(key.getEncoded());} } 再给出一个测试类 import static org.junit.Assert.*;import java.util.Map;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class DSACoderTest {Testpublic void test() throws Exception {String inputStr  abc;byte[] data  inputStr.getBytes();// 构建密钥MapString, Object keyMap  DSACoder.initKey();// 获得密钥String publicKey  DSACoder.getPublicKey(keyMap);String privateKey  DSACoder.getPrivateKey(keyMap);System.err.println(公钥:\r  publicKey);System.err.println(私钥:\r  privateKey);// 产生签名String sign  DSACoder.sign(data, privateKey);System.err.println(签名:\r  sign);// 验证签名boolean status  DSACoder.verify(data, publicKey, sign);System.err.println(状态:\r  status);assertTrue(status);}} 控制台输出 公钥: MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJf6AR7ECLCT7up1/63xhv4O1fn xqimFQ8E4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE C/BYHPUCgYEA9GghdabPd7LvKtcNrhXuXmUr7v6OuqCVdMCz0HgmdRWVeOutRZTZxBxCBgLRJ FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx2J6ASQ7zKTxvqhRkImo g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY3uySVnp0TULSv 5T4VaHoKzsLHgGTrwOvsGAV3yCNl2WDu3D84bSLF7liTWgOjSMOEaPk4VyRTlLXZWGPsf1Mfd9 21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrComv7efstMM0PGo私钥: MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2 USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJf6AR7ECLCT7up1/63xhv4 O1fnxqimFQ8E4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC ouuEC/BYHPUCgYEA9GghdabPd7LvKtcNrhXuXmUr7v6OuqCVdMCz0HgmdRWVeOutRZTZxBxCB gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx2J6ASQ7zKTxvqhR kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q签名: MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNahHtbU6NcQfy8Ac6LeLQs状态: true 注意状态为true就验证成功 ECC ECC-Elliptic Curves Cryptography椭圆曲线密码编码学是目前已知的公钥体制中对每比特所提供加密强度最高的一种体制。在软件注册保护方面起到很大的作用一般的序列号通常由该算法产生。     当我开始整理《Java加密技术二》的时候我就已经在开始研究ECC了但是关于Java实现ECC算法的资料实在是太少了无论是国内还是国外的资料无论是官方还是非官方的解释最终只有一种答案——ECC算法在jdk1.5后加入支持目前仅仅只能完成密钥的生成与解析。 如果想要获得ECC算法实现需要调用硬件完成加密/解密ECC算法相当耗费资源如果单纯使用CPU进行加密/解密效率低下涉及到Java Card领域PKCS#11。 其实PKCS#11配置很简单但缺乏硬件设备无法尝试     尽管如此我照旧提供相应的Java实现代码以供大家参考。 通过java代码实现如下Coder类见 import java.math.BigInteger; import java.security.Key; import java.security.KeyFactory; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.ECFieldF2m; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; import java.security.spec.EllipticCurve; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map;import javax.crypto.Cipher; import javax.crypto.NullCipher;import sun.security.ec.ECKeyFactory; import sun.security.ec.ECPrivateKeyImpl; import sun.security.ec.ECPublicKeyImpl;/*** ECC安全编码组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class ECCCoder extends Coder {public static final String ALGORITHM  EC;private static final String PUBLIC_KEY  ECCPublicKey;private static final String PRIVATE_KEY  ECCPrivateKey;/*** 解密br* 用私钥解密* * param data* param key* return* throws Exception*/public static byte[] decrypt(byte[] data, String key) throws Exception {// 对密钥解密byte[] keyBytes  decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec  new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory  ECKeyFactory.INSTANCE;ECPrivateKey priKey  (ECPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);ECPrivateKeySpec ecPrivateKeySpec  new ECPrivateKeySpec(priKey.getS(),priKey.getParams());// 对数据解密// TODO Chipher不支持EC算法 未能实现Cipher cipher  new NullCipher();// Cipher.getInstance(ALGORITHM, keyFactory.getProvider());cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams());return cipher.doFinal(data);}/*** 加密br* 用公钥加密* * param data* param privateKey* return* throws Exception*/public static byte[] encrypt(byte[] data, String privateKey)throws Exception {// 对公钥解密byte[] keyBytes  decryptBASE64(privateKey);// 取得公钥X509EncodedKeySpec x509KeySpec  new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory  ECKeyFactory.INSTANCE;ECPublicKey pubKey  (ECPublicKey) keyFactory.generatePublic(x509KeySpec);ECPublicKeySpec ecPublicKeySpec  new ECPublicKeySpec(pubKey.getW(),pubKey.getParams());// 对数据加密// TODO Chipher不支持EC算法 未能实现Cipher cipher  new NullCipher();// Cipher.getInstance(ALGORITHM, keyFactory.getProvider());cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams());return cipher.doFinal(data);}/*** 取得私钥* * param keyMap* return* throws Exception*/public static String getPrivateKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PRIVATE_KEY);return encryptBASE64(key.getEncoded());}/*** 取得公钥* * param keyMap* return* throws Exception*/public static String getPublicKey(MapString, Object keyMap)throws Exception {Key key  (Key) keyMap.get(PUBLIC_KEY);return encryptBASE64(key.getEncoded());}/*** 初始化密钥* * return* throws Exception*/public static MapString, Object initKey() throws Exception {BigInteger x1  new BigInteger(2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8, 16);BigInteger x2  new BigInteger(289070fb05d38ff58321f2e800536d538ccdaa3d9, 16);ECPoint g  new ECPoint(x1, x2);// the order of generatorBigInteger n  new BigInteger(5846006549323611672814741753598448348329118574063, 10);// the cofactorint h  2;int m  163;int[] ks  { 7, 6, 3 };ECFieldF2m ecField  new ECFieldF2m(m, ks);// y^2xyx^3x^21BigInteger a  new BigInteger(1, 2);BigInteger b  new BigInteger(1, 2);EllipticCurve ellipticCurve  new EllipticCurve(ecField, a, b);ECParameterSpec ecParameterSpec  new ECParameterSpec(ellipticCurve, g,n, h);// 公钥ECPublicKey publicKey  new ECPublicKeyImpl(g, ecParameterSpec);BigInteger s  new BigInteger(1234006549323611672814741753598448348329118574063, 10);// 私钥ECPrivateKey privateKey  new ECPrivateKeyImpl(s, ecParameterSpec);MapString, Object keyMap  new HashMapString, Object(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}}     请注意上述代码中的TODO内容再次提醒注意Chipher不支持EC算法 以上代码仅供参考。Chipher、Signature、KeyPairGenerator、KeyAgreement、SecretKey均不支持EC算法。为了确保程序能够正常执行我们使用了NullCipher类验证程序。照旧提供一个测试类 import static org.junit.Assert.*;import java.math.BigInteger; import java.security.spec.ECFieldF2m; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; import java.security.spec.EllipticCurve; import java.util.Map;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class ECCCoderTest {Testpublic void test() throws Exception {String inputStr  abc;byte[] data  inputStr.getBytes();MapString, Object keyMap  ECCCoder.initKey();String publicKey  ECCCoder.getPublicKey(keyMap);String privateKey  ECCCoder.getPrivateKey(keyMap);System.err.println(公钥: \n  publicKey);System.err.println(私钥 \n  privateKey);byte[] encodedData  ECCCoder.encrypt(data, publicKey);byte[] decodedData  ECCCoder.decrypt(encodedData, privateKey);String outputStr  new String(decodedData);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);assertEquals(inputStr, outputStr);} } 控制台输出 公钥:  MEAwEAYHKoZIzj0CAQYFK4EEAAEDLAAEAv4TwFN7vBGsqgfXk95ObV5clO7oAokHD7BdOP9YMh8u gAU21TjM2qPZ私钥  MDICAQAwEAYHKoZIzj0CAQYFK4EEAAEEGzAZAgEBBBTYJsR3BN7TFw7JHcAHFkwNmfil7w加密前: abc解密后: abc     本篇的主要内容为Java证书体系的实现。 在构建Java代码实现前我们需要完成证书的制作。 1.生成keyStroe文件 在命令行下执行以下命令 keytool -genkey -validity 36000 -alias www.zlex.org -keyalg RSA -keystore d:\zlex.keystore 其中 -genkey表示生成密钥 -validity指定证书有效期这里是36000天 -alias指定别名这里是www.zlex.org -keyalg指定算法这里是RSA -keystore指定存储位置这里是d:\zlex.keystore 在这里我使用的密码为 123456 控制台输出 输入keystore密码 再次输入新密码: 您的名字与姓氏是什么[Unknown]  www.zlex.org 您的组织单位名称是什么[Unknown]  zlex 您的组织名称是什么[Unknown]  zlex 您所在的城市或区域名称是什么[Unknown]  BJ 您所在的州或省份名称是什么[Unknown]  BJ 该单位的两字母国家代码是什么[Unknown]  CN CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN 正确吗[否]  Y输入tomcat的主密码如果和 keystore 密码相同按回车 再次输入新密码: 这时在D盘下会生成一个zlex.keystore的文件。 2.生成自签名证书 光有keyStore文件是不够的还需要证书文件证书才是直接提供给外界使用的公钥凭证。 导出证书 keytool -export -keystore d:\zlex.keystore -alias www.zlex.org -file d:\zlex.cer -rfc 其中 -export指定为导出操作 -keystore指定keystore文件 -alias指定导出keystore文件中的别名 -file指向导出路径 -rfc以文本格式输出也就是以BASE64编码输出 这里的密码是 123456 控制台输出 输入keystore密码 保存在文件中的认证 d:\zlex.cer 当然使用方是需要导入证书的 可以通过自签名证书完成CAS单点登录系统的构建 Ok准备工作完成开始Java实现 通过java代码实现如下Coder类见 import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Date;import javax.crypto.Cipher;/*** 证书组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class CertificateCoder extends Coder {/*** Java密钥库(Java Key StoreJKS)KEY_STORE*/public static final String KEY_STORE  JKS;public static final String X509  X.509;/*** 由KeyStore获得私钥* * param keyStorePath* param alias* param password* return* throws Exception*/private static PrivateKey getPrivateKey(String keyStorePath, String alias,String password) throws Exception {KeyStore ks  getKeyStore(keyStorePath, password);PrivateKey key  (PrivateKey) ks.getKey(alias, password.toCharArray());return key;}/*** 由Certificate获得公钥* * param certificatePath* return* throws Exception*/private static PublicKey getPublicKey(String certificatePath)throws Exception {Certificate certificate  getCertificate(certificatePath);PublicKey key  certificate.getPublicKey();return key;}/*** 获得Certificate* * param certificatePath* return* throws Exception*/private static Certificate getCertificate(String certificatePath)throws Exception {CertificateFactory certificateFactory  CertificateFactory.getInstance(X509);FileInputStream in  new FileInputStream(certificatePath);Certificate certificate  certificateFactory.generateCertificate(in);in.close();return certificate;}/*** 获得Certificate* * param keyStorePath* param alias* param password* return* throws Exception*/private static Certificate getCertificate(String keyStorePath,String alias, String password) throws Exception {KeyStore ks  getKeyStore(keyStorePath, password);Certificate certificate  ks.getCertificate(alias);return certificate;}/*** 获得KeyStore* * param keyStorePath* param password* return* throws Exception*/private static KeyStore getKeyStore(String keyStorePath, String password)throws Exception {FileInputStream is  new FileInputStream(keyStorePath);KeyStore ks  KeyStore.getInstance(KEY_STORE);ks.load(is, password.toCharArray());is.close();return ks;}/*** 私钥加密* * param data* param keyStorePath* param alias* param password* return* throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath,String alias, String password) throws Exception {// 取得私钥PrivateKey privateKey  getPrivateKey(keyStorePath, alias, password);// 对数据加密Cipher cipher  Cipher.getInstance(privateKey.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 私钥解密* * param data* param keyStorePath* param alias* param password* return* throws Exception*/public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath,String alias, String password) throws Exception {// 取得私钥PrivateKey privateKey  getPrivateKey(keyStorePath, alias, password);// 对数据加密Cipher cipher  Cipher.getInstance(privateKey.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 公钥加密* * param data* param certificatePath* return* throws Exception*/public static byte[] encryptByPublicKey(byte[] data, String certificatePath)throws Exception {// 取得公钥PublicKey publicKey  getPublicKey(certificatePath);// 对数据加密Cipher cipher  Cipher.getInstance(publicKey.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 公钥解密* * param data* param certificatePath* return* throws Exception*/public static byte[] decryptByPublicKey(byte[] data, String certificatePath)throws Exception {// 取得公钥PublicKey publicKey  getPublicKey(certificatePath);// 对数据加密Cipher cipher  Cipher.getInstance(publicKey.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 验证Certificate* * param certificatePath* return*/public static boolean verifyCertificate(String certificatePath) {return verifyCertificate(new Date(), certificatePath);}/*** 验证Certificate是否过期或无效* * param date* param certificatePath* return*/public static boolean verifyCertificate(Date date, String certificatePath) {boolean status  true;try {// 取得证书Certificate certificate  getCertificate(certificatePath);// 验证证书是否过期或无效status  verifyCertificate(date, certificate);} catch (Exception e) {status  false;}return status;}/*** 验证证书是否过期或无效* * param date* param certificate* return*/private static boolean verifyCertificate(Date date, Certificate certificate) {boolean status  true;try {X509Certificate x509Certificate  (X509Certificate) certificate;x509Certificate.checkValidity(date);} catch (Exception e) {status  false;}return status;}/*** 签名* * param keyStorePath* param alias* param password* * return* throws Exception*/public static String sign(byte[] sign, String keyStorePath, String alias,String password) throws Exception {// 获得证书X509Certificate x509Certificate  (X509Certificate) getCertificate(keyStorePath, alias, password);// 获取私钥KeyStore ks  getKeyStore(keyStorePath, password);// 取得私钥PrivateKey privateKey  (PrivateKey) ks.getKey(alias, password.toCharArray());// 构建签名Signature signature  Signature.getInstance(x509Certificate.getSigAlgName());signature.initSign(privateKey);signature.update(sign);return encryptBASE64(signature.sign());}/*** 验证签名* * param data* param sign* param certificatePath* return* throws Exception*/public static boolean verify(byte[] data, String sign,String certificatePath) throws Exception {// 获得证书X509Certificate x509Certificate  (X509Certificate) getCertificate(certificatePath);// 获得公钥PublicKey publicKey  x509Certificate.getPublicKey();// 构建签名Signature signature  Signature.getInstance(x509Certificate.getSigAlgName());signature.initVerify(publicKey);signature.update(data);return signature.verify(decryptBASE64(sign));}/*** 验证Certificate* * param keyStorePath* param alias* param password* return*/public static boolean verifyCertificate(Date date, String keyStorePath,String alias, String password) {boolean status  true;try {Certificate certificate  getCertificate(keyStorePath, alias,password);status  verifyCertificate(date, certificate);} catch (Exception e) {status  false;}return status;}/*** 验证Certificate* * param keyStorePath* param alias* param password* return*/public static boolean verifyCertificate(String keyStorePath, String alias,String password) {return verifyCertificate(new Date(), keyStorePath, alias, password);} } 再给出一个测试类 import static org.junit.Assert.*;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class CertificateCoderTest {private String password  123456;private String alias  www.zlex.org;private String certificatePath  d:/zlex.cer;private String keyStorePath  d:/zlex.keystore;Testpublic void test() throws Exception {System.err.println(公钥加密——私钥解密);String inputStr  Ceritifcate;byte[] data  inputStr.getBytes();byte[] encrypt  CertificateCoder.encryptByPublicKey(data,certificatePath);byte[] decrypt  CertificateCoder.decryptByPrivateKey(encrypt,keyStorePath, alias, password);String outputStr  new String(decrypt);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);// 验证数据一致assertArrayEquals(data, decrypt);// 验证证书有效assertTrue(CertificateCoder.verifyCertificate(certificatePath));}Testpublic void testSign() throws Exception {System.err.println(私钥加密——公钥解密);String inputStr  sign;byte[] data  inputStr.getBytes();byte[] encodedData  CertificateCoder.encryptByPrivateKey(data,keyStorePath, alias, password);byte[] decodedData  CertificateCoder.decryptByPublicKey(encodedData,certificatePath);String outputStr  new String(decodedData);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);assertEquals(inputStr, outputStr);System.err.println(私钥签名——公钥验证签名);// 产生签名String sign  CertificateCoder.sign(encodedData, keyStorePath, alias,password);System.err.println(签名:\r  sign);// 验证签名boolean status  CertificateCoder.verify(encodedData, sign,certificatePath);System.err.println(状态:\r  status);assertTrue(status);} } 控制台输出 公钥加密——私钥解密 加密前: Ceritificate解密后: Ceritificate私钥加密——公钥解密 加密前: sign解密后: sign 私钥签名——公钥验证签名 签名: pqBn5m6PJlfOjH0A6U2o2mUmBsfgyEY1NWCbiyA/I5Gc3gaVNVIdj/zkGNZRqTjhf3J9a9z9EI7 6F2eWYd7punHx5oh6hfNgcKbVb52EfItl4QENdjbXiPynn07Lbg1NOjULnpEd6ZhLP1YwrEAuM OfvX0e7/wplxLbySaKQ状态: true 由此完成了证书验证体系 同样我们可以对代码做签名——代码签名 通过工具JarSigner可以完成代码签名。 这里我们对tools.jar做代码签名命令如下 jarsigner -storetype jks -keystore zlex.keystore -verbose tools.jar www.zlex.org 控制台输出 输入密钥库的口令短语正在更新 META-INF/WWW_ZLEX.SF正在更新 META-INF/WWW_ZLEX.RSA正在签名 org/zlex/security/Security.class正在签名 org/zlex/tool/Main$1.class正在签名 org/zlex/tool/Main$2.class正在签名 org/zlex/tool/Main.class警告 签名者证书将在六个月内过期。 此时我们可以对签名后的jar做验证 验证tools.jar命令如下 jarsigner -verify -verbose -certs tools.jar 控制台输出          402 Sat Jun 20 16:25:14 CST 2009 META-INF/MANIFEST.MF532 Sat Jun 20 16:25:14 CST 2009 META-INF/WWW_ZLEX.SF889 Sat Jun 20 16:25:14 CST 2009 META-INF/WWW_ZLEX.RSA sm       590 Wed Dec 10 13:03:42 CST 2008 org/zlex/security/Security.classX.509, CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN[证书将在 09-9-18 下午3:27 到期]sm       705 Tue Dec 16 18:00:56 CST 2008 org/zlex/tool/Main$1.classX.509, CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN[证书将在 09-9-18 下午3:27 到期]sm       779 Tue Dec 16 18:00:56 CST 2008 org/zlex/tool/Main$2.classX.509, CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN[证书将在 09-9-18 下午3:27 到期]sm     12672 Tue Dec 16 18:00:56 CST 2008 org/zlex/tool/Main.classX.509, CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN[证书将在 09-9-18 下午3:27 到期]s  已验证签名m  在清单中列出条目k  在密钥库中至少找到了一个证书i  在身份作用域内至少找到了一个证书jar 已验证。警告 此 jar 包含签名者证书将在六个月内过期的条目。 代码签名认证的用途主要是对发布的软件做验证支持 Sun Java .jar (Java Applet) 文件(J2SE)和 J2ME MIDlet Suite 文件。      在中我们模拟了一个基于RSA非对称加密网络的安全通信。现在我们深度了解一下现有的安全网络通信——SSL。     我们需要构建一个由CA机构签发的有效证书这里我们使用上文中生成的自签名证书zlex.cer     这里我们将证书导入到我们的密钥库。  keytool -import -alias www.zlex.org -file d:/zlex.cer -keystore d:/zlex.keystore 其中 -import表示导入 -alias指定别名这里是www.zlex.org -file指定算法这里是d:/zlex.cer -keystore指定存储位置这里是d:/zlex.keystore 在这里我使用的密码为654321 控制台输出 输入keystore密码 再次输入新密码: 所有者:CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN 签发人:CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN 序列号:4a1e48df 有效期: Thu May 28 16:18:39 CST 2009 至Wed Aug 26 16:18:39 CST 2009 证书指纹:MD5:19:CA:E6:36:E2:DF:AD:96:31:97:2F:A9:AD:FC:37:6ASHA1:49:88:30:59:29:45:F1:69:CA:97:A9:6D:8A:CF:08:D2:C3:D5:C0:C4签名算法名称:SHA1withRSA版本: 3 信任这个认证 [否]  y 认证已添加至keystore中 OK最复杂的准备工作已经完成。 接下来我们将域名www.zlex.org定位到本机上。打开C:\Windows\System32\drivers\etc\hosts文件将www.zlex.org绑定在本机上。在文件末尾追加127.0.0.1       www.zlex.org。现在通过地址栏访问http://www.zlex.org或者通过ping命令如果能够定位到本机域名映射就搞定了。 现在配置tomcat。先将zlex.keystore拷贝到tomcat的conf目录下然后配置server.xml。将如下内容加入配置文件 ConnectorSSLEnabledtrueURIEncodingUTF-8clientAuthfalsekeystoreFileconf/zlex.keystorekeystorePass123456maxThreads150port443protocolHTTP/1.1schemehttpssecuretruesslProtocolTLS / 注意clientAuthfalse测试阶段置为false正式使用时建议使用true。现在启动tomcat访问https://www.zlex.org/。 显然证书未能通过认证这个时候你可以选择安装证书上文中的zlex.cer文件就是证书作为受信任的根证书颁发机构导入再次重启浏览器IE其他浏览器对于域名www.zlex.org不支持本地方式访问访问https://www.zlex.org/你会看到地址栏中会有个小锁就说明安装成功。所有的浏览器联网操作已经在RSA加密解密系统的保护之下了。但似乎我们感受不到。 这个时候很多人开始怀疑如果我们要手工做一个这样的https的访问是不是需要把浏览器的这些个功能都实现呢不需要 接着上篇内容给出如下代码实现 import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Date;import javax.crypto.Cipher; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory;/*** 证书组件* * author 梁栋* version 1.0* since 1.0*/ public abstract class CertificateCoder extends Coder {/*** Java密钥库(Java Key StoreJKS)KEY_STORE*/public static final String KEY_STORE  JKS;public static final String X509  X.509;public static final String SunX509  SunX509;public static final String SSL  SSL;/*** 由KeyStore获得私钥* * param keyStorePath* param alias* param password* return* throws Exception*/private static PrivateKey getPrivateKey(String keyStorePath, String alias,String password) throws Exception {KeyStore ks  getKeyStore(keyStorePath, password);PrivateKey key  (PrivateKey) ks.getKey(alias, password.toCharArray());return key;}/*** 由Certificate获得公钥* * param certificatePath* return* throws Exception*/private static PublicKey getPublicKey(String certificatePath)throws Exception {Certificate certificate  getCertificate(certificatePath);PublicKey key  certificate.getPublicKey();return key;}/*** 获得Certificate* * param certificatePath* return* throws Exception*/private static Certificate getCertificate(String certificatePath)throws Exception {CertificateFactory certificateFactory  CertificateFactory.getInstance(X509);FileInputStream in  new FileInputStream(certificatePath);Certificate certificate  certificateFactory.generateCertificate(in);in.close();return certificate;}/*** 获得Certificate* * param keyStorePath* param alias* param password* return* throws Exception*/private static Certificate getCertificate(String keyStorePath,String alias, String password) throws Exception {KeyStore ks  getKeyStore(keyStorePath, password);Certificate certificate  ks.getCertificate(alias);return certificate;}/*** 获得KeyStore* * param keyStorePath* param password* return* throws Exception*/private static KeyStore getKeyStore(String keyStorePath, String password)throws Exception {FileInputStream is  new FileInputStream(keyStorePath);KeyStore ks  KeyStore.getInstance(KEY_STORE);ks.load(is, password.toCharArray());is.close();return ks;}/*** 私钥加密* * param data* param keyStorePath* param alias* param password* return* throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath,String alias, String password) throws Exception {// 取得私钥PrivateKey privateKey  getPrivateKey(keyStorePath, alias, password);// 对数据加密Cipher cipher  Cipher.getInstance(privateKey.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 私钥解密* * param data* param keyStorePath* param alias* param password* return* throws Exception*/public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath,String alias, String password) throws Exception {// 取得私钥PrivateKey privateKey  getPrivateKey(keyStorePath, alias, password);// 对数据加密Cipher cipher  Cipher.getInstance(privateKey.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 公钥加密* * param data* param certificatePath* return* throws Exception*/public static byte[] encryptByPublicKey(byte[] data, String certificatePath)throws Exception {// 取得公钥PublicKey publicKey  getPublicKey(certificatePath);// 对数据加密Cipher cipher  Cipher.getInstance(publicKey.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 公钥解密* * param data* param certificatePath* return* throws Exception*/public static byte[] decryptByPublicKey(byte[] data, String certificatePath)throws Exception {// 取得公钥PublicKey publicKey  getPublicKey(certificatePath);// 对数据加密Cipher cipher  Cipher.getInstance(publicKey.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 验证Certificate* * param certificatePath* return*/public static boolean verifyCertificate(String certificatePath) {return verifyCertificate(new Date(), certificatePath);}/*** 验证Certificate是否过期或无效* * param date* param certificatePath* return*/public static boolean verifyCertificate(Date date, String certificatePath) {boolean status  true;try {// 取得证书Certificate certificate  getCertificate(certificatePath);// 验证证书是否过期或无效status  verifyCertificate(date, certificate);} catch (Exception e) {status  false;}return status;}/*** 验证证书是否过期或无效* * param date* param certificate* return*/private static boolean verifyCertificate(Date date, Certificate certificate) {boolean status  true;try {X509Certificate x509Certificate  (X509Certificate) certificate;x509Certificate.checkValidity(date);} catch (Exception e) {status  false;}return status;}/*** 签名* * param keyStorePath* param alias* param password* * return* throws Exception*/public static String sign(byte[] sign, String keyStorePath, String alias,String password) throws Exception {// 获得证书X509Certificate x509Certificate  (X509Certificate) getCertificate(keyStorePath, alias, password);// 获取私钥KeyStore ks  getKeyStore(keyStorePath, password);// 取得私钥PrivateKey privateKey  (PrivateKey) ks.getKey(alias, password.toCharArray());// 构建签名Signature signature  Signature.getInstance(x509Certificate.getSigAlgName());signature.initSign(privateKey);signature.update(sign);return encryptBASE64(signature.sign());}/*** 验证签名* * param data* param sign* param certificatePath* return* throws Exception*/public static boolean verify(byte[] data, String sign,String certificatePath) throws Exception {// 获得证书X509Certificate x509Certificate  (X509Certificate) getCertificate(certificatePath);// 获得公钥PublicKey publicKey  x509Certificate.getPublicKey();// 构建签名Signature signature  Signature.getInstance(x509Certificate.getSigAlgName());signature.initVerify(publicKey);signature.update(data);return signature.verify(decryptBASE64(sign));}/*** 验证Certificate* * param keyStorePath* param alias* param password* return*/public static boolean verifyCertificate(Date date, String keyStorePath,String alias, String password) {boolean status  true;try {Certificate certificate  getCertificate(keyStorePath, alias,password);status  verifyCertificate(date, certificate);} catch (Exception e) {status  false;}return status;}/*** 验证Certificate* * param keyStorePath* param alias* param password* return*/public static boolean verifyCertificate(String keyStorePath, String alias,String password) {return verifyCertificate(new Date(), keyStorePath, alias, password);}/*** 获得SSLSocektFactory* * param password*            密码* param keyStorePath*            密钥库路径* * param trustKeyStorePath*            信任库路径* return* throws Exception*/private static SSLSocketFactory getSSLSocketFactory(String password,String keyStorePath, String trustKeyStorePath) throws Exception {// 初始化密钥库KeyManagerFactory keyManagerFactory  KeyManagerFactory.getInstance(SunX509);KeyStore keyStore  getKeyStore(keyStorePath, password);keyManagerFactory.init(keyStore, password.toCharArray());// 初始化信任库TrustManagerFactory trustManagerFactory  TrustManagerFactory.getInstance(SunX509);KeyStore trustkeyStore  getKeyStore(trustKeyStorePath, password);trustManagerFactory.init(trustkeyStore);// 初始化SSL上下文SSLContext ctx  SSLContext.getInstance(SSL);ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);SSLSocketFactory sf  ctx.getSocketFactory();return sf;}/*** 为HttpsURLConnection配置SSLSocketFactory* * param conn*            HttpsURLConnection* param password*            密码* param keyStorePath*            密钥库路径* * param trustKeyStorePath*            信任库路径* throws Exception*/public static void configSSLSocketFactory(HttpsURLConnection conn,String password, String keyStorePath, String trustKeyStorePath)throws Exception {conn.setSSLSocketFactory(getSSLSocketFactory(password, keyStorePath,trustKeyStorePath));} } 增加了configSSLSocketFactory方法供外界调用该方法为HttpsURLConnection配置了SSLSocketFactory。当HttpsURLConnection配置了SSLSocketFactory后我们就可以通过HttpsURLConnection的getInputStream、getOutputStream像往常使用HttpURLConnection做操作了。尤其要说明一点未配置SSLSocketFactory前HttpsURLConnection的getContentLength()获得值永远都是-1。 给出相应测试类 import static org.junit.Assert.*;import java.io.DataInputStream; import java.io.InputStream; import java.net.URL;import javax.net.ssl.HttpsURLConnection;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class CertificateCoderTest {private String password  123456;private String alias  www.zlex.org;private String certificatePath  d:/zlex.cer;private String keyStorePath  d:/zlex.keystore;private String clientKeyStorePath  d:/zlex-client.keystore;private String clientPassword  654321;Testpublic void test() throws Exception {System.err.println(公钥加密——私钥解密);String inputStr  Ceritifcate;byte[] data  inputStr.getBytes();byte[] encrypt  CertificateCoder.encryptByPublicKey(data,certificatePath);byte[] decrypt  CertificateCoder.decryptByPrivateKey(encrypt,keyStorePath, alias, password);String outputStr  new String(decrypt);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);// 验证数据一致assertArrayEquals(data, decrypt);// 验证证书有效assertTrue(CertificateCoder.verifyCertificate(certificatePath));}Testpublic void testSign() throws Exception {System.err.println(私钥加密——公钥解密);String inputStr  sign;byte[] data  inputStr.getBytes();byte[] encodedData  CertificateCoder.encryptByPrivateKey(data,keyStorePath, alias, password);byte[] decodedData  CertificateCoder.decryptByPublicKey(encodedData,certificatePath);String outputStr  new String(decodedData);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);assertEquals(inputStr, outputStr);System.err.println(私钥签名——公钥验证签名);// 产生签名String sign  CertificateCoder.sign(encodedData, keyStorePath, alias,password);System.err.println(签名:\r  sign);// 验证签名boolean status  CertificateCoder.verify(encodedData, sign,certificatePath);System.err.println(状态:\r  status);assertTrue(status);}Testpublic void testHttps() throws Exception {URL url  new URL(https://www.zlex.org/examples/);HttpsURLConnection conn  (HttpsURLConnection) url.openConnection();conn.setDoInput(true);conn.setDoOutput(true);CertificateCoder.configSSLSocketFactory(conn, clientPassword,clientKeyStorePath, clientKeyStorePath);InputStream is  conn.getInputStream();int length  conn.getContentLength();DataInputStream dis  new DataInputStream(is);byte[] data  new byte[length];dis.readFully(data);dis.close();System.err.println(new String(data));conn.disconnect();} } 注意testHttps方法几乎和我们往常做HTTP访问没有差别我们来看控制台输出 !--Licensed to the Apache Software Foundation (ASF) under one or morecontributor license agreements.  See the NOTICE file distributed withthis work for additional information regarding copyright ownership.The ASF licenses this file to You under the Apache License, Version 2.0(the License); you may not use this file except in compliance withthe License.  You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an AS IS BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License. -- !DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.0 Transitional//EN HTMLHEADTITLEApache Tomcat Examples/TITLE META http-equivContent-Type contenttext/html /HEAD BODY P H3Apache Tomcat Examples/H3 P/P ul lia hrefhttp://javaeye.shaduwang.com/?snowolf/blog/servletsServlets examples/a/li lia hrefhttp://javaeye.shaduwang.com/?snowolf/blog/jspJSP Examples/a/li /ul /BODY/HTML 通过浏览器直接访问https://www.zlex.org/examples/你也会获得上述内容。也就是说应用甲方作为服务器构建tomcat服务乙方可以通过上述方式访问甲方受保护的SSL应用并且不需要考虑具体的加密解密问题。甲乙双方可以经过相应配置通过双方的tomcat配置有效的SSL服务简化上述代码实现完全通过证书配置完成SSL双向认证     我们使用自签名证书完成了认证。接下来我们使用第三方CA签名机构完成证书签名。     这里我们使用thawte提供的测试用21天免费ca证书。     1.要在该网站上注明你的域名这里使用www.zlex.org作为测试用域名请勿使用该域名作为你的域名地址该域名受法律保护请使用其他非注册域名。     2.如果域名有效你会收到邮件要求你访问https://www.thawte.com/cgi/server/try.exe获得ca证书。     3.复述密钥库的创建。 keytool -genkey -validity 36000 -alias www.zlex.org -keyalg RSA -keystore d:\zlex.keystore 在这里我使用的密码为 123456 控制台输出 输入keystore密码 再次输入新密码: 您的名字与姓氏是什么[Unknown]  www.zlex.org 您的组织单位名称是什么[Unknown]  zlex 您的组织名称是什么[Unknown]  zlex 您所在的城市或区域名称是什么[Unknown]  BJ 您所在的州或省份名称是什么[Unknown]  BJ 该单位的两字母国家代码是什么[Unknown]  CN CNwww.zlex.org, OUzlex, Ozlex, LBJ, STBJ, CCN 正确吗[否]  Y输入tomcat的主密码如果和 keystore 密码相同按回车 再次输入新密码:     4.通过如下命令从zlex.keystore中导出CA证书申请。     keytool -certreq -alias www.zlex.org -file d:\zlex.csr -keystore d:\zlex.keystore -v 你会获得zlex.csr文件可以用记事本打开内容如下格式 -----BEGIN NEW CERTIFICATE REQUEST----- MIIBnDCCAQUCAQAwXDELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAkJKMQswCQYDVQQHEwJCSjENMAsG A1UEChMEemxleDENMAsGA1UECxMEemxleDEVMBMGA1UEAxMMd3d3LnpsZXgub3JnMIGfMA0GCSqG SIb3DQEBAQUAA4GNADCBiQKBgQCR6DXU9MpmCKO7cv9JPsj0n1Ec/GpM09qvhpgX3FNad/ZWSDc vU77YXZSoF9hQp3w1LCeeKgd2MlVpXTvbVwBNVd2HiQPp37ic6BUUjSaX8LHtCl7l0BIEye9qQ2 j8G0kak7e8ZA0s7nb3Ymq/K8BV7v0MQIdhIc1bifK9ZDewIDAQABoAAwDQYJKoZIhvcNAQEFBQAD gYEAMA1r2fbZPtNx37U9TRwadCH2TZZecwKJS/hskNm6ryPKIAp9APWwAyj8WJHRBz5SpZM4zmYO oMCI8BcnY2A4JPR7/SwXTdH/xcg7NVghd9A2SCgqMpF7KMfc5dE3iygdiPuUhY200Dvpjx8gmJ 1UbH3nqMUyCrZgURFslOUY -----END NEW CERTIFICATE REQUEST-----     5.将上述文件内容拷贝到https://www.thawte.com/cgi/server/try.exe中点击next获得回应内容这里是p7b格式。 内容如下 -----BEGIN PKCS7----- MIIF3AYJKoZIhvcNAQcCoIIFzTCCBckCAQExADALBgkqhkiG9w0BBwGgggWxMIID EDCCAnmgAwIBAgIQA/mx/pKoaBKGX2hveFU9zANBgkqhkiG9w0BAQUFADCBhzEL MAkGA1UEBhMCWkExIjAgBgNVBAgTGUZPUiBURVNUSU5HIFBVUlBPU0VTIE9OTFkx HTAbBgNVBAoTFFRoYXd0ZSBDZXJ0aWZpY2F0aW9uMRcwFQYDVQQLEw5URVNUIFRF U1QgVEVTVDEcMBoGA1UEAxMTVGhhd3RlIFRlc3QgQ0EgUm9vdDAeFw0wOTA1Mjgw MDIxMzlaFw0wOTA2MTgwMDIxMzlaMFwxCzAJBgNVBAYTAkNOMQswCQYDVQQIEwJC SjELMAkGA1UEBxMCQkoxDTALBgNVBAoTBHpsZXgxDTALBgNVBAsTBHpsZXgxFTAT BgNVBAMTDHd3dy56bGV4Lm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA keg11PTKfpgiju3L/ST7I9J9RHPxqTNPar4aYF9xTWnf2Vkg3L1O2F2UqBfYUKd 8NSwvnnioHdjJVaV0721cATVXdh4kD6d4nOgVFI0ml/Cx7Qpe5dASBMnvakNo/B tJGpO3vGQNLO5292JqvyvAVe79DECHYSHNW4nyvWQ3sCAwEAAaOBpjCBozAMBgNV HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBABgNVHR8E OTA3MDWgM6Axhi9odHRwOi8vY3JsLnRoYXd0ZS5jb20vVGhhd3RlUHJlbWl1bVNl cnZlckNBLmNybDAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9v Y3NwLnRoYXd0ZS5jb20wDQYJKoZIhvcNAQEFBQADgYEATPuxZbtJJSPmXvfrr1yz xqM06IwTZ6UU0lZRG7I0WufMjNMKdpn8hklUhE17mxAhGSpewLVVeLR7uzBLFkuC X7wMXxhoYdJZtNai72izU6Rd1oknao7diahvRxPK4IuQ7y2oZ511/4T4vgY6iRAj q4q76HhPJrVRL/sduaiugYwggKZMIICAqADAgECAgEAMA0GCSqGSIb3DQEBBAUA MIGHMQswCQYDVQQGEwJaQTEiMCAGA1UECBMZRk9SIFRFU1RJTkcgUFVSUE9TRVMg T05MWTEdMBsGA1UEChMUVGhhd3RlIENlcnRpZmljYXRpb24xFzAVBgNVBAsTDlRF U1QgVEVTVCBURVNUMRwwGgYDVQQDExNUaGF3dGUgVGVzdCBDQSBSb290MB4XDTk2 MDgwMTAwMDAwMFoXDTIwMTIzMTIxNTk1OVowgYcxCzAJBgNVBAYTAlpBMSIwIAYD VQQIExlGT1IgVEVTVElORyBQVVJQT1NFUyBPTkxZMR0wGwYDVQQKExRUaGF3dGUg Q2VydGlmaWNhdGlvbjEXMBUGA1UECxMOVEVTVCBURVNUIFRFU1QxHDAaBgNVBAMT E1RoYXd0ZSBUZXN0IENBIFJvb3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB ALV9kGOs6x/DOhmtKUQfzVMWGhE95sFmEtkMMTX2Zi4n6i6BvzoReJ5njzt1LF cqu4EUk9Ji20egKKfmqRzmQFLP71niSdfJEUE7cKY40QoI99270PTrLjJeaMcCl AYlkDRL5BtuKKU3PurYcsCsre6aTvjMcqpTJOGeSPAgMBAAGjEzARMA8GA1Ud EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAgozj7BkD9O8si2V0vEZ/t7E fz/LC8y6mD7IBUziHy5/53ymGAGLtyhXHvXUIE6UWbHro3IqVkrmY5uC93Z2Wew A/6edK3KFUcUikrLeewM7gmqsiASEKx2mKRKlu12jXyNS5tXrPWRDvUKtFC1uL9a 12rFAQS2BkIk7aUghYxAA -----END PKCS7----- 将其存储为zlex.p7b     6.将由CA签发的证书导入密钥库。 keytool -import -trustcacerts -alias www.zlex.org -file d:\zlex.p7b -keystore d:\zlex.keystore -v 在这里我使用的密码为 123456     控制台输出 输入keystore密码回复中的最高级认证所有者:CNThawte Test CA Root, OUTEST TEST TEST, OThawte Certification, STFORTESTING PURPOSES ONLY, CZA 签发人:CNThawte Test CA Root, OUTEST TEST TEST, OThawte Certification, STFORTESTING PURPOSES ONLY, CZA 序列号:0 有效期: Thu Aug 01 08:00:00 CST 1996 至Fri Jan 01 05:59:59 CST 2021 证书指纹:MD5:5E:E0:0E:1D:17:B7:CA:A5:7D:36:D6:02:DF:4D:26:A4SHA1:39:C6:9D:27:AF:DC:EB:47:D6:33:36:6A:B2:05:F1:47:A9:B4:DA:EA签名算法名称:MD5withRSA版本: 3扩展:#1: ObjectId: 2.5.29.19 Criticalitytrue BasicConstraints:[CA:truePathLen:2147483647 ]... 是不可信的。 还是要安装回复 [否]  Y 认证回复已安装在 keystore中 [正在存储 d:\zlex.keystore]     7.域名定位     将域名www.zlex.org定位到本机上。打开C:\Windows\System32\drivers\etc\hosts文件将www.zlex.org绑定在本机上。在文件末尾追加127.0.0.1       www.zlex.org。现在通过地址栏访问http://www.zlex.org或者通过ping命令如果能够定位到本机域名映射就搞定了。     8.配置server.xml ConnectorkeystoreFileconf/zlex.keystorekeystorePass123456 truststoreFileconf/zlex.keystore    truststorePass123456     SSLEnabledtrueURIEncodingUTF-8clientAuthfalse maxThreads150port443protocolHTTP/1.1schemehttpssecuretruesslProtocolTLS / 将文件zlex.keystore拷贝到tomcat的conf目录下重新启动tomcat。访问https://www.zlex.org/我们发现联网有些迟钝。大约5秒钟后网页正常显示同时有如下图所示  浏览器验证了该CA机构的有效性。 打开证书如下图所示  调整测试类  import static org.junit.Assert.*;import java.io.DataInputStream; import java.io.InputStream; import java.net.URL;import javax.net.ssl.HttpsURLConnection;import org.junit.Test;/*** * author 梁栋* version 1.0* since 1.0*/ public class CertificateCoderTest {private String password  123456;private String alias  www.zlex.org;private String certificatePath  d:/zlex.cer;private String keyStorePath  d:/zlex.keystore;Testpublic void test() throws Exception {System.err.println(公钥加密——私钥解密);String inputStr  Ceritifcate;byte[] data  inputStr.getBytes();byte[] encrypt  CertificateCoder.encryptByPublicKey(data,certificatePath);byte[] decrypt  CertificateCoder.decryptByPrivateKey(encrypt,keyStorePath, alias, password);String outputStr  new String(decrypt);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);// 验证数据一致assertArrayEquals(data, decrypt);// 验证证书有效assertTrue(CertificateCoder.verifyCertificate(certificatePath));}Testpublic void testSign() throws Exception {System.err.println(私钥加密——公钥解密);String inputStr  sign;byte[] data  inputStr.getBytes();byte[] encodedData  CertificateCoder.encryptByPrivateKey(data,keyStorePath, alias, password);byte[] decodedData  CertificateCoder.decryptByPublicKey(encodedData,certificatePath);String outputStr  new String(decodedData);System.err.println(加密前:   inputStr  \n\r  解密后:   outputStr);assertEquals(inputStr, outputStr);System.err.println(私钥签名——公钥验证签名);// 产生签名String sign  CertificateCoder.sign(encodedData, keyStorePath, alias,password);System.err.println(签名:\r  sign);// 验证签名boolean status  CertificateCoder.verify(encodedData, sign,certificatePath);System.err.println(状态:\r  status);assertTrue(status);}Testpublic void testHttps() throws Exception {URL url  new URL(https://www.zlex.org/examples/);HttpsURLConnection conn  (HttpsURLConnection) url.openConnection();conn.setDoInput(true);conn.setDoOutput(true);CertificateCoder.configSSLSocketFactory(conn, password, keyStorePath,keyStorePath);InputStream is  conn.getInputStream();int length  conn.getContentLength();DataInputStream dis  new DataInputStream(is);byte[] data  new byte[length];dis.readFully(data);dis.close();conn.disconnect();System.err.println(new String(data));} } 再次执行验证通过 由此我们了基于SSL协议的认证过程。测试类的testHttps方法模拟了一次浏览器的HTTPS访问。 转载于:https://my.oschina.net/me0eric/blog/221027
http://www.pierceye.com/news/663370/

相关文章:

  • 常见的简单的网站制作建设网站的好公司
  • 邯郸网站制作建设wordpress+怎么迁移
  • 设计创意广告上海企业网站优化
  • 自己做网站需要购买服务器吗WordPress文章相册修改
  • 校园招聘哪个网站做的好学做川菜网站
  • 大足网站建设公司医院网站建设熊掌号
  • 做网站编辑是不是也要做推广做蛋白go分析网站
  • 免费品牌网站制作云南电商网站建设
  • 宿迁莱布拉网站建设常州做网站建设的公司
  • 广东网站建站系统哪家好常州网站搭建公司
  • 400网站建设推广软件工程师工资
  • 专门做正品的网站手机版深圳市门户网站建设怎么样
  • 做外贸比较好的网站有哪些北京短视频代运营
  • 建站公司学习筑梦网站建设
  • 手工艺品网站建设侧胡顺个人简历表格可填写
  • 电商网站竞价推广策略淘宝做问卷的网站
  • 门窗 东莞网站建设婚庆公司收费标准
  • 网站页面下沉的特效代码网络建设存在的问题
  • 给网站做维护是什么工作网页怎么赚钱
  • 三丰云做游戏网站win主机安装wordpress
  • 网站建设黄荣vuejs做视频网站设计
  • 手机怎样下载安装建设银行网站企业通过网络推广成功的案例
  • 门户网站开发工具软件哪个公司的网络最好用
  • 河南省住房和城乡建设厅查询网站首页舆情网站推荐
  • 网页设计是网站建设与管理的内容吗公司网络营销的方案思路
  • 商业授权网站标题优化技巧
  • 班级网站做哪些方面阿里云市场网站建设
  • 2345网站登录电子工程师有前途吗
  • 网站建设企业邮箱制作网站山东平台网站建设制作
  • 仿新浪微博网站代码国家高新技术企业公示