JAVA加密算法- 非对称加密算法(DH,RSA)的详细介绍
非对称密码概念
1、与对称加密算法的主要差别在于,加密和解密的密钥不相同,一个公开(公钥),一个保密(私钥)。主要解决了对称加密算法密钥分配管理的问题,提高了算法安全性。
2、非对称加密算法的加密、解密的效率比较低。在算法设计上,非对称加密算法对待加密的数据长度有着苛刻的要求。例如RSA算法要求待加密的数据不得大于53个字节。
3、非对称加密算法主要用于交换对称加密算法的密钥,而非数据交换
4、java6提供实现了DH和RSA两种算法。BouncyCastle提供了E1Gamal算法支持。除了上述三种算法还有一个ECC算法,目前没有相关的开源组件提供支持
需要两个密钥进行加密或解密,分为公钥和私钥
特点:安全性高,速度慢
用途
【密钥交换(DH)】
双方在没有确定共同密钥的情况下,生成密钥,不提供加密工作,加解密还需要其他对称加密算法实现
DH算法示例
importjavax.crypto.KeyAgreement;
importjavax.crypto.interfaces.DHPrivateKey;
importjavax.crypto.interfaces.DHPublicKey;
importjavax.crypto.spec.DHParameterSpec;
importjava.security.*;
importjava.security.spec.PKCS8EncodedKeySpec;
importjava.security.spec.X509EncodedKeySpec;
importjava.util.HashMap;
importjava.util.Map;
//1生成源密钥
//2把源公钥交给目标,目标通过源公钥,生成目标公钥和私钥
//3把目标公钥交给源
//4双方使用对方的公钥和和自己的私钥,生成本地密钥
//5如果双方生成本地密钥相同则完成密钥交换
publicclassDHUtil{
publicstaticfinalStringPUBLIC_KEY="DH_Public_Key";
publicstaticfinalStringPRIVATE_KEY="DH_Private_key";
/**
*生成源密钥对
*@return
*@throwsException
*/
publicstaticMap<String,Object>initSourceKey()throwsException{
//创建KeyPairGenerator的实例,选用DH算法
KeyPairGeneratorkeyPairGenerator=KeyPairGenerator.getInstance("DH");
//初始化密钥长度,默认1024,可选范围512-65536&64的倍数
keyPairGenerator.initialize(1024);
//生成密钥对
KeyPairkeyPair=keyPairGenerator.generateKeyPair();
DHPublicKeydhPublicKey=(DHPublicKey)keyPair.getPublic();
DHPrivateKeydhPrivateKey=(DHPrivateKey)keyPair.getPrivate();
//将密钥对放入Map
Map<String,Object>keyMap=newHashMap<String,Object>();
keyMap.put(PUBLIC_KEY,dhPublicKey);
keyMap.put(PRIVATE_KEY,dhPrivateKey);
returnkeyMap;
}
/**
*通过源公钥生成目标密钥对
*@paramsourcePublicKey
*@return
*@throwsException
*/
publicstaticMap<String,Object>initTargetKey(byte[]sourcePublicKey)throwsException{
KeyFactorykeyFactory=KeyFactory.getInstance("DH");
//通过源公钥,生成keySpec,使用KeyFactory生成源PublicKey相关信息
X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(sourcePublicKey);
DHPublicKeysourcePublic=(DHPublicKey)keyFactory.generatePublic(keySpec);
DHParameterSpecdhPublicKeyParams=sourcePublic.getParams();
KeyPairGeneratorkeyPairGenerator=KeyPairGenerator.getInstance("DH");
keyPairGenerator.initialize(dhPublicKeyParams);
KeyPairkeyPair=keyPairGenerator.generateKeyPair();
DHPublicKeydhPublicKey=(DHPublicKey)keyPair.getPublic();
DHPrivateKeydhPrivateKey=(DHPrivateKey)keyPair.getPrivate();
//将密钥对放入Map
Map<String,Object>keyMap=newHashMap<String,Object>();
keyMap.put(PUBLIC_KEY,dhPublicKey);
keyMap.put(PRIVATE_KEY,dhPrivateKey);
returnkeyMap;
}
/**
*使用一方的公钥和另一方的私钥,生成本地密钥
*@return
*/
publicstaticbyte[]generateLocalSecretKey(byte[]aPublicKey,byte[]bPrivateKey)throwsException{
KeyFactorykeyFactory=KeyFactory.getInstance("DH");
//通过A公钥,生成keySpec,使用KeyFactory生成APublicKey相关信息
X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(aPublicKey);
PublicKeypublicKey=keyFactory.generatePublic(keySpec);
//通过B私钥,生成BPrivateKey相关信息
PKCS8EncodedKeySpecpkcs8EncodedKeySpec=newPKCS8EncodedKeySpec(bPrivateKey);
PrivateKeyprivateKey=keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//通过KeyAgreement对A的PublicKey和B的PrivateKey进行加密
KeyAgreementkeyAgreement=KeyAgreement.getInstance("DH");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey,true);
returnkeyAgreement.generateSecret("AES").getEncoded();//算法使用对称加密算法(DES,DESede,AES)
//returnkeyAgreement.generateSecret();//也可以不选择算法,使用默认方法计算
}
//获取公钥字节数组
publicstaticbyte[]getPublicKey(Map<String,Object>map){
return((DHPublicKey)map.get(PUBLIC_KEY)).getEncoded();
}
//获取私钥字节数组
publicstaticbyte[]getPrivateKey(Map<String,Object>map){
return((DHPrivateKey)map.get(PRIVATE_KEY)).getEncoded();
}
publicstaticvoidmain(String[]args)throwsException{
byte[]source_public_key;
byte[]source_private_key;
byte[]source_local_key;
byte[]target_public_key;
byte[]target_private_key;
byte[]target_local_key;
Map<String,Object>sourceKey=initSourceKey();
source_public_key=getPublicKey(sourceKey);
source_private_key=getPrivateKey(sourceKey);
System.out.println("源公钥:"+BytesToHex.fromBytesToHex(source_public_key));
System.out.println("源私钥:"+BytesToHex.fromBytesToHex(source_private_key));
Map<String,Object>targetKey=initTargetKey(getPublicKey(sourceKey));
target_public_key=getPublicKey(targetKey);
target_private_key=getPrivateKey(targetKey);
System.out.println("目标公钥:"+BytesToHex.fromBytesToHex(target_public_key));
System.out.println("目标私钥:"+BytesToHex.fromBytesToHex(target_private_key));
source_local_key=generateLocalSecretKey(target_public_key,source_private_key);
target_local_key=generateLocalSecretKey(source_public_key,target_private_key);
System.out.println("源本地密钥:"+BytesToHex.fromBytesToHex(source_local_key));
System.out.println("目标本地密钥:"+BytesToHex.fromBytesToHex(target_local_key));
}
}
【加密/解密(RSA)】【数字签名(RSA)】
RSA算法晚于DH算法,这五个字母全都是人名首字母.DH算法是第一个非对称密码体系.
RSA算法运算速度慢,不适宜加密大量数据.一种解决方案是,将RSA跟对称加密方式混合使用,将数据使用对称加密方式加密,对称加密的密钥使用RSA算法加密,因为密钥很短,所以时间费不了太多.实际上,对称加密方式唯一的弊端就是密钥不好传递,对称加密方式也很难破解.
RSA的适用情景一:
(1)服务器生成一个公钥和一个私钥,把公钥公开了.
(2)客户端使用公钥把数据进行加密,上交服务器.别人是没法理解加密后的数据的.
(3)服务器使用私钥将数据解密,查看用户提交的数据.
这种情景下,公钥像是一个信箱,每个人都可以往这个信箱里面放信,但是这个信箱里面的信只有掌握信箱钥匙的人才能开箱查看.
RSA适用情景二:
(1)皇上生成一个公钥和一个密钥,把公钥公开了.
(2)皇上发布了一封诏书,昭告天下.诏书右下角有两串数字,第一串数字是一个随机串,第二串数字是用私钥加密第一串数字所得的结果.
(3)有人不相信这诏书是皇上写的,就把第二串数字使用公钥解密,解密之后发现跟第一串数字一样,说明确实是皇上写的,因为一般人没有密钥,也就没法加密那些能够用公钥解密的数据.
这种情境下,公钥用于解密,私钥用于加密,这可以用于发布公告时,证明这个公告确实是某个人发的.相当于签名.
实际上,签名没有必要特别长,一般情况下,签名是定长的,要想定长,可以使用MessageDigest算法,如MD5和SHA系列.所以就有了多种签名算法,如MD5withRSA等.
RSA加密/解密示例
importjavax.crypto.Cipher;
importjava.security.KeyPair;
importjava.security.KeyPairGenerator;
importjava.security.PublicKey;
importjava.security.interfaces.RSAPrivateKey;
importjava.security.interfaces.RSAPublicKey;
importjava.util.HashMap;
importjava.util.Map;
/**
*RSA加密工具
*/
publicclassRSAUtil{
publicstaticfinalStringPUBLIC_KEY="RSA_Public_Key";
publicstaticfinalStringPRIVATE_KEY="RSA_Private_Key";
/**
*初始化密钥
*@return
*@throwsException
*/
publicstaticMap<String,Object>initKey()throwsException{
KeyPairGeneratorkeyPairGenerator=KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);//512-65536&64的倍数
KeyPairkeyPair=keyPairGenerator.generateKeyPair();
RSAPublicKeypublicKey=(RSAPublicKey)keyPair.getPublic();
RSAPrivateKeyprivateKey=(RSAPrivateKey)keyPair.getPrivate();
Map<String,Object>keyMap=newHashMap<String,Object>();
keyMap.put(PUBLIC_KEY,publicKey);
keyMap.put(PRIVATE_KEY,privateKey);
returnkeyMap;
}
publicstaticRSAPublicKeygetPublicKey(Map<String,Object>keyMap){
return(RSAPublicKey)keyMap.get(PUBLIC_KEY);
}
publicstaticRSAPrivateKeygetPrivateKey(Map<String,Object>keyMap){
return(RSAPrivateKey)keyMap.get(PRIVATE_KEY);
}
/**
*使用公钥对数据进行加密
*@paramdata
*@parampublicKey
*@return
*@throwsException
*/
publicstaticbyte[]encrypt(byte[]data,RSAPublicKeypublicKey)throwsException{
Ciphercipher=Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
returncipher.doFinal(data);
}
/**
*使用私钥解密
*@paramdata
*@paramprivateKey
*@return
*@throwsException
*/
publicstaticbyte[]decrypt(byte[]data,RSAPrivateKeyprivateKey)throwsException{
Ciphercipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,privateKey);
returncipher.doFinal(data);
}
publicstaticvoidmain(String[]args)throwsException{
Stringdata="周杰伦-东风破";
Map<String,Object>keyMap=initKey();
byte[]miwen=encrypt(data.getBytes(),getPublicKey(keyMap));
System.out.println("加密后的内容:"+BytesToHex.fromBytesToHex(miwen));
byte[]plain=decrypt(miwen,getPrivateKey(keyMap));
System.out.println("解密后的内容:"+newString(plain));
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。