java加密与解密_JAVA加密与解密

本文详细介绍了JAVA中的摘要算法,包括MD5、SHA和MAC,并提供了代码示例。此外,还讲解了对称加密体制,如DES、AES等,以及非对称加密中的DH和RSA算法的使用。
摘要由CSDN通过智能技术生成

摘要算法

摘要算法主要包含三大类型:MD算法,SHA算法,已经基于KEY的MAC算法

MD算法

MD算法主要有MD2,MD3,MD4以及最常用的MD5。

SHA算法主要有SHA-1,SHA-224,SHA-256,SHA-384,SHA-512。

MAC算法是基于哈西散列算法(MD系列或者SHA系列等),在HASH散列进行KEY加密

JAVA密码体系对主流摘要算法的支持

fc795721b5874fa98c7b51e79ecc714b.png

MD5算法的调用示例

package com.rcl.platform.demo;

import java.security.InvalidKeyException;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

import java.security.NoSuchProviderException;

import java.security.Provider;

import java.security.Security;

import javax.crypto.Mac;

import javax.crypto.SecretKey;

import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class ProviderTest {

public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {

MessageDigest messageDigest = MessageDigest.getInstance("MD5");

messageDigest.update("我是MD".getBytes());

byte [] md5 = messageDigest.digest();

System.out.println(byte2HexStr(md5));

Security.addProvider(new BouncyCastleProvider());//注册BouncyCastleProvider

Provider provider = Security.getProvider("BC");

messageDigest = MessageDigest.getInstance("MD4", provider);

messageDigest.update("我是MD".getBytes());

byte [] md4 = messageDigest.digest();

System.out.println(byte2HexStr(md4));

messageDigest = MessageDigest.getInstance("SHA512");//调用SHA算法

messageDigest.update("我是SHA".getBytes());

byte [] sha512 = messageDigest.digest();

System.out.println(byte2HexStr(sha512));

SecretKey secretKey = new SecretKeySpec("woshikey".getBytes(), "HmacSHA512");//HMAC算法调用

Mac mac = Mac.getInstance(secretKey.getAlgorithm());

mac.init(secretKey);

byte [] hmacSHA224 = mac.doFinal("我是SHA".getBytes());

System.out.println(byte2HexStr(hmacSHA224));

}

public static String byte2HexStr(byte[] b) {

String stmp="";

StringBuilder sb = new StringBuilder("");

for (int n=0;n

stmp = Integer.toHexString(b[n] & 0xFF);

sb.append((stmp.length()==1)? "0"+stmp : stmp);

sb.append("");

}

return sb.toString().toLowerCase().trim();

}

}

执行结果

f610c6a17a31eec9d36c5ef646149ea6

d40694ae1650fdb9bfe807833a3b6c89

e7046e9687398575eadf7eadf5854103b9a98fbedc1333cd553bc288b3518f997884cb7b827bc789b973d2dcf818253359133361602518d045d2cc2ff0eb0871

4e8f13266500448abf27d54aeaeb7825ed62c62d6c40633b3066faf10f6b3b9e933ec2e335b9ab5388da1c09161bf75a2e6fdac7f01ebeb1910f187824fc2562

对称加密

1、对称加密体制要求加密与解密使用同一个共享密钥,解密是加密的逆运算,对于共享密钥,要求通讯双方在通讯前协商共享密钥并妥善保存

2、对称加密体制分为两种:一种是对明文的单个位(或单个字节)进行加密,称为流密码;另一种是明文划分为不同的组(或块),分别对组加密,称为分组加密

3、常用的为分组加密,分组加密的安全性与分组长度有关,但是一般默认的长度为56位

4、对称加密有DES,DESede,AES,Blowfish,RC2,RC4,IDEA。相关概念可以百度百科

分组密码工作模式

1、电子密码本模式ECB:每次加密均产生独立的密文分组,每组加密的结果不会对其他组产生影响,无初始化向量

2、密文连接模式CBC:目前应用最广泛的工作模式,组明文加密前需先与前面的组密文进行异或运算(XOR)在加密

3、密文反馈模式CFB:类似于自同步流密码,分组加密后,按8位分组将密文和明文进行位移异或得到输出并同时反馈回位移寄存器

