以下文章来自:http://kingj.iteye.com/blog/2103662
1、创建java证书:
C:\> keytool -genkey -alias wangyi -keypass wangyi -keyalg RSA -keysize 1024 -keystore https.keystore -storepass wangyi
2、将创建的证书保存到C盘(为了方便演示)
C:\>keytool -export -keystore https.keystore -alias wangyi -file https.crt -storepass wangyi
代码包含6个类,分别为:
名称 | 说明 |
CertifcateUtils | 证书操作类 |
DesCoder | Des对称加密和解密工具类 |
HttpsMockBase | https父类 |
HttpsMockClient | client类 |
HttpsMockServer | 服务器类 |
SocketUtils | socket工具类 |
CertifacateUtils.java
package httpsmock;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
/**
* Created by kingj on 2014/8/13.
*/
public class CertifcateUtils {
public static byte[] readCertifacates() throws Exception{
CertificateFactory factory=CertificateFactory.getInstance("X.509");
InputStream in=new FileInputStream("c:/https.crt");
java.security.cert.Certificate cate=factory.generateCertificate(in);
return cate.getEncoded();
}
public static byte[] readPrivateKey() throws Exception{
KeyStore store=KeyStore.getInstance("JKS");
InputStream in=new FileInputStream("c:/https.keystore");
store.load(in,"wangyi".toCharArray());
PrivateKey pk=(PrivateKey)store.getKey("wangyi","wangyi".toCharArray());
return pk.getEncoded();
}
public static PrivateKey readPrivateKeys() throws Exception{
KeyStore store=KeyStore.getInstance("JKS");
InputStream in=new FileInputStream("c:/https.keystore");
store.load(in,"wangyi".toCharArray());
PrivateKey pk=(PrivateKey)store.getKey("wangyi","wangyi".toCharArray());
return pk;
}
public static PublicKey readPublicKeys() throws Exception{
CertificateFactory factory=CertificateFactory.getInstance("X.509");
InputStream in=new FileInputStream("c:/https.crt");
java.security.cert.Certificate cate=factory.generateCertificate(in);
return cate.getPublicKey();
}
public static java.security.cert.Certificate createCertiface(byte b[]) throws Exception{
CertificateFactory factory=CertificateFactory.getInstance("X.509");
InputStream in=new ByteArrayInputStream(b);
java.security.cert.Certificate cate=factory.generateCertificate(in);
return cate;
}
public static String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs.toUpperCase();
}
}
package httpsmock;
/**
* Created by kingj on 2014/8/13.
*/
import org.apache.commons.codec.binary.Hex;
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 Coder
* secret key length: 56 bit, default: 56 bit
* mode: ECB/CBC/PCBC/CTR/CTS/CFB/CFB8 to CFB128/OFB/OBF8 to OFB128
* padding: Nopadding/PKCS5Padding/ISO10126Padding/
* @author Aub
*
*/
public class DesCoder {
/**
* 密钥算法
*/
private static final String KEY_ALGORITHM = "DES";
private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
// private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/ISO10126Padding";
/**
* 初始化密钥
*
* @return byte[] 密钥
* @throws Exception
*/
public static byte[] initSecretKey(SecureRandom random) throws Exception{
//返回生成指定算法的秘密密钥的 KeyGenerator 对象
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
//初始化此密钥生成器,使其具有确定的密钥大小
kg.init(random);
//生成一个密钥
SecretKey secretKey = kg.generateKey();
return secretKey.getEncoded();
}
/**
* 转换密钥
*
* @param key 二进制密钥
* @return Key 密钥
* @throws Exception
*/
public static Key toKey(byte[] key) throws Exception{
//实例化DES密钥规则
DESKeySpec dks = new DESKeySpec(key);
//实例化密钥工厂
SecretKeyFactory skf = SecretKeyFactory.getInstance(KEY_ALGORITHM);
//生成密钥
SecretKey secretKey = skf.generateSecret(dks);
return secretKey;
}
/**
* 加密
*
* @param data 待加密数据
* @param key 密钥
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data,Key key) throws Exception{
return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
}
/**
* 加密
*
* @param data 待加密数据
* @param key 二进制密钥
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data,byte[] key) throws Exception{
return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
}
/**
* 加密
*
* @param data 待加密数据
* @param key 二进制密钥
* @param cipherAlgorithm 加密算法/工作模式/填充方式
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{
//还原密钥
Key k = toKey(key);
return encrypt(data, k, cipherAlgorithm);
}
/**
* 加密
*
* @param data 待加密数据
* @param key 密钥
* @param cipherAlgorithm 加密算法/工作模式/填充方式
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{
//实例化
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
//使用密钥初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, key);
//执行操作
return cipher.doFinal(data);
}
/**
* 解密
*
* @param data 待解密数据
* @param key 二进制密钥
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data,byte[] key) throws Exception{
return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
}
/**
* 解密
*
* @param data 待解密数据
* @param key 密钥
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data,Key key) throws Exception{
return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
}
/**
* 解密
*
* @param data 待解密数据
* @param key 二进制密钥
* @param cipherAlgorithm 加密算法/工作模式/填充方式
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{
//还原密钥
Key k = toKey(key);
return decrypt(data, k, cipherAlgorithm);
}
/**
* 解密
*
* @param data 待解密数据
* @param key 密钥
* @param cipherAlgorithm 加密算法/工作模式/填充方式
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{
//实例化
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
//使用密钥初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, key);
//执行操作
return cipher.doFinal(data);
}
private static String showByteArray(byte[] data){
if(null == data){
return null;
}
StringBuilder sb = new StringBuilder("{");
for(byte b:data){
sb.append(b).append(",");
}
sb.deleteCharAt(sb.length()-1);
sb.append("}");
return sb.toString();
}
}
package httpsmock;
import com.sun.org.apache.bcel.internal.generic.NEW;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;
/**
* Created by kingj on 2014/8/13.
*/
public class HttpsMockBase {
static PrivateKey privateKey;
static PublicKey publicKey;
public static boolean byteEquals(byte a[],byte[] b){
boolean equals=true;
if(a==null || b==null){
equals=false;
}
if(a!=null && b!=null){
if(a.length!=b.length){
equals=false;
}else{
for(int i=0;i
package httpsmock;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.security.Key;
import java.security.SecureRandom;
/**
* Created by kingj on 2014/8/13.
*/
public class HttpsMockClient extends HttpsMockBase {
static DataInputStream in;
static DataOutputStream out;
static Key key;
public static void main(String args[]) throws Exception{
int port=80;
Socket s=new Socket("localhost",port);
s.setReceiveBufferSize(102400);
s.setKeepAlive(true);
in=new DataInputStream(s.getInputStream());
out=new DataOutputStream(s.getOutputStream());
shakeHands();
System.out.println("------------------------------------------------------------------");
String name="duck";
writeBytes(name.getBytes());
int len=in.readInt();
byte[] msg=readBytes(len);
System.out.println("服务器反馈消息:"+byte2hex(msg));
Thread.sleep(1000*100);
}
private static void shakeHands() throws Exception {
//第一步 客户端发送自己支持的hash算法
String supportHash="SHA1";
int length=supportHash.getBytes().length;
out.writeInt(length);
SocketUtils.writeBytes(out, supportHash.getBytes(), length);
//第二步 客户端验证服务器端证书是否合法
int skip=in.readInt();
byte[] certificate=SocketUtils.readBytes(in,skip);
java.security.cert.Certificate cc= CertifcateUtils.createCertiface(certificate);
publicKey=cc.getPublicKey();
cc.verify(publicKey);
System.out.println("客户端校验服务器端证书是否合法:" +true);
//第三步 客户端校验服务器端发送过来的证书成功,生成随机数并用公钥加密
System.out.println("客户端校验服务器端发送过来的证书成功,生成随机数并用公钥加密");
SecureRandom seed=new SecureRandom();
int seedLength=2;
byte seedBytes[]=seed.generateSeed(seedLength);
System.out.println("生成的随机数为 : " + byte2hex(seedBytes));
System.out.println("将随机数用公钥加密后发送到服务器");
byte[] encrptedSeed=encryptByPublicKey(seedBytes, null);
SocketUtils.writeBytes(out,encrptedSeed,encrptedSeed.length);
System.out.println("加密后的seed值为 :" + byte2hex(encrptedSeed));
String message=random();
System.out.println("客户端生成消息为:"+message);
System.out.println("使用随机数并用公钥对消息加密");
byte[] encrpt=encryptByPublicKey(message.getBytes(),seed);
System.out.println("加密后消息位数为 : " +encrpt.length);
SocketUtils.writeBytes(out,encrpt,encrpt.length);
System.out.println("客户端使用SHA1计算消息摘要");
byte hash[]=cactHash(message.getBytes());
System.out.println("摘要信息为:"+byte2hex(hash));
System.out.println("消息加密完成,摘要计算完成,发送服务器");
SocketUtils.writeBytes(out,hash,hash.length);
System.out.println("客户端向服务器发送消息完成,开始接受服务器端发送回来的消息和摘要");
System.out.println("接受服务器端发送的消息");
int serverMessageLength=in.readInt();
byte[] serverMessage=SocketUtils.readBytes(in,serverMessageLength);
System.out.println("服务器端的消息内容为 :" + byte2hex(serverMessage));
System.out.println("开始用之前生成的随机密码和DES算法解密消息,密码为:"+byte2hex(seedBytes));
byte[] desKey= DesCoder.initSecretKey(new SecureRandom(seedBytes));
key=DesCoder.toKey(desKey);
byte[] decrpytedServerMsg=DesCoder.decrypt(serverMessage, key);
System.out.println("解密后的消息为:"+byte2hex(decrpytedServerMsg));
int serverHashLength=in.readInt();
byte[] serverHash=SocketUtils.readBytes(in,serverHashLength);
System.out.println("开始接受服务器端的摘要消息:"+byte2hex(serverHash));
byte[] serverHashValues=cactHash(decrpytedServerMsg);
System.out.println("计算服务器端发送过来的消息的摘要 : " +byte2hex(serverHashValues));
System.out.println("判断服务器端发送过来的hash摘要是否和计算出的摘要一致");
boolean isHashEquals=byteEquals(serverHashValues,serverHash);
if(isHashEquals){
System.out.println("验证完成,握手成功");
}else{
System.out.println("验证失败,握手失败");
}
}
public static byte[] readBytes(int length) throws Exception{
byte[] undecrpty=SocketUtils.readBytes(in,length);
System.out.println("读取未解密消息:"+byte2hex(undecrpty));
return DesCoder.decrypt(undecrpty,key);
}
public static void writeBytes(byte[] data) throws Exception{
byte[] encrpted=DesCoder.encrypt(data,key);
System.out.println("写入加密后消息:"+byte2hex(encrpted));
SocketUtils.writeBytes(out,encrpted,encrpted.length);
}
}
package httpsmock;
import javax.net.ServerSocketFactory;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.Key;
import java.security.SecureRandom;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by kingj on 2014/8/13.
*/
public class HttpsMockServer extends HttpsMockBase {
static DataInputStream in;
static DataOutputStream out;
static String hash;
static Key key;
static ExecutorService executorService= Executors.newFixedThreadPool(20);
public static void main(String args[]) throws Exception{
int port=80;
ServerSocket ss= ServerSocketFactory.getDefault().createServerSocket(port);
ss.setReceiveBufferSize(102400);
ss.setReuseAddress(false);
while(true){
try {
final Socket s = ss.accept();
doHttpsShakeHands(s);
executorService.execute(new Runnable() {
@Override
public void run() {
doSocketTransport(s);
}
});
}catch (Exception e){
e.printStackTrace();
}
}
}
private static void doSocketTransport(Socket s){
try{
System.out.println("--------------------------------------------------------");
int length=in.readInt();
byte[] clientMsg=readBytes(length);
System.out.println("客户端指令内容为:" + byte2hex(clientMsg));
writeBytes("服务器已经接受请求".getBytes());
}catch (Exception ex){
ex.printStackTrace();
}
}
public static byte[] readBytes(int length) throws Exception{
byte[] undecrpty=SocketUtils.readBytes(in,length);
System.out.println("读取未解密消息:"+byte2hex(undecrpty));
return DesCoder.decrypt(undecrpty,key);
}
public static void writeBytes(byte[] data) throws Exception{
byte[] encrpted=DesCoder.encrypt(data,key);
System.out.println("写入加密后消息:"+byte2hex(encrpted));
SocketUtils.writeBytes(out,encrpted,encrpted.length);
}
private static void doHttpsShakeHands(Socket s) throws Exception {
in=new DataInputStream(s.getInputStream());
out=new DataOutputStream(s.getOutputStream());
//第一步 获取客户端发送的支持的验证规则,包括hash算法,这里选用SHA1作为hash
int length=in.readInt();
in.skipBytes(4);
byte[] clientSupportHash=SocketUtils.readBytes(in,length);
String clientHash=new String(clientSupportHash);
hash=clientHash;
System.out.println("客户端发送了hash算法为:"+clientHash);
//第二步,发送服务器证书到客户端
byte[] certificateBytes=CertifcateUtils.readCertifacates();
privateKey=CertifcateUtils.readPrivateKeys();
System.out.println("发送证书给客户端,字节长度为:"+certificateBytes.length);
System.out.println("证书内容为:" + byte2hex(certificateBytes));
SocketUtils.writeBytes(out, certificateBytes, certificateBytes.length);
System.out.println("获取客户端通过公钥加密后的随机数");
int secureByteLength=in.readInt();
byte[] secureBytes=SocketUtils.readBytes(in, secureByteLength);
System.out.println("读取到的客户端的随机数为:"+byte2hex(secureBytes));
byte secureSeed[]=decrypt(secureBytes);
System.out.println("解密后的随机数密码为:" +byte2hex(secureSeed));
//第三步 获取客户端加密字符串
int skip=in.readInt();
System.out.println("第三步 获取客户端加密消息,消息长度为 :" +skip);
byte[] data=SocketUtils.readBytes(in,skip);
System.out.println("客户端发送的加密消息为 : " +byte2hex(data));
System.out.println("用私钥对消息解密,并计算SHA1的hash值");
byte message[] =decrypt(data,new SecureRandom(secureBytes));
byte serverHash[]=cactHash(message);
System.out.println("获取客户端计算的SHA1摘要");
int hashSkip=in.readInt();
byte[] clientHashBytes=SocketUtils.readBytes(in,hashSkip);
System.out.println("客户端SHA1摘要为 : " + byte2hex(clientHashBytes));
System.out.println("开始比较客户端hash和服务器端从消息中计算的hash值是否一致");
boolean isHashEquals=byteEquals(serverHash,clientHashBytes);
System.out.println("是否一致结果为 : " + isHashEquals);
System.out.println("第一次校验客户端发送过来的消息和摘译一致,服务器开始向客户端发送消息和摘要");
System.out.println("生成密码用于加密服务器端消息,secureRandom : "+byte2hex(secureSeed));
SecureRandom secureRandom=new SecureRandom(secureSeed);
String randomMessage=random();
System.out.println("服务器端生成的随机消息为 : "+randomMessage);
System.out.println("用DES算法并使用客户端生成的随机密码对消息加密");
byte[] desKey=DesCoder.initSecretKey(secureRandom);
key=DesCoder.toKey(desKey);
byte serverMessage[]=DesCoder.encrypt(randomMessage.getBytes(), key);
SocketUtils.writeBytes(out,serverMessage,serverMessage.length);
System.out.println("服务器端发送的机密后的消息为:"+byte2hex(serverMessage)+",加密密码为:"+byte2hex(secureSeed));
System.out.println("服务器端开始计算hash摘要值");
byte serverMessageHash[]=cactHash(randomMessage.getBytes());
System.out.println("服务器端计算的hash摘要值为 :" +byte2hex(serverMessageHash));
SocketUtils.writeBytes(out,serverMessageHash,serverMessageHash.length);
System.out.println("握手成功,之后所有通信都将使用DES加密算法进行加密");
}
}
package httpsmock;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Arrays;
/**
* Created by kingj on 2014/8/13.
*/
public class SocketUtils {
public static void close(Socket s){
try {
s.shutdownInput();
s.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] readBytes(DataInputStream in,int length) throws IOException {
int r=0;
byte[] data=new byte[length];
while(r
以下文章来自:http://snowolf.iteye.com/blog/397693
Coder.java
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算法可选以下多种算法
*
*
* HmacMD5
* HmacSHA1
* HmacSHA256
* HmacSHA384
* HmacSHA512
*
*/
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 {
@Test
public 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));
}
}
CertificateCoder.java
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 Store,JKS)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));
}
}
CertificateCoderTest.java
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";
@Test
public 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));
}
@Test
public 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);
}
@Test
public 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();
}
}
Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC
Java加密技术(二)——对称加密DES&AES
Java加密技术(三)——PBE算法
Java加密技术(四)——非对称加密算法RSA
Java加密技术(五)——非对称加密算法的由来
Java加密技术(六)——数字签名算法DSA
Java加密技术(七)——非对称加密算法最高ECC
Java加密技术(八)——数字证书
Java加密技术(九)——初探SSL
Java加密技术(十)——单向认证
Java加密技术(十一)——双向认证
Java加密技术(十二)——*.PFX(*.p12)&个人信息交换文件