一,Base64
算法的实现:
定义:基于64个字符的编码算法
-JDK
jdk1.6之前用sun/oracle jdk里面的sun.misc.BASE64Encoder,注意不能直接调用,需要加入%JAVA_HOME%\jre\lib\rt.jar
public static void jdkBase64() throws IOException{
BASE64Encoder encoder = new BASE64Encoder();
String encode = encoder.encode(src.getBytes());
System.out.println("encode:"+encode);
BASE64Decoder decoder = new BASE64Decoder();
byte[] bytes = decoder.decodeBuffer(encode);
System.out.println("decode:"+new String(bytes));
}
jdk1.6的实现:
public static void jdk1_6Base64(){
String encode = DatatypeConverter.printBase64Binary(src.getBytes());
System.out.println(encode);
byte[] decode = DatatypeConverter.parseBase64Binary(encode);
System.out.println("encode:"+new String(decode));
}
jdk1.8的实现:
public static void jdk1_8Base64(){
byte[] encode = java.util.Base64.getEncoder().encode(src.getBytes());
System.out.println("encode:"+new String(encode));
byte[] decode = java.util.Base64.getDecoder().decode(encode);
System.out.println("encode:"+new String(decode));
}
-Commons Codec
public static void commonsCodecBase64(){
byte[] encodeBytes = Base64.encodeBase64(src.getBytes());
System.out.println("encode:"+new String(encodeBytes));
byte[] decodeBytes = Base64.decodeBase64(encodeBytes);
System.out.println("decode:"+new String(decodeBytes));
}
-BuuncyCastle的实现:
public static void bouncyCastleBase64(){
byte[] encodeBytes =org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
System.out.println("encode:"+new String(encodeBytes));
byte[] decodeBytes = org.bouncycastle.util.encoders.Base64.decode(encodeBytes);
System.out.println("decode:"+new String(decodeBytes));
}
应用场景:e-mail,密钥,证书文件
二,消息摘要算法(数字签名的核心算法)
1,MD(Message Digest) 消息摘要
2,SHA(Secure Hash Algorithm) 安全散列
2,MAC(Message Authentication Code) 消息认证码
主要作用:验证数据的完整性
MD家族:(128位摘要信息)
-MD2,MD4,MD5
MD2 JDK的实现:
public static void jdkMD2(){
try {
MessageDigest md = MessageDigest.getInstance("MD2");
byte[] md2Bytes = md.digest(src.getBytes());
System.out.println("jdk md2:"+bytes2hex(md2Bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public static void commonsCodecMD2(){
//commonsCodec并没有自己实现md2算法,而是使用的jdk的实现
System.out.println("commonsCodec md2:"+DigestUtils.md2Hex(src.getBytes()));
}
MD4 Bouncy Castle(jdk 并没有提供md4)的实现:
public static void bouncyCastleMD4(){
//提供Providerjdk
Security.addProvider(new BouncyCastleProvider());
try {
MessageDigest md4 = MessageDigest.getInstance("MD4");
byte[] md4Bytes = md4.digest(src.getBytes());
System.out.println("bouncyCastle md4:"+bytes2hex(md4Bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
//bouncyCastle自己的md4的实现
Digest digest = new MD4Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] md4Bytes = new byte[digest.getDigestSize()];
digest.doFinal(md4Bytes, 0);
System.out.println("bouncyCastle md4:"+bytes2hex(md4Bytes));
}
MD5 JDK的实现:
public static void jdkMD5(){
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] md5Bytes = md.digest(src.getBytes());
System.out.println("jdk md5:"+bytes2hex(md5Bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public static void commonsCodecMD5(){
//commonsCodec并没有自己实现md5算法,而是使用的jdk的实现
System.out.println("commonsCodec md5:"+DigestUtils.md5Hex(src.getBytes()));
}
SHA:
-SHA1:160位 JDK
-SHA2(SHA-224(224位) JDK,Bouncy Castle, SHA-256 (256位) jdk, SHA-384(384位) jdk, SHA-512(512位) jdk)
SHA1 JDK:
public static void jdkSHA1() {
try {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(src.getBytes());
byte[] bytes = md.digest();
System.out.println("jdkSHA1:" + bytes2hex(bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
SHA-224 JDK,BouncyCastle的代码实现:
public static void jdkSHA224() {
try {
MessageDigest md = MessageDigest.getInstance("SHA-224");
md.update(src.getBytes());
byte[] bytes = md.digest();
System.out.println("jdkSHA224:" + bytes2hex(bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public static void bouncyCastleSHA224() {
try {
Security.addProvider(new BouncyCastlePQCProvider());
MessageDigest md = MessageDigest.getInstance("SHA-224");
md.update(src.getBytes());
byte[] bytes = md.digest();
System.out.println("bouncyCastleSHA224:" + bytes2hex(bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
Digest digest = new SHA224Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] bytes = new byte[digest.getDigestSize()];
digest.doFinal(bytes, 0);
System.out.println("bouncyCastleSHA224:" + bytes2hex(bytes));
}
SHA-256 BouncyCastle的代码实现:
public static void bouncyCastleSHA256() {
Digest digest = new SHA256Digest();
digest.update(src.getBytes(), 0, src.getBytes().length);
byte[] bytes = new byte[digest.getDigestSize()];
digest.doFinal(bytes, 0);
System.out.println("bouncyCastleSHA256:" + bytes2hex(bytes));
}
SHA-384 JDK的代码实现:
public static void jdkSHA384(){
try {
MessageDigest md = MessageDigest.getInstance("SHA-384");
md.update(src.getBytes());
byte[] bytes = md.digest();
System.out.println("jdkSHA384" + bytes2hex(bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
SHA512 CommonsCodec的代码实现:
public static void CommonsCodec512() {
System.out.println("CommonsCodec512:" + DigestUtils.sha512Hex(src));
}
MAC(HMAC (keyed-hash message authentication code 含有密钥的散列函数算法))
融合MD,SHA
-MD系列:HmacMD2(128位,Bouncy Castle),HmacMD4(128位,Bouncy Castle),HmacMD5(128位,jdk)
-SHA系列:HmacSHA1(160位,jdk),HmacSHA224(224位,Bouncy Castle),HmacSHA256(256位,jdk),HmacSHA384(384位,jdk),HmacSHA512(512位,jdk)
HmacMD5 JDK的代码实现:
public static void jdkHmacMD5() {
try {
// 初始化KeyGenerator
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
// 产生密钥
SecretKey secretKey = keyGenerator.generateKey();
// 获得密钥
byte[] key = secretKey.getEncoded();
// 还原密钥
SecretKey restoreSecretKey = new SecretKeySpec(key, "HmacMD5");
// 实例化MAC
Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());
// 初始MAC
mac.init(restoreSecretKey);
// 执行摘要
byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
System.out.println("jdkhmacmd5:" + bytes2hex(hmacMD5Bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
HmacMD5 bouncyCastle的代码实现:
public static void bouncyCastleHmacMD5() {
HMac hmac = new HMac(new MD5Digest());
hmac.init(new KeyParameter(Hex.decode("aaaaaaaaaa")));
hmac.update(src.getBytes(), 0, src.getBytes().length);
byte[] hmacMD5Bytes = new byte[hmac.getMacSize()];
hmac.doFinal(hmacMD5Bytes, 0);
System.out.println("bouncyCastleHmacMD5:" + bytes2hex(hmacMD5Bytes));
}
这2中由于密钥的不同摘要之后的结果不一样。
如果jdk的实现也是10个a那么摘要的结果就和bouncy Castle一样:
public static void jdkHmacMD5() {
try {
// 初始化KeyGenerator
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
// 产生密钥
SecretKey secretKey = keyGenerator.generateKey();
// 获得密钥
// byte[] key = secretKey.getEncoded();s
byte[] key = hexStr2ByteArray("aaaaaaaaaa");
// 还原密钥
SecretKey restoreSecretKey = new SecretKeySpec(key, "HmacMD5");
// 实例化MAC
Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());
// 初始MAC
mac.init(restoreSecretKey);
// 执行摘要
byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
System.out.println("jdkhmacmd5:" + bytes2hex(hmacMD5Bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
byte数组转16进制的的实现:
private static final String HEX = "0123456789abcdef";
public static String bytes2hex(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
// 取出这个字节的高4位,然后与0x0f与运算,得到一个0-15之间的数据,通过HEX.charAt(0-15)即为16进制数
sb.append(HEX.charAt((b >> 4) & 0x0f));
// 取出这个字节的低位,与0x0f与运算,得到一个0-15之间的数据,通过HEX.charAt(0-15)即为16进制数
sb.append(HEX.charAt(b & 0x0f));
}
return sb.toString();
}
16进制转byte数组的实现:
public static byte[] hexStr2ByteArray(String hexString) {
if (hexString == null || hexString.equals(""))
throw new IllegalArgumentException("this hexString must not be empty");
hexString = hexString.toLowerCase();
final byte[] byteArray = new byte[hexString.length() / 2];
int k = 0;
for (int i = 0; i < byteArray.length; i++) {
// 因为是16进制,最多只会占用4位,转换成字节需要两个16进制的字符,高位在先
// 将hex 转换成byte "&" 操作为了防止负数的自动扩展
// hex转换成byte 其实只占用了4位,然后把高位进行右移四位
// 然后“|”操作 低四位 就能得到 两个 16进制数转换成一个byte.
//
byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
byteArray[i] = (byte) (high << 4 | low);
k += 2;
}
return byteArray;
}
三,对称加密算法:
加密密钥=解密密钥
-DES
-3DES
-AES
-PBE
-IDEA
DES(Data Encryption Standard) 数据加密标准(新项目不推荐使用,安全性较差)
JDK代码实现:
public static void jdkDES(){
try {
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56);
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
//key转换
DESKeySpec desKeySpec = new DESKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 Cipher.getInstance("加解密算法/工作方式/填充方式")
Cipher ciper = Cipher.getInstance("DES/ECB/PKCS5Padding");
ciper.init(Cipher.ENCRYPT_MODE, convertSecretKey);
byte[] bytes = ciper.doFinal(src.getBytes());
System.out.println("jdk des encrypt:"+Hex.encodeHexString(bytes));
//解密
ciper.init(Cipher.DECRYPT_MODE,convertSecretKey);
bytes = ciper.doFinal(bytes);
System.out.println("jdk des decrypt:"+new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
bouncyCastle的代码实现:
public static void bouncyCastleDES(){
try {
Security.addProvider(new BouncyCastleProvider());
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES","BC");
keyGenerator.init(56);
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
//key转换
DESKeySpec desKeySpec = new DESKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES","BC");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 Cipher.getInstance("加解密算法/工作方式/填充方式")
Cipher ciper = Cipher.getInstance("DES/ECB/PKCS5Padding","BC");
ciper.init(Cipher.ENCRYPT_MODE, convertSecretKey);
byte[] bytes = ciper.doFinal(src.getBytes());
System.out.println("bouncyCastle des encrypt:"+Hex.encodeHexString(bytes));
//解密
ciper.init(Cipher.DECRYPT_MODE,convertSecretKey);
bytes = ciper.doFinal(bytes);
System.out.println("bouncyCastle des decrypt:"+new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
DES的算法应用流程图:
3DES(3重DES)
出现的原因:DES违反了柯克霍夫原则(DES加密算法半公开)
3DES的好处:
1,密钥长度增强
2,迭代次数增多
JDK
public static void jdk3DES(){
try {
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
// keyGenerator.init(168);
keyGenerator.init(new SecureRandom());//根据不同的算法生成相应长度的key
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
//key转换
DESedeKeySpec desKeySpec = new DESedeKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 Cipher.getInstance("加解密算法/工作方式/填充方式")
Cipher ciper = Cipher.getInstance("DESede/ECB/PKCS5Padding");
ciper.init(Cipher.ENCRYPT_MODE, convertSecretKey);
byte[] bytes = ciper.doFinal(src.getBytes());
System.out.println("jdk 3des encrypt:"+Hex.encodeHexString(bytes));
//解密
ciper.init(Cipher.DECRYPT_MODE,convertSecretKey);
bytes = ciper.doFinal(bytes);
System.out.println("jdk 3des decrypt:"+new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
bouncyCastle
public static void bouncyCastle3DES(){
try {
Security.addProvider(new BouncyCastleProvider());
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede","BC");
// keyGenerator.init(168);
keyGenerator.init(new SecureRandom());//根据不同的算法生成相应长度的key
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
//key转换
DESedeKeySpec desKeySpec = new DESedeKeySpec(byteKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede","BC");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 Cipher.getInstance("加解密算法/工作方式/填充方式")
Cipher ciper = Cipher.getInstance("DESede/ECB/PKCS5Padding","BC");
ciper.init(Cipher.ENCRYPT_MODE, convertSecretKey);
byte[] bytes = ciper.doFinal(src.getBytes());
System.out.println("bouncyCastle 3des encrypt:"+Hex.encodeHexString(bytes));
//解密
ciper.init(Cipher.DECRYPT_MODE,convertSecretKey);
bytes = ciper.doFinal(bytes);
System.out.println("bouncyCastle 3des decrypt:"+new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
3DES算法应用流程同上DES
AES
出现的原因:DES的算法那存在安全,3DES效率较低
AES是目前使用最多的对称加密算法(DES的替代者)
AES通常用于移动通讯系统的加密以及基于SSH协议的软件
jdk代码实现:
public static void jdkAES(){
try {
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
//key转换
Key key = new SecretKeySpec(byteKey, "AES");
//加密 Cipher.getInstance("加解密算法/工作方式/填充方式")
Cipher ciper = Cipher.getInstance("AES/ECB/PKCS5Padding");
ciper.init(Cipher.ENCRYPT_MODE, key);
byte[] bytes = ciper.doFinal(src.getBytes());
System.out.println("jdk aes encrypt:"+Hex.encodeHexString(bytes));
//解密
ciper.init(Cipher.DECRYPT_MODE,key);
bytes = ciper.doFinal(bytes);
System.out.println("jdk aes decrypt:"+new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
bouncyCastle代码实现:
public static void bouncyCastleAES(){
try {
Security.addProvider(new BouncyCastleProvider());
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES","BC");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
//key转换
Key key = new SecretKeySpec(byteKey, "AES");
//加密 Cipher.getInstance("加解密算法/工作方式/填充方式")
Cipher ciper = Cipher.getInstance("AES/ECB/PKCS5Padding","BC");
ciper.init(Cipher.ENCRYPT_MODE, key);
byte[] bytes = ciper.doFinal(src.getBytes());
System.out.println("bouncyCastle aes encrypt:"+Hex.encodeHexString(bytes));
//解密
ciper.init(Cipher.DECRYPT_MODE,key);
bytes = ciper.doFinal(bytes);
System.out.println("bouncyCastle aes decrypt:"+new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
AES算法应用流程图:
PBE(Password Based Encryption)基于口令的加密
对已有算法的包装
加盐(加扰码)
JDK代码实现:
public static void jdkPBE(){
try {
//初始化盐
SecureRandom random = new SecureRandom();
byte[] salt = random.generateSeed(8);
//口令与秘钥
String password = "siy";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
Key key = factory.generateSecret(pbeKeySpec);
//加密
PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE, key,pbeParameterSpec);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("jdk pbe enctpy:"+Hex.encodeHexString(result));
//解密
cipher.init(Cipher.DECRYPT_MODE, key,pbeParameterSpec);
result = cipher.doFinal(result);
System.out.println("jdk pbe dectpy:"+new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
bouncyCastle代码实现:
public static void bouncyCastlePBE(){
try {
Security.addProvider(new BouncyCastleProvider());
//初始化盐
SecureRandom random = new SecureRandom();
byte[] salt = random.generateSeed(8);
//口令与秘钥
String password = "siy";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES","BC");
Key key = factory.generateSecret(pbeKeySpec);
//加密
PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES","BC");
cipher.init(Cipher.ENCRYPT_MODE, key,pbeParameterSpec);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("bouncyCastle pbe enctpy:"+Hex.encodeHexString(result));
//解密
cipher.init(Cipher.DECRYPT_MODE, key,pbeParameterSpec);
result = cipher.doFinal(result);
System.out.println("bouncyCastle pbe dectpy:"+new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
PBF算法应用流程图:
四,非对称加密算法
DH(Diffie-Hellman)密钥交换算法
RSA-基于因子分解
ElGamal-基于离散对数
ECC(Elliptical Curve Cryptography)-椭圆曲线加密
DH密钥交换算法
jdk代码实现:
/**
* 初始化发送方密钥
* -KeyPairGenerator //通过KeyPairGenerator来得到KeyPair类的对象 KeyPairGenerator.getInstance("DH");
* -KeyPair //密钥对(包含公钥,私钥)
* -PublicKey //公钥
*
* 通过KeyPairGenerator来得到KeyPair类的对象
*
*
* 初始化接收方密钥
* -KeyFactory //密钥工厂,用来生成密钥,通过某种规范来还原密钥
* -X509EncodeKeySpec //根据ASN.1标准进行密钥的编码
* -DHPublicKey //DH类PublicKey的具体形式
* -DHParameterSpec//DH参数的集合
* -KeyPairGenerator
* -PrivateKey//私钥
*
*
* 密钥构建
* -KeyAgreement//提供密钥一致性(或密钥交换)协议的功能
* -SecretKey//密码密钥 生成一个分组的秘密密钥
* -KeyFactory
* -X509EncodedKeySpec
* -PublicKey
*
* 加密,解密
* -Cipher
**/
public static void jdkDH(){
try {
//1,初始化发送方密钥
KeyPairGenerator sendKeyPairGenerator = KeyPairGenerator.getInstance("DH");
sendKeyPairGenerator.initialize(512);
KeyPair senderkeyPair = sendKeyPairGenerator.generateKeyPair();
byte[] senderPublicKeyEnc = senderkeyPair.getPublic().getEncoded();//发送方公钥,发送给接收方
//2,初始化接受方密钥
KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
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[] receiverPublic = receiverKeyPair.getPublic().getEncoded();
//3,密钥构建
KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
receiverKeyAgreement.init(receiverPrivateKey);
receiverKeyAgreement.doPhase(receiverPublicKey, true);
SecretKey receiverDesKey = receiverKeyAgreement.generateSecret("DES");
KeyFactory sendKeyFactory = KeyFactory.getInstance("DH");
x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublic);
PublicKey senderPublicKey = sendKeyFactory.generatePublic(x509EncodedKeySpec);
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
senderKeyAgreement.init(senderkeyPair.getPrivate());
senderKeyAgreement.doPhase(senderPublicKey, true);
SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");
if(Objects.equals(receiverDesKey, senderDesKey)){
System.out.println("双方密钥相同");
}
//4,加密
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("jdk dh encrypt:"+Base64.getEncoder().encodeToString(result));
//5,解密
cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
result = cipher.doFinal(result);
System.out.println("jdk dh decrypt:"+new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
DH算法应用流程图:
RSA
唯一广泛接受并实现
数据加密&数字签名
公钥加密,私钥解密
私钥加密,公钥解密
缺点:有点慢
jdk代码实现:
public static void jdkRAS() {
try {
// 1,初始化密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println("rsaPublicKey:" + Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()));
System.out.println("rsaPrivateKey:" + Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded()));
// 2,私钥加密,公钥解密 - 加密
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[] result = cipher.doFinal(src.getBytes());
System.out.println("私钥加密,公钥解密 - 加密:" + Base64.getEncoder().encodeToString(result));
// 3,私钥加密,公钥解密 - 解密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher.doFinal(result);
System.out.println("私钥加密,公钥解密 - 解密:" + new String(result));
// 4,公钥加密,私钥解密 - 加密
x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
result = cipher.doFinal(src.getBytes());
System.out.println("公钥加密,私钥解密 - 加密:" + Base64.getEncoder().encodeToString(result));
// 5,公钥加密,私钥解密 - 解密
pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
result = cipher.doFinal(result);
System.out.println("公钥加密,私钥解密 - 解密:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
RSA算法的应用流程图:
ElGamal(jdk没有提供实现,需要使用bouncyCastle架包)
只支持公钥加密私钥解密,不支持私钥加密,公钥解密
bouncyCastle的Elmal的代码实现:
public static void bouncyCastleElGamal() {
try {
// 加入对BouncyCastle支持
Security.addProvider(new BouncyCastleProvider());
// 公钥加密,私钥解密(不能私钥加密,公钥解密)
// 1,初始化密钥
AlgorithmParameterGenerator algorithmParameterGenerator = AlgorithmParameterGenerator
.getInstance("ElGamal");
// 初始化参数生成器
algorithmParameterGenerator.init(256);
// 生成算法参数
AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();
// 构建参数材料
DHParameterSpec dhParameterSpec = algorithmParameters.getParameterSpec(DHParameterSpec.class);
// 实例化密钥生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ElGamal");
// 初始化密钥对生成器
keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 公钥
PublicKey elGamalPublicKey = keyPair.getPublic();
// 私钥
PrivateKey elGamalPrivateKey = keyPair.getPrivate();
System.out.println("publicKey:" + Base64.getEncoder().encodeToString(elGamalPublicKey.getEncoded()));
System.out.println("privateKey:" + Base64.getEncoder().encodeToString(elGamalPrivateKey.getEncoded()));
// 2.私钥解密、公钥加密 ---- 加密
// 初始化公钥
// 密钥材料转换
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
// 实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance("Elgamal");
// 产生公钥
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
// 数据加密
Cipher cipher = Cipher.getInstance("Elgamal");
// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("公钥加密,私钥解密:" + Base64.getEncoder().encodeToString(result));
// 3.私钥解密、公钥加密 ---- 解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance("Elgamal");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
cipher = Cipher.getInstance("Elgamal");
// cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
result = cipher.doFinal(result);
System.out.println("公钥加密,私钥解密:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
如果直接运行这个加密方法会报如下错误:
这个是由于无政策限制权限文件(local_policy.jar、US_export_policy.jar)引起的。
这2个文件的位置在jdk\jre\lib\security和jre\lib\security下
Oracle在其官方网站上提供了无政策限制权限文件(Unlimited Strength Jurisdiction Policy Files),我们只需要将其下载下来然后替换掉就可以了。
jdk1.6下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
jdk1.7下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
jdk1.8下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
替换后运行:
ElGamal算法应用流程图:
五,数字签名算法
定义:带有密钥(公钥,私钥)的消息摘要算法
作用:验证数据的完整性,认证数据来源,抗否认
私钥签名,公钥验证
RAS,DSA,ECDSA
RSA
MD,SHA两类
jdk代码实现:
public static void jdkRAS(){
try {
//私钥签名,公钥验证
//1,初始化密钥
KeyPairGenerator keyPairGeneratot = KeyPairGenerator.getInstance("RSA");
keyPairGeneratot.initialize(512);
KeyPair keyPair = keyPairGeneratot.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
//2,执行签名
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());
byte[] result = signature.sign();
System.out.println("jdk RSA sign:"+Base64.getEncoder().encodeToString(result));
//3,验证签名
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 bool = signature.verify(result);
System.out.println("jdk RSA verify:"+ bool);
} catch (Exception e) {
e.printStackTrace();
}
}
RSA数字签名算法的应用流程图:
DSA(Digital Signature Algorithm)数字签名算法标准
DSA仅包含数字签名,不包含加密
jdk代码的实现:
public static void jdkDSA(){
try {
//1,初始化密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
DSAPublicKey dsaPublicKey = (DSAPublicKey)keyPair.getPublic();
DSAPrivateKey dsaPrivateKey = (DSAPrivateKey)keyPair.getPrivate();
//2,执行签名
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA1withDSA");
signature.initSign(privateKey);
signature.update(src.getBytes());
byte[] result = signature.sign();
System.out.println("jdk DSA sign:"+Base64.getEncoder().encodeToString(result));
//3,验证签名
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("DSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
signature = Signature.getInstance("SHA1withDSA");
signature.initVerify(publicKey);
signature.update(src.getBytes());
boolean bool = signature.verify(result);
System.out.println("jdk DSA verify:"+ bool);
} catch (Exception e) {
e.printStackTrace();
}
}
DSA数字签名算法的应用流程图:
ECDSA(Elliptic Curve Digital Signture Algorithm)椭圆曲线数字签名算法(jdk1.7)
优点:速度快,强度高,签名短
jdk代码实现:
public static void jdkECDSA(){
try {
//1,初始化密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
keyPairGenerator.initialize(256);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();
ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();
//2,执行签名
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA1withECDSA");
signature.initSign(privateKey);
signature.update(src.getBytes());
byte[] result = signature.sign();
System.out.println("jdk ECDSA sign:"+Base64.getEncoder().encodeToString(result));
//3,验证签名
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ecPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("EC");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
signature = Signature.getInstance("SHA1withECDSA");
signature.initVerify(publicKey);
signature.update(src.getBytes());
boolean bool = signature.verify(result);
System.out.println("jdk ECDSA verify:"+ bool);
} catch (Exception e) {
e.printStackTrace();
}
}
ECDSA数字签名算法应用流程图:
终于敲完了!!!
完整例子项目代码在:http://download.csdn.net/detail/baidu_34012226/9695810
jdk1.8的无政策限制权限文件(local_policy.jar、US_export_policy.jar)在:http://download.csdn.net/detail/baidu_34012226/9695825