4、输出反馈模式OFB:和CFB类似,不过OFB用的是前一个n位密文输出分组反馈回位移寄存器

5、计数器模式CTR:将计数器从初始值开始计数,所得到的值发送给分组密码,随着计数器的增加,分组密码算法输出连续的分组来构成一个位串,该串用来与明文分组进行异或运算。在AES中,经常使用的是CBC和CTR,CTR用的比CBC更多些

填充模式

对于明文进行分组,最后一个分组长度不满足默认长度,称为短分组。对于短分组如何处理,需要使用到填充模式。

Java对对称加密算法的支持

3eedf31eefcd64bda96f1cbb251d5a97.png

9777c93f1642f45ff24105d690d258c6.png

Bouncy castle对于PBE的支持

ba6aa2ba73590192a03e7deda6a6719a.png

示例代码

package com.rcl.platform.demo;

import java.security.Key;

import javax.crypto.Cipher;

import javax.crypto.SecretKey;

import javax.crypto.SecretKeyFactory;

import javax.crypto.spec.DESKeySpec;

import javax.crypto.spec.DESedeKeySpec;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.PBEKeySpec;

import javax.crypto.spec.PBEParameterSpec;

import javax.crypto.spec.SecretKeySpec;

public abstract class DESCoder {

public static void main(String[] args) throws Exception {

String inputStr = "我是加密内容";

byte[] inputData = inputStr.getBytes();

byte[] key = "key123321".getBytes();

inputData = encrypt(inputData, key);

byte[] outputData = decrypt(inputData, key);

System.out.println("解密后:\t" + new String(outputData));

byte [] iv = "11111111".getBytes();

inputData = encryptCBC(inputStr.getBytes(), key, iv);

outputData = decryptCBC(inputData, key, iv);

System.out.println("解密后 CBC模式:\t" + new String(outputData));

byte[] data = encrypt(inputStr.getBytes(), "snowolf1", "11111111".getBytes());//SALT必须为8字节

byte[] output = decrypt(data, "snowolf1", "11111111".getBytes());

System.out.println("PBE解密后:\t" + new String(output));

}

private static Key toKey(byte[] key) throws Exception {

// 实例化DES密钥材料

DESKeySpec dks = new DESKeySpec(key);

// 实例化秘密密钥工厂

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");

// 生成秘密密钥

SecretKey secretKey = keyFactory.generateSecret(dks);

return secretKey;

}

/**

* 转换密钥

*

* @param key

* 二进制密钥

* @return Key 密钥

* @throws Exception

*/

private static Key toKeyDESede(byte[] key) throws Exception {

// 实例化DES密钥材料

DESedeKeySpec dks = new DESedeKeySpec(key);

// 实例化秘密密钥工厂

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");

// 生成秘密密钥

SecretKey secretKey = keyFactory.generateSecret(dks);

return secretKey;

}

/**

* 转换密钥

*

* @param key

* 二进制密钥

* @return Key 密钥

* @throws Exception

*/

private static Key toKeyAESOrIDEA(byte[] key) throws Exception {

// 实例化AES密钥材料

SecretKey secretKey = new SecretKeySpec(key, "AES");

// SecretKey secretKey = new SecretKeySpec(key, "IDEA");

return secretKey;

}

/**

* 转换密钥

*

* @param password

* 密码

* @return Key 密钥

* @throws Exception

*/

private static Key toKeyPBE(String password) throws Exception {

// 密钥材料转换

PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());

// 实例化

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndTripleDES");

// 生成密钥

SecretKey secretKey = keyFactory.generateSecret(keySpec);

return secretKey;

}

/**

* 解密

*

* @param data

* 待解密数据

* @param key

* 密钥

* @param ivParameterSpec

* 加密向量

* @return byte[] 解密数据

* @throws Exception

*/

public static byte[] decryptCBC(byte[] data, byte[] key, byte [] ivParameterSpec) throws Exception {

// 还原密钥

Key k = toKey(key);

// 实例化

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

//初始化加密向量,CBC模式必须参数,参数最少8位

IvParameterSpec param = new IvParameterSpec(ivParameterSpec);//CBC

// 初始化,设置为解密模式

cipher.init(Cipher.DECRYPT_MODE, k, param);

// 执行操作

return cipher.doFinal(data);

}

