Created
January 30, 2019 06:39
-
-
Save zhuhai/f94db18b9a023b281fac87da14bd883a to your computer and use it in GitHub Desktop.
RSA加解密工具类
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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