JAVA 实现DES 加密解密、生成秘钥
JAVA 加密使用的库是Cipher
javax.crypto.Cipher 是java原生的类库,用来做加密解密的。
官网描述
https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html#method.detail/
此类提供用于加密和解密的密码算法的功能。它构成了Java加密扩展(JCE)框架的核心。
1、getInstance 创建Cipher实例
A transformation is a string that describes the operation
(or set of operations) to be performed on the given input,
to produce some output. A transformation always includes
the name of a cryptographic algorithm (e.g., AES), and may
be followed by a feedback mode and padding scheme.
A transformation is of the form:
"algorithm/mode/padding" or
"algorithm"
(in the latter case, provider-specific default values for
the mode and padding scheme are used). For example, the
following is a valid transformation:
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
创建实例两种方法:
第一种创建方式
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
参数由“/” 隔开
algorithm 算法
mode 模式
padding 填充
第二种创建方式
Cipher c = Cipher.getInstance("RSA");
algorithm 算法
算法支持
Every implementation of the Java platform is required to support the following standard Cipher transformations with the keysizes in parentheses:
AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA/ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
可以看出Cipher 支持AES,DES,DESede,RSA
这里列举了全部支持的Algorithm Mode Padding
https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
2、init 初始化秘钥
可以从证书、Key来初始化Cipher
使用给定参数初始化此密码。
针对以下四个操作之一初始化密码:加密,解密,密钥包装或密钥解包,具体取决于的值opmode。
如果证书的类型为X.509,并且密钥使用 扩展字段标记为关键,并且密钥使用 扩展字段的值表示证书中的公钥及其对应的私钥不应用于 抛出opmode一个以表示的操作InvalidKeyException。
如果此密码需要任何不能从给定证书中的公钥派生的算法参数,则如果正在对其进行加密或加密初始化,则该基础密码实现应自行生成所需的参数(使用提供程序特定的默认值或随机值)。密钥包装, InvalidKeyException如果正在初始化以进行解密或密钥解包,则引发。可以使用getParameters或 getIV(如果参数为IV)检索生成的参数 。
如果此密码要求无法从输入参数中得出的算法参数,并且没有合理的提供程序特定的默认值,则初始化必然会失败。
如果此密码(包括其基础反馈或填充方案)需要任何随机字节(例如,用于参数生成),它将使用SecureRandom 安装的最高优先级提供程序作为随机源来获取它们 。(如果没有安装的提供程序提供SecureRandom的实现,则将使用系统提供的随机性源。)
请注意,在初始化Cipher对象时,它将丢失所有先前获取的状态。换句话说,初始化Cipher等效于创建该Cipher的新实例并将其初始化。
参数:
opmode 参数可选:
ENCRYPT_MODE,DECRYPT_MODE, WRAP_MODE或UNWRAP_MODE
key 可选
DHPrivateKey, DHPublicKey, DSAPrivateKey, DSAPublicKey, ECPrivateKey, ECPublicKey, PBEKey, PrivateKey, PublicKey, RSAMultiPrimePrivateCrtKey, RSAPrivateCrtKey, RSAPrivateKey, RSAPublicKey, SecretKey
InvalidKeyException 抛出情况:
如果给定密钥不适合初始化此密码;
或者需要无法从给定密钥确定的算法参数;
或者给定密钥的密钥大小超过最大允许密钥大小;
通过Key来创建
//获取key
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
DESKeySpec keySpec = new DESKeySpec(secretKey.getBytes());
Key key = keyFactory.generateSecret(keySpec);
//初始化
cipher.init(Cipher.DECRYPT_MODE, key);
证书的方式就不实验了
3、doFinal 完成加密 、解密数据
参数:
byte[] input 输入的数据
4、方法封装
秘钥获取
/**
* @Title: generateKey
* @Description: 生成SecretKey
* @param key字符串
* @return SecretKey
* @throws
*/
private static SecretKey generateKey(String secretKey)
throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
DESKeySpec keySpec = new DESKeySpec(secretKey.getBytes());
keyFactory.generateSecret(keySpec);
return keyFactory.generateSecret(keySpec);
}
加密
/**
* @Title: encrypt
* @Description: 加密方法
* @param
* @return byte[]
* @throws
*/
public static byte[] encrypt(byte[] content, byte[] keyBytes) throws Exception{
try {
DESKeySpec keySpec = new DESKeySpec(keyBytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey key = keyFactory.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB);
// Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
// IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
// cipher.init(Cipher.ENCRYPT_MODE, key ,iv );
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(content);
return result;
}catch(Exception e) {
e.printStackTrace();
throw new Exception("DES加密异常:"+e.getMessage());
}
}
解密
/**
* @Title: decrypt
* @Description: 解密
* @param content 解密内容
* @param key 密key
* @return String
* @throws
*/
public static String decrypt(String content, String key) throws Exception {
try {
// Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
// IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
// cipher.init(Cipher.DECRYPT_MODE, generateKey(key),iv);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB);
cipher.init(Cipher.DECRYPT_MODE, generateKey(key));
byte[] buf = cipher.doFinal(hexStr2Bytes(content));
return new String(buf, CHARSET);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("DES解密异常:" + e.getMessage());
}
}
注意事项
1、前端和后端的 algorithm/mode/padding 需要一致
2、秘钥的 String 编码方式要注意一致
扩展
1、可以看到这对应的AES和RSA 各种加密方式都支持,可以直接将秘钥初始化成其他的算法就完成了更换。
2、EBC为默认的模式,前端库中的默认模式为CBC,因为EBC在很多时候评估并不太安全,所以两边都使用默认的时候就会发现怎么都对不上,所以需要指定对应的方式。
3、https://docs.oracle.com/javase/8/docs/api/ 详细API可以直接查看官网