/**

* 加密

*

* @param data

* 待加密数据

* @param key

* 密钥

* @param ivParameterSpec

* 加密向量

* @return byte[] 加密数据

* @throws Exception

*/

public static byte[] encryptCBC(byte[] data, byte[] key, byte [] ivParameterSpec) throws Exception {

// 还原密钥

Key k = toKey(key);

// 实例化

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

IvParameterSpec param = new IvParameterSpec(ivParameterSpec);//CBC

// 初始化,设置为加密模式

cipher.init(Cipher.ENCRYPT_MODE, k, param);

// 执行操作

return cipher.doFinal(data);

}

/**

* 解密

*

* @param data

* 待解密数据

* @param key

* 密钥

* @return byte[] 解密数据

* @throws Exception

*/

public static byte[] decrypt(byte[] data, byte[] key) throws Exception {

// 还原密钥

Key k = toKey(key);

// 实例化

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5PADDING");

// 初始化,设置为解密模式

cipher.init(Cipher.DECRYPT_MODE, k);

// 执行操作

return cipher.doFinal(data);

}

/**

* 加密

*

* @param data

* 待加密数据

* @param key

* 密钥

* @return byte[] 加密数据

* @throws Exception

*/

public static byte[] encrypt(byte[] data, byte[] key) throws Exception {

// 还原密钥

Key k = toKey(key);

// 实例化

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5PADDING");

// 初始化,设置为加密模式

cipher.init(Cipher.ENCRYPT_MODE, k);

// 执行操作

return cipher.doFinal(data);

}

/**

* 加密

*

* @param data

* 数据

* @param password

* 密码

* @param salt

* 盐

* @return byte[] 加密数据

* @throws Exception

*/

public static byte[] encrypt(byte[] data, String password, byte[] salt)

throws Exception {

// 转换密钥

Key key = toKeyPBE(password);

// 实例化PBE参数材料

PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);

// 实例化

Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");

// 初始化

cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

// 执行操作

return cipher.doFinal(data);

}

/**

* 解密

*

* @param data

* 数据

* @param password

* 密码

* @param salt

* 盐

* @return byte[] 解密数据

* @throws Exception

*/

public static byte[] decrypt(byte[] data, String password, byte[] salt)

throws Exception {

// 转换密钥

Key key = toKeyPBE(password);

// 实例化PBE参数材料

PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);

// 实例化

Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");

// 初始化

cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

// 执行操作

return cipher.doFinal(data);

}

}

执行结果

解密后: 我是加密内容

解密后 CBC模式: 我是加密内容

PBE解密后: 我是加密内容

非对称加密

DH:密钥交换算法

DH算法的目的是解决非对称加密解密性能问题,通过协商的方式产生对称密钥。生产对称密钥的步骤大致如下

1、甲方通过DH算法生成甲方的公私钥对

2、甲方加自己的公钥发送给乙方

3、乙方根据甲方的公钥产生自己的公私钥对

4、甲乙双产生协商的好的对应加密算法的对称密钥。甲方生成是通过甲方私钥+乙方公钥使用DH提供的对称密钥的生成方式产生对称密钥;乙方生成是通过乙方私钥+甲方公钥使用DH提供的对称密钥的生成方式产生对称密钥

关键点:甲方需要公布自己的公钥给乙方,乙方生成需要使用此公钥;无法抵挡中间人攻击

密钥长度:512-1024位

密钥默认长度:1024位

工作模式:无

填充方式:无

JDK6.0提供了实现

package test;

import java.security.Key;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PublicKey;

import java.security.PrivateKey;

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.SecretKeySpec;

public abstract class DHCoder {

/**

* 非对称加密密钥算法

*/

public static final String KEY_ALGORITHM = "DH";

/**

* 本地密钥算法,即对称加密密钥算法,可选DES、DESede和AES算法

*/

public static final String SECRET_KEY_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

* @throws Exception

*/

public static Map 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 keyMap = new HashMap(2);

keyMap.put(PUBLIC_KEY, publicKey);

keyMap.put(PRIVATE_KEY, privateKey);

return keyMap;

}

/**

* 初始化乙方密钥

*

* @param key

* 甲方公钥

* @return Map 乙方密钥Map

* @throws Exception

*/

public static Map 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.generateKeyPair();

// 乙方公钥

DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();

