Skip to content

Instantly share code, notes, and snippets.

@zhuhai
Created January 30, 2019 06:39
Show Gist options
  • Save zhuhai/f94db18b9a023b281fac87da14bd883a to your computer and use it in GitHub Desktop.
Save zhuhai/f94db18b9a023b281fac87da14bd883a to your computer and use it in GitHub Desktop.
RSA加解密工具类
public class RsaUtil {
/**
* 密钥位数
*/
private static final int RAS_KEY_SIZE = 1024;
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 填充方式
*/
public static final String KEY_ALGORITHM_PADDING = "RSA/ECB/PKCS1Padding";
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 128 - 11;
public static final String PRIVATE_KEY = "";
public static final String PUBLIC_KEY = "";
/**
* 编码密钥,便于存储
*
* @param key key
* @return xxx String String
* @throws Exception Exception
*/
public static String encodeBase64(Key key) throws Exception {
return Base64.encodeBase64String(key.getEncoded());
}
/**
* 从字符串解码私钥
*
* @param key key
* @return xxx
* @throws Exception Exception
*/
public static PrivateKey decodePrivateKey(String key) throws Exception {
byte[] keyBytes = Base64.decodeBase64(key);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return keyFactory.generatePrivate(pkcs8KeySpec);
}
/**
* 从字符串解码公钥
*
* @param publicKey publicKey
* @return xxx
* @throws Exception Exception
*/
public static PublicKey decodePublicKey(String publicKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return keyFactory.generatePublic(x509KeySpec);
}
/**
* 用私钥对信息生成数字签名
*
* @param data data 已加密数据
* @param privateKey privateKey 私钥(BASE64编码)
* @return xxx
* @throws Exception Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(decodePrivateKey(privateKey));
signature.update(data);
return Base64.encodeBase64String(signature.sign());
}
/**
* 校验数字签名
*
* @param data data 已加密数据
* @param publicKey publicKey 公钥(BASE64编码)
* @param sign sign 数字签名
* @return xxx
* @throws Exception Exception
*/
public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(decodePublicKey(publicKey));
signature.update(data);
return signature.verify(Base64.decodeBase64(sign));
}
/**
* 使用模和指数生成RSA公钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,
* 不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus modulus 模
* @param exponent exponent 指数
* @return xxx
*/
public static RSAPublicKey getPublicKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
//LOGGER.error("getPublicKey ex modulus={}, exponent={}", modulus, exponent, e);
}
return null;
}
/**
* 使用模和指数生成RSA私钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,
* 不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus modulus 模
* @param exponent exponent 指数
* @return xxx
*/
public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
//LOGGER.error("getPrivateKey ex modulus={}, exponent={}", modulus, exponent, e);
return null;
}
}
/**
* 生成密钥对
*
*/
public static void generateKeyPair() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(RAS_KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
String privatekeyStr = Base64.encodeBase64String(privateKey.getEncoded());
String publicKeyStr = Base64.encodeBase64String(publicKey.getEncoded());
System.out.println("privateKey is " + privatekeyStr);
System.out.println("publicKey is " + publicKeyStr);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 公钥加密
*
* @param data data
* @param publicKey publicKey
* @return xxx
*/
public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 模长
int key_len = publicKey.getModulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
//如果明文长度大于模长-11则要分组加密
return doFinal(cipher, data, key_len - 11);
} catch (Exception e) {
}
return null;
}
/**
* 私钥解密
*
* @param data data
* @param privateKey privateKey
* @return xxx
*/
public static byte[] decryptByPrivateKey(byte[] data, RSAPrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_PADDING);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//模长
int key_len = privateKey.getModulus().bitLength() / 8;
//如果密文长度大于模长则要分组解密
return doFinal(cipher, data, key_len);
} catch (Exception e) {
}
return null;
}
/**
* 注意:RSA加密明文最大长度117字节,
* 解密要求密文最大长度为128字节,
* 所以在加密和解密的过程中需要分块进行。
*
* @param cipher cipher
* @param data data
* @return xxx
* @throws BadPaddingException BadPaddingException
* @throws IllegalBlockSizeException IllegalBlockSizeException
*/
private static byte[] doFinal(Cipher cipher, byte[] data, int key_len) throws BadPaddingException, IllegalBlockSizeException {
int inputLen = data.length, offSet = 0;
byte[] tmp;
ByteArrayOutputStream out = new ByteArrayOutputStream(getTmpArrayLength(inputLen));
while (inputLen > 0) {
tmp = cipher.doFinal(data, offSet, Math.min(key_len, inputLen));
out.write(tmp, 0, tmp.length);
offSet += key_len;
inputLen -= key_len;
}
return out.toByteArray();
}
private static int getTmpArrayLength(int L) {
int S = MAX_DECRYPT_BLOCK;
while (S < L) {
S <<= 1;
}
return S;
}
/**
* 私钥解密
*
* @param data data 已加密数据
* @param privateKey privateKey 私钥(BASE64编码)
* @return xxx
* @throws Exception Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception {
PrivateKey key = decodePrivateKey(privateKey);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_PADDING);
cipher.init(Cipher.DECRYPT_MODE, key);
return doFinal(cipher, data, MAX_DECRYPT_BLOCK);
}
/**
* 公钥解密
*
* @param data data 已加密数据
* @param publicKey publicKey 公钥(BASE64编码)
* @return xxx
* @throws Exception Exception
*/
public static byte[] decryptByPublicKey(byte[] data, String publicKey) throws Exception {
PublicKey key = decodePublicKey(publicKey);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_PADDING);
cipher.init(Cipher.DECRYPT_MODE, key);
return doFinal(cipher, data, MAX_DECRYPT_BLOCK);
}
/**
* 公钥加密
*
* @param data data 源数据
* @param publicKey publicKey 公钥(BASE64编码)
* @return xxx
* @throws Exception Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
PublicKey key = decodePublicKey(publicKey);
// 对数据加密
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, key);
return doFinal(cipher, data, MAX_ENCRYPT_BLOCK);
}
/**
* 私钥加密
*
* @param data data 源数据
* @param privateKey privateKey 私钥(BASE64编码)
* @return xxx
* @throws Exception Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
PrivateKey key = decodePrivateKey(privateKey);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, key);
return doFinal(cipher, data, MAX_ENCRYPT_BLOCK);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment