java加解密之RSA使用
来源:程序员人生 发布时间:2016-09-30 10:53:57 阅读次数:2469次
最近为了分析1段要求流,不能不去研究1下RSA加密。
首先,强调1点:密钥的“钥”读“yue”,不是“yao”,额。。。
网上关于RSA的原理1抓1大把的,这里只是简单说说我的理解:
1. 两个足够大的互质数p, q;
2. 用于模运算的模 n=p*q;
3. 公钥KU(e, n)中的e满足 1<e< (p⑴)(q⑴),且与(p⑴)(q⑴)互质;
4. 密钥KR(d, n)中的d满足 d*e % (p⑴)(q⑴)= 1,%是取余运算。
由于公钥是公然的,所以我知道了e和n,那末根据2,3,4式子的关系,我们只要从n的值推出p, q的值则可计算出d的值,也就可以找到密钥。
但是,关键就在这里, n=p*q,如果两个互质数p和q足够大,那末根据目前的计算机技术和其他工具,至今也没能从n分解出p和q,这是数学上的1个困难,也正是这个困难成了RSA加密至今被广泛使用的缘由。换句话说,只要密钥长度n足够大(1般1024足矣),基本上不可能从公钥信息推出私钥信息。
好了,这里作为研究的随笔,记录1下java如何使用,以下主要有3种方法,基本大同小异,只是获得公钥私钥的途径不1样就是了:
方法1:
利用KeyPairGenerator直接生成公钥和密钥,1般私钥保存给服务端,公钥交给客户端。
public class RSACryptography {
public static String data="hello world";
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
KeyPair keyPair=genKeyPair(1024);
//获得公钥,并以base64格式打印出来
PublicKey publicKey=keyPair.getPublic();
System.out.println("公钥:"+new String(Base64.getEncoder().encode(publicKey.getEncoded())));
//获得私钥,并以base64格式打印出来
PrivateKey privateKey=keyPair.getPrivate();
System.out.println("私钥:"+new String(Base64.getEncoder().encode(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 KeyPair genKeyPair(int keyLength) throws Exception{
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
return keyPairGenerator.generateKeyPair();
}
//公钥加密
public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");//java默许"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}
//私钥解密
public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
}
}
运行结果:
方法2:
实际上,方法1只是用来生成密钥就OK了,生成的密钥需要保存到本地文件中,所以1般不会在客户端调用KeyPairGenerator进行密钥的生成操作。
这里,我们可以将方法1得到的密钥保存到文件,下次我们直接读取就能够了。我假定以String的情势保存在文件内,那末接下来直接使用读取到的String生成密钥便可。
固然,你也能够使用openssl来生成也能够,不过我觉得麻烦就不弄了。
public class RSACryptography {
public static String data="hello world";
public static String publicKeyString="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCISLP98M/56HexX/9FDM8iuIEQozy6kn2JMcbZS5/BhJ+U4PZIChJfggYlWnd8NWn4BYr2kxxyO8Qgvc8rpRZCkN0OSLqLgZGmNvoSlDw80UXq90ZsVHDTOHuSFHw8Bv//B4evUNJBB8g9tpVxr6P5EJ6FMoR/kY2dVFQCQM4+5QIDAQAB";
public static String privateKeyString="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) throws Exception {
// TODO Auto-generated method stub
//获得公钥
PublicKey publicKey=getPublicKey(publicKeyString);
//获得私钥
PrivateKey privateKey=getPrivateKey(privateKeyString);
//公钥加密
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实例
public static PublicKey getPublicKey(String publicKey) throws Exception{
byte[ ] keyBytes=Base64.getDecoder().decode(publicKey.getBytes());
X509EncodedKeySpec keySpec=new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory=KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
//将base64编码后的私钥字符串转成PrivateKey实例
public static PrivateKey getPrivateKey(String privateKey) throws Exception{
byte[ ] keyBytes=Base64.getDecoder().decode(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory=KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
//公钥加密
public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");//java默许"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}
//私钥解密
public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
}
}
运行结果:
方法3:
除保存密钥字符串以外,其他的做法1般是只保存 模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:
public class RSACryptography {
public static String data="hello world";
public static String modulusString="95701876885335270857822974167577168764621211406341574477817778908798408856077334510496515211568839843884498881589280440763139683446418982307428928523091367233376499779842840789220784202847513854967218444344438545354682865713417516385450114501727182277555013890267914809715178404671863643421619292274848317157";
public static String publicExponentString="65537";
public static String privateExponentString="15118200884902819158506511612629910252530988627643229329521452996670429328272100404155979400725883072214721713247384231857130859555987849975263007110480563992945828011871526769689381461965107692102011772019212674436519765580328720044447875477151172925640047963361834004267745612848169871802590337012858580097";
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//由n和e获得公钥
PublicKey publicKey=getPublicKey(modulusString, publicExponentString);
//由n和d获得私钥
PrivateKey privateKey=getPrivateKey(modulusString, privateExponentString);
//公钥加密
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实例
public static PublicKey getPublicKey(String modulusStr, String exponentStr) throws Exception{
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);
}
//将base64编码后的私钥字符串转成PrivateKey实例
public static PrivateKey getPrivateKey(String modulusStr, String exponentStr) throws Exception{
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);
}
//公钥加密
public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");//java默许"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}
//私钥解密
public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
}
}
运行结果:
这里3种方式总结起来也就是
1,.KeyPairGenerator获得key;
2. String获得key;
3. modulus和exponent获得key。
但是,当加密的数据太长的时候需要
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