// 乙方私钥

DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();

// 将密钥对存储在Map中

Map keyMap = new HashMap(2);

keyMap.put(PUBLIC_KEY, publicKey);

keyMap.put(PRIVATE_KEY, privateKey);

return keyMap;

}

/**

* 构建密钥

*

* @param publicKey

* 公钥

* @param privateKey

* 私钥

* @return byte[] 本地密钥

* @throws Exception

*/

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_KEY_ALGORITHM);

return secretKey.getEncoded();

}

}

非对称加密至RSA

JDK6.0提供了RSA加密算法的实现

在RSA算法中,公钥既可以用于解密,也可以用于加密,私钥也是如此。但是公钥加密只能私钥解密,反正私钥加密只能公钥解密。

对于JDK与 Bouncy Castle的实现如下

1f841a8dcf273cba9f00a17a14649436.png

package test;

import java.security.Key;

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 java.util.HashMap;

import java.util.Map;

import javax.crypto.Cipher;

public abstract class RSACoder {

/**

* 非对称加密密钥算法

*/

public static final String KEY_ALGORITHM = "RSA";

/**

* 公钥

*/

private static final String PUBLIC_KEY = "RSAPublicKey";

/**

* 私钥

*/

private static final String PRIVATE_KEY = "RSAPrivateKey";

/**

* RSA密钥长度

* 默认1024位,

* 密钥长度必须是64的倍数,

* 范围在512至65536位之间。

*/

private static final int KEY_SIZE = 512;

/**

* 私钥解密

*

* @param data

* 待解密数据

* @param key

* 私钥

* @return byte[] 解密数据

* @throws Exception

*/

public static byte[] decryptByPrivateKey(byte[] data, byte[] key)

throws Exception {

// 取得私钥

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

// 生成私钥

PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

// 对数据解密

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE, privateKey);

return cipher.doFinal(data);

}

/**

* 公钥解密

*

* @param data

* 待解密数据

* @param key

* 公钥

* @return byte[] 解密数据

* @throws Exception

*/

public static byte[] decryptByPublicKey(byte[] data, byte[] key)

throws Exception {

// 取得公钥

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

// 生成公钥

PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);

// 对数据解密

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE, publicKey);

return cipher.doFinal(data);

}

/**

* 公钥加密

*

* @param data

* 待加密数据

* @param key

* 公钥

* @return byte[] 加密数据

* @throws Exception

*/

public static byte[] encryptByPublicKey(byte[] data, byte[] key)

throws Exception {

// 取得公钥

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);

// 对数据加密

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, publicKey);

return cipher.doFinal(data);

}

/**

* 私钥加密

*

* @param data

* 待加密数据

* @param key

* 私钥

* @return byte[] 加密数据

* @throws Exception

*/

public static byte[] encryptByPrivateKey(byte[] data, byte[] key)

throws Exception {

// 取得私钥

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

// 生成私钥

PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

// 对数据加密

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, privateKey);

return cipher.doFinal(data);

}

/**

* 取得私钥

*

* @param keyMap

* 密钥Map

* @return byte[] 私钥

* @throws Exception

*/

public static byte[] getPrivateKey(Map keyMap)

throws Exception {

Key key = (Key) keyMap.get(PRIVATE_KEY);

return key.getEncoded();

}

/**

* 取得公钥

*

* @param keyMap

* 密钥Map

* @return byte[] 公钥

* @throws Exception

*/

public static byte[] getPublicKey(Map keyMap)

throws Exception {

Key key = (Key) keyMap.get(PUBLIC_KEY);

return key.getEncoded();

}

/**

* 初始化密钥

*

* @return Map 密钥Map

* @throws Exception

*/

public static Map initKey() throws Exception {

// 实例化密钥对生成器

KeyPairGenerator keyPairGen = KeyPairGenerator

.getInstance(KEY_ALGORITHM);

// 初始化密钥对生成器

keyPairGen.initialize(KEY_SIZE);

// 生成密钥对

KeyPair keyPair = keyPairGen.generateKeyPair();

// 公钥

RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

// 私钥

RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

// 封装密钥

Map keyMap = new HashMap(2);

keyMap.put(PUBLIC_KEY, publicKey);

keyMap.put(PRIVATE_KEY, privateKey);

return keyMap;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值