RSA加解密(JAVA)
程序员文章站
2024-03-14 17:27:28
...
RSA加解密(JAVA)
记录一下java如何使用RSA,以下主要有三种方法,基本大同小异,只是获取公钥私钥的途径不一样,总结起来也就是:
1. KeyPairGenerator获取key
2. String获取key
3. modulus和exponent获取key
方法一:
利用KeyPairGenerator直接生成公钥和**,一般私钥保留给服务端,公钥交给客户端
package com.michael.RSA;
import javax.crypto.Cipher;
import java.security.*;
import java.util.Base64;
public class RSACryptography {
public static String data = "hello world";
public static void main(String[] args) {
KeyPair keyPair = genKeyPair(1024);
// 获取公钥,并以base64格式打印出来
PublicKey publicKey = keyPair.getPublic();
System.out.println("公钥:" + base64Encode(publicKey.getEncoded()));
// 获取私钥,并以base64格式打印出来
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("私钥:" + base64Encode(privateKey.getEncoded()));
// 公钥加密
byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
System.out.println("加密后:" + new String(encryptedBytes));
// 私钥解密
byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
System.out.println("解密后:" + new String(decryptedBytes));
}
public static String base64Encode(byte[] src) {
return new String(Base64.getEncoder().encode(src));
}
/**
* 生成**对
*
* @param keyLength
* @return
*/
public static KeyPair genKeyPair(int keyLength) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
return keyPairGenerator.generateKeyPair();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 公钥加密
*
* @param content
* @param publicKey
* @return
*/
public static byte[] encrypt(byte[] content, PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance("RSA");// java默认"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 私钥解密
*
* @param content
* @param privateKey
* @return
*/
public static byte[] decrypt(byte[] content, PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
方法二:
方法一只是用来生成**就OK了,生成的**需要保存到本地文件中,所以一般不会在客户端调用KeyPairGenerator进行**的生成操作。
可以将方法一得到的**保存到文件,下次我们直接读取就可以了。
假设以String的形式保存在文件内,那么接下来直接使用读取到的String生成**即可。
也可以使用openssl来生成
package com.michael.RSA;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;
public class RSACryptography2 {
public static String data = "hello world";
public static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCISLP98M/56HexX/9FDM8iuIEQozy6kn2JMcbZS5/BhJ+U4PZIChJfggYlWnd8NWn4BYr2kxxyO8Qgvc8rpRZCkN0OSLqLgZGmNvoSlDw80UXq90ZsVHDTOHuSFHw8Bv//B4evUNJBB8g9tpVxr6P5EJ6FMoR/kY2dVFQCQM4+5QIDAQAB";
public static String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIhIs/3wz/nod7Ff/0UMzyK4gRCjPLqSfYkxxtlLn8GEn5Tg9kgKEl+CBiVad3w1afgFivaTHHI7xCC9zyulFkKQ3Q5IuouBkaY2+hKUPDzRRer3RmxUcNM4e5IUfDwG//8Hh69Q0kEHyD22lXGvo/kQnoUyhH+RjZ1UVAJAzj7lAgMBAAECgYAVh26vsggY0Yl/Asw/qztZn837w93HF3cvYiaokxLErl/LVBJz5OtsHQ09f2IaxBFedfmy5CB9R0W/aly851JxrI8WAkx2W2FNllzhha01fmlNlOSumoiRF++JcbsAjDcrcIiR8eSVNuB6ymBCrx/FqhdX3+t/VUbSAFXYT9tsgQJBALsHurnovZS1qjCTl6pkNS0V5qio88SzYP7lzgq0eYGlvfupdlLX8/MrSdi4DherMTcutUcaTzgQU20uAI0EMyECQQC6il1Kdkw8Peeb0JZMHbs+cMCsbGATiAt4pfo1b/i9/BO0QnRgDqYcjt3J9Ux22dPYbDpDtMjMRNrAKFb4BJdFAkBMrdWTZOVc88IL2mcC98SJcII5wdL3YSeyOZto7icmzUH/zLFzM5CTsLq8/HDiqVArNJ4jwZia/q6Fg6e8KO2hAkB0EK1VLF/ox7e5GkK533Hmuu8XGWN6I5bHnbYd06qYQyTbbtHMBrFSaY4UH91Qwd3u9gAWqoCZoGnfT/o03V5lAkBqq8jZd2lHifey+9cf1hsHD5WQbjJKPPIb57CK08hn7vUlX5ePJ02Q8AhdZKETaW+EsqJWpNgsu5wPqsy2UynO";
public static void main(String[] args) {
//获取公钥
PublicKey publicKey = getPublicKey(PUBLIC_KEY);
//获取私钥
PrivateKey privateKey = getPrivateKey(PRIVATE_KEY);
//公钥加密
byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
System.out.println("加密后:" + new String(encryptedBytes));
//私钥解密
byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
System.out.println("解密后:" + new String(decryptedBytes));
}
/**
* 将base64编码后的公钥字符串转成PublicKey实例
*
* @param publicKey
* @return
*/
public static PublicKey getPublicKey(String publicKey) {
try {
byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将base64编码后的私钥字符串转成PrivateKey实例
*
* @param privateKey
* @return
*/
public static PrivateKey getPrivateKey(String privateKey) {
try {
byte[] keyBytes = Base64.getDecoder().decode(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 公钥加密
*
* @param content
* @param publicKey
* @return
*/
public static byte[] encrypt(byte[] content, PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance("RSA");// java默认"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 私钥解密
*
* @param content
* @param privateKey
* @return
*/
public static byte[] decrypt(byte[] content, PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
方法三:
除了保存**字符串之外,其他的做法一般是只保存 模n(modulus),公钥和私钥的e和d(exponent);其中,n, e, d可以这样获取到,获取到后可以保存到本地文件中。
//获取公钥
RSAPublicKey publicKey=(RSAPublicKey) getPublicKey(publicKeyString);
BigInteger modulus1=publicKey.getModulus();
BigInteger exponent1=publicKey.getPublicExponent();
//获取私钥
RSAPrivateKey privateKey=(RSAPrivateKey) getPrivateKey(privateKeyString);
BigInteger modulus2=privateKey.getModulus();
BigInteger exponent2=privateKey..getPrivateExponent();
假设已经从文件中读取到了modulus
和 exponent
:
package com.michael.RSA;
import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
public class RSACryptography3 {
public static String data = "hello world";
public static String MODULUS = "95701876885335270857822974167577168764621211406341574477817778908798408856077334510496515211568839843884498881589280440763139683446418982307428928523091367233376499779842840789220784202847513854967218444344438545354682865713417516385450114501727182277555013890267914809715178404671863643421619292274848317157";
public static String PUBLIC_EXPONENT = "65537";
public static String PRIVATE_EXPONENT = "15118200884902819158506511612629910252530988627643229329521452996670429328272100404155979400725883072214721713247384231857130859555987849975263007110480563992945828011871526769689381461965107692102011772019212674436519765580328720044447875477151172925640047963361834004267745612848169871802590337012858580097";
public static void main(String[] args) throws Exception {
//由n和e获取公钥
PublicKey publicKey = getPublicKey(MODULUS, PUBLIC_EXPONENT);
//由n和d获取私钥
PrivateKey privateKey = getPrivateKey(MODULUS, PRIVATE_EXPONENT);
//公钥加密
String encrypted = encrypt(data, publicKey);
System.out.println("加密后:" + encrypted);
//私钥解密
String decrypted = decrypt(encrypted, privateKey);
System.out.println("解密后:" + new String(decrypted));
}
/**
* 将base64编码后的公钥字符串转成PublicKey实例
*
* @param modulusStr
* @param exponentStr
* @return
*/
public static PublicKey getPublicKey(String modulusStr, String exponentStr) {
try {
BigInteger modulus = new BigInteger(modulusStr);
BigInteger exponent = new BigInteger(exponentStr);
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(publicKeySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将base64编码后的私钥字符串转成PrivateKey实例
*
* @param modulusStr
* @param exponentStr
* @return
*/
public static PrivateKey getPrivateKey(String modulusStr, String exponentStr) {
try {
BigInteger modulus = new BigInteger(modulusStr);
BigInteger exponent = new BigInteger(exponentStr);
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(privateKeySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 公钥加密,并转换成十六进制字符串打印出来
*
* @param content
* @param publicKey
* @return
*/
public static String encrypt(String content, PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance("RSA");// java默认"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8 - 11;
byte[][] arrays = splitBytes(content.getBytes(), splitLength);
StringBuffer sb = new StringBuffer();
for (byte[] array : arrays) {
sb.append(bytesToHexString(cipher.doFinal(array)));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 私钥解密,并转换成十六进制字符串打印出来
*
* @param content
* @param privateKey
* @return
*/
public static String decrypt(String content, PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8;
byte[] contentBytes = hexString2Bytes(content);
byte[][] arrays = splitBytes(contentBytes, splitLength);
StringBuffer sb = new StringBuffer();
for (byte[] array : arrays) {
sb.append(new String(cipher.doFinal(array)));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 拆分byte数组
*
* @param bytes
* @param splitLength
* @return
*/
public static byte[][] splitBytes(byte[] bytes, int splitLength) {
int x; //商,数据拆分的组数,余数不为0时+1
int y; //余数
y = bytes.length % splitLength;
if (y != 0) {
x = bytes.length / splitLength + 1;
} else {
x = bytes.length / splitLength;
}
byte[][] arrays = new byte[x][];
byte[] array;
for (int i = 0; i < x; i++) {
if (i == x - 1 && bytes.length % splitLength != 0) {
array = new byte[bytes.length % splitLength];
System.arraycopy(bytes, i * splitLength, array, 0, bytes.length % splitLength);
} else {
array = new byte[splitLength];
System.arraycopy(bytes, i * splitLength, array, 0, splitLength);
}
arrays[i] = array;
}
return arrays;
}
/**
* byte数组转十六进制字符串
*
* @param bytes
* @return
*/
public static String bytesToHexString(byte[] bytes) {
StringBuffer sb = new StringBuffer(bytes.length);
String sTemp;
for (int i = 0; i < bytes.length; i++) {
sTemp = Integer.toHexString(0xFF & bytes[i]);
if (sTemp.length() < 2)
sb.append(0);
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
/**
* 十六进制字符串转byte数组
*
* @param hex
* @return
*/
public static byte[] hexString2Bytes(String hex) {
int len = (hex.length() / 2);
hex = hex.toUpperCase();
byte[] result = new byte[len];
char[] achar = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
}
return result;
}
private static byte toByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
}
上一篇: php aes加解密
下一篇: java serlve后台数据传到前台