在java中,诸如MD5、BASE64、DES、RSA等经典加密解密算法,JDK都有提供专门的API来封装相关操作。下面逐一介绍每种算法的具体应用流程。
一、 MD5加密算法:
MD5算法,是一种基于哈希函数的单向加密算法,只能加密、无法解密。Java中提供了MD5算法的API
1.创建md5对象:
2. 进行加密操作:
3. 将其中的每个字节转成十六进制字符串:byte类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数。
4.如果该正数小于16(长度为1个字符),前面拼接0占位:确保最后生成的是32位字符串。
public void testMD5() throws Exception {
String plainText = "Hello , world !" ;
//创建MD5对象
MessageDigest md5 = MessageDigest.getInstance( "md5" );
//加密操作
byte [] cipherData = md5.digest(plainText.getBytes());
//组织输出
StringBuilder builder = new StringBuilder();
for ( byte cipher : cipherData) {
//将其中的每个字节转成十六进制字符串:byte类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数
String toHexStr = Integer.toHexString(cipher & 0xff );
// 如果该正数小于16(长度为1个字符),前面拼接0占位:确保最后生成的是32位字符串
builder.append(toHexStr.length() == 1 ? "0" + toHexStr : toHexStr);
}
System.out.println(builder.toString());
//c0bb4f54f1d8b14caf6fe1069e5f93ad
}
二、使用BASE64进行加密/解密:
使用BASE64算法通常用作对二进制数据进行加密,加密之后的数据不易被肉眼识别。BASE64的加密解密算法都是公开的,可进行加密解密操作。
具体步骤同MD5,首先实例化base64对象,进行加密操作
/**
* 功能简述: 使用BASE64进行双向加密/解密.
* @throws Exception
*/
public void testBase64() throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
BASE64Decoder decoder = new BASE64Decoder();
String plainText = "Hello , world !" ;
String cipherText = encoder.encode(plainText.getBytes());
System.out.println( "cipherText : " + cipherText);
//cipherText : SGVsbG8gLCB3b3JsZCAh
System.out.println( "plainText : " +
new String(decoder.decodeBuffer(cipherText)));
//plainText : Hello , world !
}
三、使用DES对称加密/解密:
数据加密标准算法(Data Encryption Standard),和BASE64最明显的区别就是有一个公有密钥,该密钥既用于加密、也用于解密,并且要求密钥是一个长度至少大于8位的字符串。使用DES加密、解密的核心是确保工作密钥的安全性。
1. 根据key生成密钥:
2. 加密操作:
3. 为了便于观察生成的加密数据,使用BASE64再次加密:
4. 解密操作:
/**
* 功能简述: 使用DES 对称加密/解密.
* @throws Exception
*/
public void testDES() throws Exception {
String plainText = "Hello , world !" ;
String key = "12345678" ; //要求key至少长度为8个字符
//根据key生成密钥
SecureRandom random = new SecureRandom();
DESKeySpec keySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "des" );
SecretKey secretKey = keyFactory.generateSecret(keySpec);
//加密操作
Cipher cipher = Cipher.getInstance( "des" );
cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
byte [] cipherData = cipher.doFinal(plainText.getBytes());
//为了便于观察生成的加密数据,使用BASE64再次加密
System.out.println( "cipherText : " + new BASE64Encoder().encode(cipherData));
//PtRYi3sp7TOR69UrKEIicA==
//解密操作
cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
byte [] plainData = cipher.doFinal(cipherData);
System.out.println( "plainText : " + new String(plainData));
//Hello , world !
}
四、使用RSA非对称加密/解密:
RSA算法是非对称加密算法的典型代表,既能加密、又能解密。和对称加密算法比如DES的明显区别在于用于加密、解密的密钥是不同的。使用RSA算法,只要密钥足够长(一般要求1024bit),加密的信息是不能被破解的。用户通过https协议访问服务器时,就是使用非对称加密算法进行数据的加密、解密操作的。
服务器发送数据给客户端时使用私钥(private key)进行加密,并且使用加密之后的数据和私钥生成数字签名(digital signature)并发送给客户端。客户端接收到服务器发送的数据会使用公钥(public key)对数据来进行解密,并且根据加密数据和公钥验证数字签名的有效性,防止加密数据在传输过程中被第三方进行了修改。
客户端发送数据给服务器时使用公钥进行加密,服务器接收到加密数据之后使用私钥进行解密。
1. 创建密钥对KeyPair:
2. 获取公钥/私钥:
3. 服务器数据使用私钥加密:
4. 用户使用公钥解密:
5. 服务器根据私钥和加密数据生成数字签名:
6. 用户根据公钥、加密数据验证数据是否被修改过:
/**
* 功能简述: 使用RSA非对称加密/解密.
* @throws Exception
*/
public void testRSA() throws Exception {
String plainText = "Hello , world !" ;
//生成公钥私钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( "rsa" );
keyPairGenerator.initialize( 1024 );
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Cipher cipher = Cipher.getInstance( "rsa" );
SecureRandom random = new SecureRandom();
//私钥加密
cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);
byte [] cipherData = cipher.doFinal(plainText.getBytes());
//转成base64
System.out.println( "cipherText : " + new BASE64Encoder().encode(cipherData));
//yQ+vHwHqXhuzZ/N8iNg=
//公钥认证
cipher.init(Cipher.DECRYPT_MODE, publicKey, random);
byte [] plainData = cipher.doFinal(cipherData);
System.out.println( "plainText : " + new String(plainData));
//Hello , world !
/*
*保证消息的完整性
*/
// 服务器根据私钥和加密数据生成数字签名,使用私钥+私钥加密后的数据==》sign生成签名
Signature signature = Signature.getInstance( "MD5withRSA" );
signature.initSign(privateKey);
signature.update(cipherData);
byte [] signData = signature.sign();
System.out.println( "signature : " + new BASE64Encoder().encode(signData));
///t9ewo+KYCWKOgvu5QQ=
//用户根据公钥、加密数据验证数据是否被修改过,使用公钥+私钥加密后的数据===》verify(signData)
signature.initVerify(publicKey);
signature.update(cipherData);
boolean status = signature.verify(signData);
System.out.println( "status : " + status);
//true
}