JAVA中实现非对称加密DH算法类
1:项目需要数据加密,故学习研究了下DH算法,在这里做点记录
2:DH算法原理: 请求端 与 被请求端 使用同样的**生成方法,请求端初始化一对**分为公钥和私钥,将公钥作为参数去请求被请求端.被请求端接受请求端的公钥,通过此公钥初始化生成一对**.同时将公钥返回给请求端.与此同时两端都要以对方回传的公钥与己方生成的私钥组装本地**.两方生成的本地**应该是一样的.两方的加密解密都通过本地**来处理.
3:加密解密类代码:(包含:无参初始化**方法及有参初始化**方法) … 欢迎留言讨论指正
import java.security.*;
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;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import net.sf.json.JSONObject;
import org.apache.commons.net.util.Base64;
/**
-
非对称加密算法DH算法组件
-
非对称算法一般是用来传送对称加密算法的**来使用的,所以这里我们用DH算法模拟**传送
-
对称加密AES算法继续做我们的数据加解密
-
@author
-
*/
public class DHUtilXM {
//非对称**算法
public static final String KEY_ALGORITHM=“DH”;//本地**算法,即对称加密算法。可选des,aes,desede
public static final String SECRET_ALGORITHM=“AES”;/**
- **长度,DH算法的默认**长度是1024
- **长度必须是64的倍数,在512到1024位之间
- */
private static final int KEY_SIZE=512;
//公钥
private static final String PUBLIC_KEY=“DHPublicKey”;
//私钥
private static final String PRIVATE_KEY=“DHPrivateKey”;/**
- 初始化甲方**
- @return Map 甲方**的Map
- */
public static Map<String,Object> initKey() throws Exception{
//实例化**生成器
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);
//初始化**生成器
keyPairGenerator.initialize(KEY_SIZE);
//生成**对
KeyPair keyPair=keyPairGenerator.generateKeyPair();
//甲方公钥
DHPublicKey publicKey=(DHPublicKey) keyPair.getPublic();
//甲方私钥
DHPrivateKey privateKey=(DHPrivateKey) keyPair.getPrivate();
//将**存储在map中
Map<String,Object> keyMap=new HashMap<String,Object>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
-
初始化乙方**
-
@param key 甲方**(这个**是通过第三方途径传递的)
-
@return Map 乙方**的Map
-
/
public static Map<String,Object> initKey(byte[] key) throws Exception{
//解析甲方的公钥
//转换公钥的材料
X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
//实例化**工厂
KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//产生公钥
PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
//由甲方的公钥构造乙方**
DHParameterSpec dhParamSpec=((DHPublicKey)pubKey).getParams();
//实例化**生成器
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
//初始化**生成器
keyPairGenerator.initialize(dhParamSpec);
//产生**对
KeyPair keyPair=keyPairGenerator.genKeyPair();
//乙方公钥
DHPublicKey publicKey=(DHPublicKey)keyPair.getPublic();
//乙方私钥
DHPrivateKey privateKey=(DHPrivateKey)keyPair.getPrivate();
//将**存储在Map中
Map<String,Object> keyMap=new HashMap<String,Object>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/* -
加密
-
@param data
-
待加密数据
-
@param key
-
**
-
@return byte[] 加密数据
-
@throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
byte[] keyBytes = new byte[16];
byte[] ivBytes = new byte[16];
System.arraycopy(key, 0, keyBytes, 0, 16);
System.arraycopy(key, 16, ivBytes, 0, 16);AlgorithmParameters params = AlgorithmParameters.getInstance(SECRET_ALGORITHM);
params.init(new IvParameterSpec(ivBytes));//转化为**
Key keyInfo = new SecretKeySpec(keyBytes,SECRET_ALGORITHM);
//Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”);
//设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, keyInfo,params);
return cipher.doFinal(data);
}
/**
-
解密
-
@param data
-
待解密数据
-
@param
-
@return byte[] 解密数据
-
@throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] keyInfo) throws Exception {
byte[] keyBytes = new byte[16];
byte[] ivBytes = new byte[16];
System.arraycopy(keyInfo, 0, keyBytes, 0, 16);
System.arraycopy(keyInfo, 16, ivBytes, 0, 16);AlgorithmParameters params = AlgorithmParameters.getInstance(SECRET_ALGORITHM);
params.init(new IvParameterSpec(ivBytes));Key key = new SecretKeySpec(keyBytes,SECRET_ALGORITHM);
Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”);
//设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, key,params);
return cipher.doFinal(data);
}
/**
- 构建**
- @param publicKey 公钥
- @param privateKey 私钥
- @return byte[] 本地**
-
/
public static byte[] getSecretKey(byte[] publicKey,byte[] privateKey) throws Exception{
//实例化**工厂
KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//初始化公钥
//**材料转换
X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(publicKey);
//产生公钥
PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
//初始化私钥
//**材料转换
PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(privateKey);
//产生私钥
PrivateKey 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.getEncoded();
}
/* - 取得私钥
- @param keyMap **map
- @return byte[] 私钥
-
/
public static byte[] getPrivateKey(Map<String,Object> keyMap){
Key key=(Key)keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/* - 取得公钥
- @param keyMap **map
- @return byte[] 公钥
- */
public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{
Key key=(Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
public static String parseByte2HexStr(byte[] buf) {
if (buf == null) {
return null;
}
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = “0” + hex;
}
sbf.append(hex.toUpperCase());
}return sbf.toString();
}
/**-
@param args
-
@throws Exception
*/
public static void main(String[] args) throws Exception {//生成甲方的**对
Map<String,Object> keyMap1=DHUtilXM.initKey();
//甲方的公钥
byte[] publicKey1=DHUtilXM.getPublicKey(keyMap1);
//甲方的私钥
byte[] privateKey1=DHUtilXM.getPrivateKey(keyMap1);
JSONObject S = new JSONObject();
S.put(“y”,Base64.encodeBase64String(publicKey1));
System.out.println(S);
System.out.println((String)S.get(“y”));System.out.println(“甲方公钥:”+Base64.encodeBase64String(publicKey1));
String publicKey11=Base64.encodeBase64String(publicKey1).toString();System.out.println(“甲方私钥:”+Base64.encodeBase64String(privateKey1));
//由甲方的公钥产生的**对
Map<String,Object> keyMap2=DHUtilXM.initKey(Base64.decodeBase64(Base64.encodeBase64String(publicKey1)));//这里 小蜜传的公钥:要Base64.encodeBase64String转下
byte[] publicKey2=DHUtilXM.getPublicKey(keyMap2);
byte[] privateKey2=DHUtilXM.getPrivateKey(keyMap2);
System.out.println(“乙方公钥:”+Base64.encodeBase64String(publicKey2));
System.out.println(“乙方私钥:”+Base64.encodeBase64String(privateKey2));//组装甲方的本地加***,由乙方的公钥和甲方的私钥组合而成
byte[] key1=DHUtilXM.getSecretKey(publicKey2, privateKey1);byte[] key3=DHUtilXM.getSecretKey(Base64.decodeBase64(Base64.encodeBase64String(publicKey2)), privateKey1);
System.out.println(“甲方的本地**:”+Base64.encodeBase64String(key3));//组装乙方的本地加***,由甲方的公钥和乙方的私钥组合而成
byte[] key2=DHUtilXM.getSecretKey(Base64.decodeBase64(Base64.encodeBase64String(publicKey1)), privateKey2); //这里 服务端传的公钥:已经Base64.encodeBase64String转了
System.out.println("乙方的本地**: "+Base64.encodeBase64String(key2));System.out.println(“**对构造完毕,开始进行加密数据的传输=");
String str="{“token” : “test”,“uid”: “168”,“pwd”: “888888”,“needdata”:false}";
System.out.println("/n=甲方向乙方发送加密数据========”);
System.out.println(“原文:”+str);
System.out.println("=使用甲方本地**对进行数据加密====");
//甲方进行数据的加密
byte[] code1= DHUtilXM.encrypt(str.getBytes(), Base64.decodeBase64(Base64.encodeBase64String(key3)));
System.out.println(“加密后的数据:”+Base64.encodeBase64String(code1));
System.out.println(“加密后的数据:”+ Base64.encodeBase64String(Base64.decodeBase64(Base64.encodeBase64String(code1))));System.out.println("=使用乙方本地**对数据进行解密====");
//乙方进行数据的解密
byte[] decode1=DHUtilXM.decrypt(code1, Base64.decodeBase64(Base64.encodeBase64String(key2)));
System.out.println(“乙方解密后的数据:”+new String(decode1));System.out.println("=反向进行操作,乙方向甲方发送数据====/n/n");
str="{token:test,data:wudi,msg:test下中文}";
System.out.println(“原文:”+str);
//使用乙方本地**对数据进行加密
byte[] code2= DHUtilXM.encrypt(str.getBytes(), Base64.decodeBase64(Base64.encodeBase64String(key2)));
System.out.println("=使用乙方本地**对进行数据加密====");
System.out.println(“加密后的数据:”+Base64.encodeBase64String(code2));System.out.println("=乙方将数据传送给甲方==========");
System.out.println("=使用甲方本地**对数据进行解密====");//甲方使用本地**对数据进行解密
byte[] decode2=DHUtilXM.decrypt(code2, Base64.decodeBase64(Base64.encodeBase64String(key1)));System.out.println(“甲方解密后的数据:”+new String(decode2));
}
}
4:应用注意事项
两方传递的公有**应注意处理换行符之类的,否则很可能造成生成的本地**不一致…
5:结果展示