这是一篇总结类的文章,我把一些常用的Java加密技术和核心代码写在这边,供参考。
首先大家要记住现代密码学最重要的原则柯克霍夫原则:
数据的安全基于密钥而不是算法的保密。也就是说即使密码系统的任何细节已为人悉知,只要密匙未洩漏,它也应是安全的。
具体来说:
1. 系统必须可用,非数学上不可译码。
2. 系统不一定要保密,可以轻易落入敌人手中。
3. 密匙必须可以不经书写的资料交换和记忆,且双方可以改变密匙。
4. 系统可以用于电讯。
5. 系统可以转移位置,它的功能必须不用经过几个人之手才可达到。
6. 系统容易使用,不要求使用者的脑力过份操劳或有很多的规则。
一、主要的加密方式代码提供方
JDK:代码在java安装目录下的jre\lib\jce.jar包里;
CC:Apache公司提供的org.apache.commons.codec
主页:http://commons.apache.org/proper/commons-codec/
所需依赖包:
commons-codec
commons-codec
1.9
二、Base64算法
1、从现在加密算法的复杂性来看Base64这种都不好意思说自己是加密,不过对于完全不懂计算机的人来说也够用了。采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
Base64编码一般用于url的处理,或者说任何你不想让普通人一眼就知道是啥的东西都可以用Base64编码处理后再发布在网络上。
package com.rz.secure;
import java.util.Base64;
/**
* Base64算法基于64个基本字符,加密后的string中只包含这64个字符
*/
public class Base64Strategy {
public String encode(String src) {
byte[] encodeBytes = Base64.getEncoder().encode(src.getBytes());
return new String(encodeBytes);
}
public String decode(String src) {
byte[] decodeBytes = Base64.getDecoder().decode(src.getBytes());
return new String(decodeBytes);
}
public static void main(String[] args) {
Base64Strategy bs=new Base64Strategy();
String encrypt=bs.encode("admin");
//密文长度跟加密源字符串有关
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
加密后[8]:YWRtaW4=
解密后:admin
2、Base64编码对应关系表
三、消息摘要算法(Message Digest)1、MD5
package com.rz.secure;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;
/**
* 消息摘要算法
* 消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。HASH函数的抗冲突性使得如果一段明文稍有变化,哪怕只更改该段落的一个字母,通过哈希算法作用后都将产生不同的值。而HASH算法的单向性使得要找到哈希值相同的两个不同的输入消息,在计算上是不可能的。所以数据的哈希值,即消息摘要,可以检验数据的完整性。
*/
public class MD5Strategy {
public String encode_apache(String src) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] encodeBytes = md.digest(src.getBytes());
return Hex.encodeHexString(encodeBytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public String encode_jdk(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
str = buf.toString();
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
public String decode(String src) {
throw new RuntimeException("MD5 no decode");
}
public static void main(String[] args) throws InterruptedException {
MD5Strategy bs = new MD5Strategy();
System.out.println("--------------apache---------------");
String encrypt = bs.encode_apache("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
try {
System.out.println("解密后:" + bs.decode(encrypt));
} catch (Exception e) {
System.err.println(e.getMessage());
}
Thread.sleep(100);
System.out.println("--------------jdk---------------");
String encrypt_jdk = bs.encode_apache("admin");
System.out.printf("加密后[%d]:%s%n", encrypt_jdk.length(),encrypt_jdk);
try {
System.out.println("解密后:" + bs.decode(encrypt_jdk));
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
输出结果:
--------------apache---------------
加密后[32]:21232f297a57a5a743894a0e4a801fc3
MD5 no decode
--------------jdk---------------
加密后[32]:21232f297a57a5a743894a0e4a801fc3
MD5 no decode
2、SHA
package com.rz.secure;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;
/**
* 安全散列算法
*/
public class SHAStrategy
{
public String encode(String src)
{
try
{
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(src.getBytes());
return Hex.encodeHexString(md.digest());
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return null;
}
public String decode(String src)
{
throw new RuntimeException("SHA no decode");
}
public static void main(String[] args) {
SHAStrategy bs=new SHAStrategy();
String encrypt=bs.encode("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
输出结果:
加密后[40]:d033e22ae348aeb5660fc2140aec35850c4da997
Exception in thread "main" java.lang.RuntimeException: SHA no decode
at com.rz.secure.SHAStrategy.decode(SHAStrategy.java:30)
at com.rz.secure.SHAStrategy.main(SHAStrategy.java:39)
四、对称加密
package com.rz.secure;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Hex;
/**
*对称加密算法-des
*/
public class DESStrategy
{
private Cipher cipher;
private SecretKey generateKey;
public String encode(String src)
{
try
{
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56);//size
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();
DESKeySpec desKeySpec = new DESKeySpec(keyBytes);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
generateKey = secretKeyFactory.generateSecret(desKeySpec);
cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, generateKey);
byte[] resultBytes = cipher.doFinal(src.getBytes());
return Hex.encodeHexString(resultBytes);
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public String decode(String src)
{
try
{
cipher.init(Cipher.DECRYPT_MODE, generateKey);
byte[] result = Hex.decodeHex(src.toCharArray());
return new String(cipher.doFinal(result));
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
DESStrategy bs=new DESStrategy();
String encrypt=bs.encode("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
加密后[16]:23a0424ee4e8f390
解密后:admin
2、3DES
3DES,也就是“Triple DES”,中文名“三重数据加密算法”,它相当于是对每个数据块应用三次 DES 加密算法。由于计算机运算能力的增强,原版 DES 密码的密钥长度变得容易被暴力破解;3DES 即是设计用来提供一种相对简单的方法,即通过增加 DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。
package com.rz.secure;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Hex;
/**
* 3DES,也就是“Triple DES”,中文名“三重数据加密算法”,它相当于是对每个数据块应用三次 DES 加密算法。由于计算机运算能力的增强,原版 DES 密码的密钥长度变得容易被暴力破解;3DES 即是设计用来提供一种相对简单的方法,即通过增加 DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。
* @author 18217
*/
public class ThreeDESStrategy
{
private Cipher cipher;
private SecretKey generateKey;
public String encode(String src)
{
try
{
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
keyGenerator.init(168);//size
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();
DESedeKeySpec desKeySpec = new DESedeKeySpec(keyBytes);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
generateKey = secretKeyFactory.generateSecret(desKeySpec);
cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, generateKey);
byte[] resultBytes = cipher.doFinal(src.getBytes());
return Hex.encodeHexString(resultBytes);
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public String decode(String src)
{
try
{
cipher.init(Cipher.DECRYPT_MODE, generateKey);
byte[] result = Hex.decodeHex(src.toCharArray());
return new String(cipher.doFinal(result));
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
ThreeDESStrategy bs=new ThreeDESStrategy();
String encrypt=bs.encode("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
加密后[16]:469b6b27d37c4541
解密后:admin
AES,全称为“Advanced Encryption Standard”,中文名“高级加密标准”,在密码学中又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。AES 加密算法作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。AES 设计有三个密钥长度:128,192,256 位。相对而言,AES 的 128 密钥比 DES 的 56 密钥强了 1021 倍。
package com.rz.secure;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
/**
* 对称加密算法-AES算法
* AES,全称为“Advanced Encryption Standard”,中文名“高级加密标准”,在密码学中又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。AES 加密算法作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。AES 设计有三个密钥长度:128,192,256 位。相对而言,AES 的 128 密钥比 DES 的 56 密钥强了 1021 倍。
* @author 18217
*
*/
public class AESStrategy
{
private Cipher cipher;
private SecretKey generateKey;
public String encode(String src)
{
try
{
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);//size
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();
generateKey = new SecretKeySpec(keyBytes, "AES");
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, generateKey);
byte[] resultBytes = cipher.doFinal(src.getBytes());
return Hex.encodeHexString(resultBytes);
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public String decode(String src)
{
try
{
cipher.init(Cipher.DECRYPT_MODE, generateKey);
byte[] result = Hex.decodeHex(src.toCharArray());
return new String(cipher.doFinal(result));
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
AESStrategy bs=new AESStrategy();
String encrypt=bs.encode("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
加密后[32]:c73544d47ac30b0b210b3870e3915bfa
解密后:admin
4、PBE
PBE算法没有密钥的概念,把口令当做密钥了。因为密钥长短影响算法安全性,还不方便记忆,这里我们直接换成我们自己常用的口令就大大不同了,便于我们的记忆。但是单纯的口令很容易被字典法给穷举出来,所以我们这里给口令加了点“盐”,这个盐和口令组合,想破解就难了。同时我们将盐和口令合并后用消息摘要算法进行迭代很多次来构建密钥初始化向量的基本材料,使破译更加难了。
package com.rz.secure;
/**
* 对称加密算法-PEB算法
* PBE,全称为“Password Base Encryption”,中文名“基于口令加密”,是一种基于密码的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。
* PBE算法没有密钥的概念,把口令当做密钥了。因为密钥长短影响算法安全性,还不方便记忆,这里我们直接换成我们自己常用的口令就大大不同了,便于我们的记忆。但是单纯的口令很容易被字典法给穷举出来,所以我们这里给口令加了点“盐”,这个盐和口令组合,想破解就难了。同时我们将盐和口令合并后用消息摘要算法进行迭代很多次来构建密钥初始化向量的基本材料,使破译更加难了。
* @author 18217
*/
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import org.apache.commons.codec.binary.Hex;
/**
* 基于口令的加密(password),对称 + 消息摘要
*/
public class PBEStrategy
{
private Cipher cipher;
private SecretKey generateKey;
private PBEParameterSpec pbeParameterSpec;
public String encode(String src)
{
try
{
SecureRandom secureRandom = new SecureRandom();
byte[] salt = secureRandom.generateSeed(8);
String password = "amuro";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
generateKey = secretKeyFactory.generateSecret(pbeKeySpec);
pbeParameterSpec = new PBEParameterSpec(salt, 100);
cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE, generateKey, pbeParameterSpec);
byte[] resultBytes = cipher.doFinal(src.getBytes());
return Hex.encodeHexString(resultBytes);
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public String decode(String src)
{
try
{
cipher.init(Cipher.DECRYPT_MODE, generateKey, pbeParameterSpec);
byte[] result = Hex.decodeHex(src.toCharArray());
return new String(cipher.doFinal(result));
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
PBEStrategy bs=new PBEStrategy();
String encrypt=bs.encode("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
加密后[16]:7ca2e0688b25fb2a
解密后:admin
其实,在早在 1978 年的时候,RSA就已经出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。其原理就如上面的工作过程所述。RSA 算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
package com.rz.secure;
/**
* 非对称加密算法-rsa
* @author 18217
*/
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Hex;
public class RSAStrategy
{
private RSAPublicKey rsaPublicKey;
private RSAPrivateKey rsaPrivateKey;
public String encode(String src)
{
try
{
//初始化密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
//私钥加密 公钥解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec
= new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] resultBytes = cipher.doFinal(src.getBytes());
//私钥解密 公钥加密
// X509EncodedKeySpec x509EncodedKeySpec =
// new X509EncodedKeySpec(rsaPublicKey.getEncoded());
// KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
// Cipher cipher = Cipher.getInstance("RSA");
// cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// byte[] resultBytes = cipher.doFinal(src.getBytes());
return Hex.encodeHexString(resultBytes);
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public String decode(String src)
{
try
{
//私钥加密 公钥解密
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(rsaPublicKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] resultBytes = cipher.doFinal(Hex.decodeHex(src.toCharArray()));
//私钥解密 公钥加密
// PKCS8EncodedKeySpec pkcs8EncodedKeySpec
// = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
// KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// Cipher cipher = Cipher.getInstance("RSA");
// cipher.init(Cipher.DECRYPT_MODE, privateKey);
// byte[] resultBytes = cipher.doFinal(Hex.decodeHex(src.toCharArray()));
return new String(resultBytes);
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
RSAStrategy bs=new RSAStrategy();
String encrypt=bs.encode("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
加密后[128]:8cfe1c05bcbeee22c73b4d8306b3ddcf2dd820d34c21d4ec0c5937a80e4f0604c1210e215471d1d945dce8e3d1b1e9abf37349a59c2ee09079232b1baeee5e86
解密后:admin
以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥(SecretKey)对数据加密。这样,在互通了本地密钥(SecretKey)算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯!
package com.rz.secure;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Hex;
/**
* 非对称加密算法-DH
* @author 18217
* DH,全称为“Diffie-Hellman”,他是一种确保共享KEY安全穿越不安全网络的方法,也就是常说的密钥一致协议。由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成“一致”的、可以共享的密钥。也就是由甲方产出一对密钥(公钥、私钥),乙方依照甲方公钥产生乙方密钥对(公钥、私钥)。
以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥(SecretKey)对数据加密。这样,在互通了本地密钥(SecretKey)算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯!
*/
public class DHStrategy {
private Cipher cipher;
private SecretKey receiverSecretKey;
public String encode(String src) {
try {
// 初始化发送方密钥
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
senderKeyPairGenerator.initialize(512);
KeyPair senderkeyPair = senderKeyPairGenerator.generateKeyPair();
PrivateKey senderPrivateKey = senderkeyPair.getPrivate();
byte[] senderPublicKeyBytes = senderkeyPair.getPublic().getEncoded();// 发送方的公钥
// 初始化接收方密钥,用发送方的公钥
KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyBytes);
PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
receiverKeyPairGenerator.initialize(dhParameterSpec);
KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate();
byte[] receiverPublicKeyBytes = receiverKeyPair.getPublic().getEncoded();
KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
receiverKeyAgreement.init(receiverPrivateKey);
receiverKeyAgreement.doPhase(receiverPublicKey, true);
receiverSecretKey = receiverKeyAgreement.generateSecret("DES");
// 发送方拿到接收方的public key就可以做加密了
KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyBytes);
PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
senderKeyAgreement.init(senderPrivateKey);
senderKeyAgreement.doPhase(senderPublicKey, true);
SecretKey senderSecretKey = senderKeyAgreement.generateSecret("DES");
if (Objects.equals(receiverSecretKey, senderSecretKey)) {
cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, senderSecretKey);
byte[] result = cipher.doFinal(src.getBytes());
return Hex.encodeHexString(result);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String decode(String src) {
try {
cipher.init(Cipher.DECRYPT_MODE, receiverSecretKey);
byte[] result = Hex.decodeHex(src.toCharArray());
return new String(cipher.doFinal(result));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
DHStrategy bs=new DHStrategy();
String encrypt=bs.encode("admin");
System.out.printf("加密后[%d]:%s%n", encrypt.length(),encrypt);
System.out.println("解密后:"+bs.decode(encrypt));
}
}
java.security.NoSuchAlgorithmException: Unsupported secret key algorithm: DES
at com.sun.crypto.provider.DHKeyAgreement.engineGenerateSecret(DHKeyAgreement.java:387)
at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:648)
at com.rz.secure.DHStrategy.encode(DHStrategy.java:51)
at com.rz.secure.DHStrategy.main(DHStrategy.java:91)
Exception in thread "main" java.lang.NullPointerException
at com.rz.secure.DHStrategy.main(DHStrategy.java:92)
该加密算法笔者还在调试中。。。,待调试成功后补全该加密算法。
六、数字签名证书
非对称加密已经灰常安全了,但是还有一个破绽:
服务器A公布了自己的公钥,我的电脑是用服务器A的公钥加密数据后再发给服务器A的;这时候服务器B侵入了我的电脑,把我用来加密的公钥换成了它的公钥,于是我发出去的数据就会被服务器B的私钥破解了。肿么防止公钥被篡改呢?
对,我们想到了前面的消息摘要,服务器A把公钥丢给我的时候,同时去CA申请一份数字证书,其实主要就是公钥的消息摘要,有了这份证书,当我再用公钥加密的时候,我就可以先验证一下当前的公钥是否确定是服务器A发送给我的。
这里就贴一种RSA的:
package com.rz.secure;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* 数字签名证书
* @author 18217
*/
public class RSASign {
public static boolean verifySign(String src)
{
try
{
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
PrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
PKCS8EncodedKeySpec pkcs8EncodedKeySpec
= new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(privateKey);
signature.update(src.getBytes());
//生成签名bytes
byte[] signBytes = signature.sign();
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
signature = Signature.getInstance("MD5withRSA");
signature.initVerify(publicKey);
signature.update(src.getBytes());
boolean isVerified = signature.verify(signBytes);
return isVerified;
}
catch(Exception e)
{
e.printStackTrace();
}
return false;
}
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException {
RSASign bs = new RSASign();
System.out.println(bs.verifySign("admin"));
}
}
true
关于数字签名和非对称加密算法的使用,还看到一个非常棒的例子,分享给大家:
您一定已经注意到了,这个使用我的私钥进行了加密的借条,具有了防篡改、防抵赖的特性,并且可以作为程堂证供,就跟我对这个借条进行了“签名”的效果是一样的。对了,“使用我的私钥对借条进行加密”的过程就叫做数字签名。
ok,加密算法告一段落。