前言
最近开发 用到数据加密 研究后要用RSA和AES对称加密工具
以前没搞过 记录一下心酸过程
说明
客户端和服务端的加密代码是不同的 即使都是java语言 只有一些模式和参数需要同步设置
比如字节码和加密模式
RSAUtils
package com.mob.common.utils;
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
/**
* RSA加密工具
*/
public class RSAUtils {
//构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding"
private static String sTransform = "RSA/NONE/PKCS1Padding";
//进行Base64转码时的flag设置,默认为Base64.DEFAULT
private static int sBase64Mode = Base64.DEFAULT;
//初始化方法,设置参数
public static void init(String transform, int base64Mode) {
sTransform = transform;
sBase64Mode = base64Mode;
}
/*
产生密钥对
@param keyLength
密钥长度,小于1024长度的密钥已经被证实是不安全的,通常设置为1024或者2048,建议2048
*/
public static KeyPair generateRSAKeyPair(int keyLength) {
KeyPair keyPair = null;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
//设置密钥长度
keyPairGenerator.initialize(keyLength);
//产生密钥对
keyPair = keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return keyPair;
}
/*
加密或解密数据的通用方法
@param srcData
待处理的数据
@param key
公钥或者私钥
@param mode
指定是加密还是解密,值为Cipher.ENCRYPT_MODE或者Cipher.DECRYPT_MODE
*/
private static byte[] processData(byte[] srcData, Key key, int mode) {
//用来保存处理结果
byte[] resultBytes = null;
try {
//获取Cipher实例
Cipher cipher = Cipher.getInstance(sTransform);
//初始化Cipher,mode指定是加密还是解密,key为公钥或私钥
cipher.init(mode, key);
//处理数据
resultBytes = cipher.doFinal(srcData);
} catch (NoSuchAlgorithmException
| NoSuchPaddingException | InvalidKeyException
| BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return resultBytes;
}
/*
使用公钥加密数据,结果用Base64转码
*/
public static String encryptDataByPublicKey(byte[] srcData, PublicKey publicKey) {
byte[] resultBytes = processData(srcData, publicKey, Cipher.ENCRYPT_MODE);
if (resultBytes != null && resultBytes.length > 0) {
return Base64.encodeToString(resultBytes, sBase64Mode);
}
return "";
}
/*
使用私钥解密,返回解码数据
*/
public static byte[] decryptDataByPrivate(String encryptedData, PrivateKey privateKey) {
byte[] bytes = Base64.decode(encryptedData, sBase64Mode);
return processData(bytes, privateKey, Cipher.DECRYPT_MODE);
}
/*
使用私钥进行解密,解密数据转换为字符串,使用utf-8编码格式
*/
public static String decryptedToStrByPrivate(String encryptedData, PrivateKey privateKey) {
return new String(decryptDataByPrivate(encryptedData, privateKey));
}
/*
使用私钥解密,解密数据转换为字符串,并指定字符集
*/
public static String decryptedToStrByPrivate(String encryptedData, PrivateKey privateKey, String charset) {
try {
return new String(decryptDataByPrivate(encryptedData, privateKey), charset);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
/*
使用私钥加密,结果用Base64转码
*/
public static String encryptDataByPrivateKey(byte[] srcData, PrivateKey privateKey) {
byte[] resultBytes = processData(srcData, privateKey, Cipher.ENCRYPT_MODE);
return Base64.encodeToString(resultBytes, sBase64Mode);
}
/*
使用公钥解密,返回解密数据
*/
public static byte[] decryptDataByPublicKey(String encryptedData, PublicKey publicKey) {
byte[] bytes = Base64.decode(encryptedData, sBase64Mode);
return processData(bytes, publicKey, Cipher.DECRYPT_MODE);
}
/*
使用公钥解密,结果转换为字符串,使用默认字符集utf-8
*/
public static String decryptedToStrByPublicKey(String encryptedData, PublicKey publicKey) {
return new String(decryptDataByPublicKey(encryptedData, publicKey));
}
/*
使用公钥解密,结果转换为字符串,使用指定字符集
*/
public static String decryptedToStrByPublicKey(String encryptedData, PublicKey publicKey, String charset) {
try {
return new String(decryptDataByPublicKey(encryptedData, publicKey), charset);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
/*
将字符串形式的公钥转换为公钥对象
*/
public static PublicKey keyStrToPublicKey(String publicKeyStr) {
PublicKey publicKey = null;
byte[] keyBytes = Base64.decode(publicKeyStr, sBase64Mode);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return publicKey;
}
/*
将字符串形式的私钥,转换为私钥对象
*/
public static PrivateKey keyStrToPrivate(String privateKeyStr) {
PrivateKey privateKey = null;
byte[] keyBytes = Base64.decode(privateKeyStr, sBase64Mode);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return privateKey;
}
}
AESUtils
package com.mob.common.utils;
import android.util.Base64;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
/**
* AES加密工具
*/
public class AESUtils {
/**
* 加密算法
*/
private static final String KEY_ALGORITHM = "AES";
/**
* AES 的 密钥长度,32 字节,范围:16 - 32 字节
*/
public static final int SECRET_KEY_LENGTH = 16;
/**
* 字符编码
*/
private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
/**
* 秘钥长度不足 16 个字节时,默认填充位数
*/
private static final String DEFAULT_VALUE = "0";
/**
* 加解密算法/工作模式/填充方式
*/
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
/**
* AES 加密
*
* @param data 待加密内容
* @param secretKey 加密密码,长度:16 或 32 个字符
* @return 返回Base64转码后的加密数据
*/
public static String encrypt(String data, String secretKey) {
try {
//创建密码器
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//初始化为加密密码器
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(secretKey));
byte[] encryptByte = cipher.doFinal(data.getBytes(CHARSET_UTF8));
// 将加密以后的数据进行 Base64 编码
return base64Encode(encryptByte);
} catch (Exception e) {
handleException(e);
}
return null;
}
/**
* AES 解密
*
* @param base64Data 加密的密文 Base64 字符串
* @param secretKey 解密的密钥,长度:16 或 32 个字符
*/
public static String decrypt(String base64Data, String secretKey) {
try {
byte[] data = base64Decode(base64Data);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(secretKey));
//执行解密操作
byte[] result = cipher.doFinal(data);
return new String(result, CHARSET_UTF8);
} catch (Exception e) {
handleException(e);
}
return null;
}
/**
* 使用密码获取 AES 秘钥
*/
public static SecretKeySpec getSecretKey(String secretKey) {
secretKey = toMakeKey(secretKey, SECRET_KEY_LENGTH, DEFAULT_VALUE);
return new SecretKeySpec(secretKey.getBytes(CHARSET_UTF8), KEY_ALGORITHM);
}
/**
* 如果 AES 的密钥小于 {@code length} 的长度,就对秘钥进行补位,保证秘钥安全。
*
* @param secretKey 密钥 key
* @param length 密钥应有的长度
* @param text 默认补的文本
* @return 密钥
*/
private static String toMakeKey(String secretKey, int length, String text) {
// 获取密钥长度
int strLen = secretKey.length();
// 判断长度是否小于应有的长度
if (strLen < length) {
// 补全位数
StringBuilder builder = new StringBuilder();
// 将key添加至builder中
builder.append(secretKey);
// 遍历添加默认文本
for (int i = 0; i < length - strLen; i++) {
builder.append(text);
}
// 赋值
secretKey = builder.toString();
}
return secretKey;
}
/**
* 将 Base64 字符串 解码成 字节数组
*/
public static byte[] base64Decode(String data) {
return Base64.decode(data, Base64.NO_WRAP);
}
/**
* 将 字节数组 转换成 Base64 编码
*/
public static String base64Encode(byte[] data) {
return Base64.encodeToString(data, Base64.NO_WRAP);
}
/**
* 处理异常
*/
private static void handleException(Exception e) {
e.printStackTrace();
}
}
测试代码
//字符串公钥
public static final String PUBLIC_KEY_STR = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHhR8P0HdnoXXvgeH2DIIxHWrI\n" +
"bfH4+rr3sqJ5z/mkBcYu7+n2f74CZABZGXyNyVMZgGB8giPKijBxjZuMAevqHxuR\n" +
"Yi22DxyOnP3kQXQVaHv9XukPpZXpDsxj6jb1ngy8rRrw2Zb1ofGLDicM2IVB9Ma8\n" +
"G8wdIPu10qrVytYsLwIDAQAB";
//字符串密钥
public static final String PRIVATE_KEY_STR = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJK3E8oqdY/AfV71/Dx+RaYhTV52hdkPgPfTAAyvH5doQvHG0WrgfGoona410P45/6NJ8w02BTWaU3wOwBR082mnmNk18edwb2vi+2RrYhO4micTfNRq5jFwapvh+FqYCJLe1VDWNwQtdLaf7b7OrqG9sZ2vMDyw8bujhdRkOvenAgMBAAECgYAZspV1yKAU0Ltk4aMPmXJrmdOqYwoorc2CGuQcVKQs6ecn4BIYLT+9fGW5+NUlYlVDbZVzz+1zqRdMWG0OaDmmFoyqzZ0te+vwekzdniCBkGK+1i9nSyR6ix9zdmXLxPlh4qxYZ0kiBwPtCKsb1RddlmBEneMGiCtLxe62b0TmQQJBAP1UGTiMOPi+X4i2/PTfBC99fKv/6trXmcczgdJmdS9ThfsO3y9sQbIdwXaR/z6eBKCLb9QYYrNSrFeWUZHj9KECQQCUQyifZXqGYP+5fMMZsKE2RuZf8dQ1OknK73S+EvlaDTvmd/DNGB3v9Kxmh0rJgmdUA6gK9drEVRYuxs1rvr9HAkBHCfBQpTHMv0X3BqmE2Y1I6/2sFgX7/H3JGK6NG+I8tUVbE96OY+NAWYvI/kP/gTx28OMZLQVwl/xwS1zwdmZBAkAn08ak0vjQAlyPslEipI0Z7H/URD0yMz9BcYPVz3kGVMnDhnK8VX8tR3fMbwmLCinBqt3IW/Txir3TwPnLuMjfAkAcbOPSFt0ebHYdKU9aeoFsBnDycT7GYYLWl4h1bZ+TAWcsnp46s1IJLVPIscwOOlIsxgd2+OX2OOSgxXPlT3RD";
public static final String CONTENT = "TI3b7oglaExMRLZ+2XZrNBW+ExMmbPk+Js9SAKt4xuf1UfGrYIYInQkMUPIt1D4QnOyvnblUfle54B9/IAMNefban5IRBmh4dPKd/c7yqVIGPzWeVujfWJZjFw8owNX0gwNcixb7fbIDk16ZRpZHoqtHLsCzMLljCMYHqHhkwY4=";
/**
* Rsa测试代码
*/
String s = RSAUtils.decryptedToStrByPrivate(CONTENT, RSAUtils.keyStrToPrivate(PRIVATE_KEY_STR));
Log.e("RSA解密:", s);
//获取公钥
PublicKey publicKey = RSAUtils.keyStrToPublicKey(PUBLIC_KEY_STR);
//获取私钥
PrivateKey privateKey = RSAUtils.keyStrToPrivate(PRIVATE_KEY_STR);
//需要加密的数据
String clearText01 = "123";
//公钥加密结果
String publicEncryptedResult = RSAUtils.encryptDataByPublicKey(clearText01.getBytes(), publicKey);
//私钥解密结果
String privateDecryptedResult = RSAUtils.decryptedToStrByPrivate(publicEncryptedResult, privateKey);
Logger.d("公钥加密,私钥解密测试:\n"
+ "原文:\n" + clearText01 + "\n"
+ "公钥加密结果:\n" + publicEncryptedResult + "\n"
+ "私钥解密结果:\n" + privateDecryptedResult
);
//需要加密的数据
String clearText02 = "456";
//私钥加密结果
String privateEncryptedResult = RSAUtils.encryptDataByPrivateKey(clearText02.getBytes(), privateKey);
//公钥解密结果
String publicDecryptedResult = RSAUtils.decryptedToStrByPublicKey(privateEncryptedResult, publicKey);
Logger.d("私钥加密,公钥解密测试:\n"
+ "原文:\n" + clearText02 + "\n"
+ "私钥加密结果:\n" + privateEncryptedResult + "\n"
+ "公钥解密结果:\n" + publicDecryptedResult
);
/**
* AES测试代码
*/
try {
String encrypt = AESUtils.decrypt( "jpgg/hUUtntX3D6VAnA7LWw9eGkdfp1WIjtBKnOWOjY=","wyq6hxm1cqmq4w8r");
Log.e("AES-解密:", encrypt);
} catch (Exception e) {
e.printStackTrace();
}