1 加密/解密
1.1 实现细节
f 加密算法
密钥(k) 加密钥匙
明文(m) 加密前的明文信息
密文(c) 被加密后的密文信息
m-----f(key)----->c-----f(key)----->m
1.1.1 加密/解密算法
JDK有一个Cipher类,该类是所有密码算法的超类。
Cipher cipher = Cipher.getInstance(algName);
或Cipher cipher = Cipher.getInstance(algName, pName);
algName: 加密算法
pName: 加密算法提供商
一旦获得一个密码对象,就可以通过设置模式和密钥来对他初始化。
cipher.init(mode,key);
模式主要分以下几种:
Cipher.ENCRYPT_MODE 加密
Cipher.DECRYPT_MODE 解密
Cipher.WRAP_MODE 将一个Key封装成字节
Cipher.UNWRAP_MODE 将前述已封装的key还原为Key对象
public byte[] doFinal(byte[] input);
对input数据进行加密,返回加密后的密文。
1.1.2 密钥
密钥可以有两个方法获得,一个是生成一个完全随机的密钥。另外一个方法就是使用口令产生一个密码。
产生一个随机密钥:
KeyGenerator keyGenerator = KeyGenerator.getInstance(algName);
SecureRandom secureRandom = new SecureRandom();
keyGenerator.init(secureRandom);
key = keyGenerator.generateKey();
产生口令产生密钥:
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algName) ;
DESKeySpec desKeySpec = new DESKeySpec(createKey);
createKey: 口令字节数组,使用 createKey中的前 8 个字节作为 DES 密钥的密钥内容,如果createKey长度不够8个字节,则抛出InvalidKeyException异常。
key = secretKeyFactory.generateSecret(desKeySpec) ;
产生公钥私钥:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algName);
SecureRandom random = new SecureRandom();
keyPairGenerator.initialize(SIZE, random);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
加密密钥:
cipher = Cipher.getInstance(algName);
cipher.init(Cipher.UNWRAP_MODE , key);
key : 公钥
cipher.wrap(key);
key : 被加密的密钥
解密密钥:
cipher = Cipher.getInstance(algName);
cipher.init(Cipher.UNWRAP_MODE,key);
key : 私钥
cipher.unwrap(key, algName,Cipher.SECRET_KEY);
key : 字节数组,加密后的密钥
1.2 代码示例
对称密码是加密和解密都使用相同的密钥。
1.2.1 对称密码
1.2.1.1 随机产生密码
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
public class RegularCipher {
private Key key = null ;
private Cipher cipher = null ;
public static void main(String[] args) {
RegularCipher regularCipher = new RegularCipher();
String information = "欢迎大家批评";
byte[] crypt_info = null; // 加密后的密文
byte[] not_crypt_info = null; // 解密后的明文
// 创建密钥
regularCipher.CreateRandomRegularKey();
System.out.println("要加密的信息: " + information);
// 生成加密算法
regularCipher.createCipher(Cipher.ENCRYPT_MODE);
crypt_info = regularCipher.Crypt(information.getBytes());
System.out.println("加密后的密文: " + new String(crypt_info));
System.out.println();
// 生成解密算法
regularCipher.createCipher(Cipher.DECRYPT_MODE);
not_crypt_info = regularCipher.Crypt(crypt_info);
System.out.println("解密后的明文: " + new String(not_crypt_info));
}
/**
* 随机生成对称密钥
*/
public void CreateRandomRegularKey(){
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
SecureRandom secureRandom = new SecureRandom();
keyGenerator.init(secureRandom);
key = keyGenerator.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建加密/解密算法
*/
public void createCipher(int mode) {
try {
cipher = Cipher.getInstance("DES");
cipher.init(mode,key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 加密/解密
*/
public byte[] Crypt(byte[] in){
try {
return cipher.doFinal(in);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null ;
}
}
1.2.1.2 使用口令产生密码
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class RegularCipher {
private Key key = null ;
private Cipher cipher = null ;
public static void main(String[] args) {
RegularCipher regularCipher = new RegularCipher();
String information = "阿里软件 AEP平台";
byte[] createKey = "12345678".getBytes();
byte[] crypt_info = null; // 加密后的密文
byte[] not_crypt_info = null; // 解密后的明文
System.out.println("要加密的信息: " + information);
// 创建密钥
regularCipher.CreateMyRegularKey(createKey,"DES");
// 生成加密算法
regularCipher.createCipher(Cipher.ENCRYPT_MODE,"DES");
crypt_info = regularCipher.Crypt(information.getBytes());
System.out.println("加密后的密文: " + new String(crypt_info));
// 生成解密算法
regularCipher.createCipher(Cipher.DECRYPT_MODE,"DES");
not_crypt_info = regularCipher.Crypt(crypt_info);
System.out.println("解密后的明文: " + new String(not_crypt_info));
}
/**
* 生成自指定密钥
*/
public void CreateMyRegularKey(byte[] createKey,String alg){
try {
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(alg) ;
DESKeySpec desKeySpec;
desKeySpec = new DESKeySpec(createKey);
key = secretKeyFactory.generateSecret(desKeySpec) ;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
/**
* 创建加密/解密算法
*/
public void createCipher(int mode , String alg) {
try {
cipher = Cipher.getInstance(alg);
cipher.init(mode,key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
/**
* 加密/解密
*/
public byte[] Crypt(byte[] in){
try {
return cipher.doFinal(in);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
}
1.2.2 公钥私钥加解密
对称密码有个弱点在是密码的分发。如果密钥修改了则必须有一个安全的通道重新分发新密钥,但不一定拥有一条安全的通道。我们用公钥私钥加解密技术来解决这个问题。
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class PairCipher {
private PrivateKey privateKey = null ;
private PublicKey publicKey = null ;
private Cipher cipher = null ;
private static int SIZE = 512 ;
public static void main(String[] args) {
PairCipher pairCipher = new PairCipher();
String information = "欢迎大家批评";
byte[] crypt_info = null; // 加密后的密文
byte[] not_crypt_info = null; // 解密后的明文
System.out.println("要加密的信息: " + information);
// 创建公钥和私钥
pairCipher.createPublicAndPrivateKey("RSA");
// 用公钥加密
pairCipher.createCipher(Cipher.ENCRYPT_MODE,"RSA",pairCipher.getPublicKey());
crypt_info = pairCipher.Crypt(information.getBytes());
System.out.println("加密后的密文: " + new String(crypt_info));
// 用私钥解密
pairCipher.createCipher(Cipher.DECRYPT_MODE,"RSA",pairCipher.getPrivateKey());
not_crypt_info = pairCipher.Crypt(crypt_info);
System.out.println("解密后的明文: " + new String(not_crypt_info));
}
/**
* 生成公钥和私钥
*/
public void createPublicAndPrivateKey(String alg) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(alg);
SecureRandom random = new SecureRandom();
keyPairGenerator.initialize(SIZE, random);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 创建加密/解密算法
*/
public void createCipher(int mode , String alg , Key key) {
try {
cipher = Cipher.getInstance(alg);
cipher.init(mode,key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
/**
* 加密/解密信息
*/
public byte[] Crypt(byte[] in){
try {
return cipher.doFinal(in);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public PublicKey getPublicKey() {
return publicKey;
}
}
1.2.3 公钥私钥和对称密钥加解密结合使用
由于公钥私钥加解密要比对称密钥加解密慢,因此我们将公钥私钥和对称密钥加解密结合使用。
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
public class PairCipher {
private Key key = null ;
private PrivateKey privateKey = null ;
private PublicKey publicKey = null ;
private Cipher cipher = null ;
private static int SIZE = 514 ;
public static void main(String[] args) {
PairCipher pairCipher = new PairCipher();
String information = "欢迎大家批评";
byte[] crypt_key = null; // 加密后的密码
Key _key = null ; // 解密后的key
byte[] crypt_info = null; // 加密后的密文
byte[] not_crypt_info = null; // 解密后的明文
System.out.println("要加密的信息: " + information);
// 创建密码
pairCipher.CreateRandomRegularKey("AES");
// 用户密码加密明文
pairCipher.createCipher(Cipher.ENCRYPT_MODE,"AES",pairCipher.getKey());
crypt_info = pairCipher.Crypt(information.getBytes());
System.out.println("加密后的密文: " + new String(crypt_info));
// 创建公钥和私钥
pairCipher.createPublicAndPrivateKey("RSA");
// 用公钥加密密码
pairCipher.createCipher(Cipher.WRAP_MODE,"RSA",pairCipher.getPublicKey());
crypt_key = pairCipher.enCryptKey(pairCipher.getKey());
System.out.println("加密后的密钥: " + new String(crypt_key));
// 用私钥解密密码
pairCipher.createCipher(Cipher.UNWRAP_MODE,"RSA",pairCipher.getPrivateKey());
_key = pairCipher.deCryptKey(crypt_key,"AES");
// 用解密后的密码解密密文
pairCipher.createCipher(Cipher.DECRYPT_MODE,"AES",_key);
not_crypt_info = pairCipher.Crypt(crypt_info);
System.out.println("解密后的明文: " + new String(not_crypt_info));
}
/**
* 生成公钥和私钥
*/
public void createPublicAndPrivateKey(String alg) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(alg);
SecureRandom random = new SecureRandom();
keyPairGenerator.initialize(SIZE, random);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
privateKey = keyPair.getPrivate();
publicKey = keyPair.getPublic();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 随机生成对称密钥
*/
public void CreateRandomRegularKey(String alg){
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(alg);
SecureRandom secureRandom = new SecureRandom();
keyGenerator.init(secureRandom);
key = keyGenerator.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建加密/解密算法
*/
public void createCipher(int mode , String alg , Key key) {
try {
cipher = Cipher.getInstance(alg);
cipher.init(mode,key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
/**
* 加密/解密信息
*/
public byte[] Crypt(byte[] in){
try {
return cipher.doFinal(in);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 加密密钥
*/
public byte[] enCryptKey(Key key){
try {
return cipher.wrap(key);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null ;
}
/**
* 解密密钥
*/
public Key deCryptKey(byte[] key,String alg){
try {
return cipher.unwrap(key, alg,Cipher.SECRET_KEY);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null ;
}
public Key getKey() {
return key;
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public PublicKey getPublicKey() {
return publicKey;
}
}