———————RSA非對(duì)稱可逆加密———————
RSA加密原理概述:
RSA的安全性依賴于大數(shù)的分解,公鑰和私鑰都是兩個(gè)大素?cái)?shù)(大于100的十進(jìn)制位)的函數(shù)。從一個(gè)密鑰和密文推斷出明文的難度等同于分解兩個(gè)大素?cái)?shù)的積
- 1.選擇兩個(gè)大素?cái)?shù) p,q ,計(jì)算 n=p*q;
- 2.隨機(jī)選擇加密密鑰 e ,要求 e 和 (p-1)*(q-1)互質(zhì)
- 3.利用 Euclid算法計(jì)算解密密鑰 d , 使其滿足 ed = 1(mod(p-1)(q-1)) (其中 n,d 也要互質(zhì))
- 4:至此得出公鑰為 (n,e) 私鑰為 * (n,d) 加解密方法:
- 1.首先將要加密的信息 m(二進(jìn)制表示) 分成等長(zhǎng)的
數(shù)據(jù)塊 m1,m2,…,mi 塊長(zhǎng) s(盡可能大) ,其中2^s< n - 2:對(duì)應(yīng)的密文是: ci = mi^e(mod n)
- 3:解密時(shí)作如下計(jì)算: mi = ci^d(mod n)
- 1.首先將要加密的信息 m(二進(jìn)制表示) 分成等長(zhǎng)的
RSA速度:
由于進(jìn)行的都是大數(shù)計(jì)算贩挣,使得RSA最快的情況也比DES慢上100倍,無(wú)論 是軟件還是硬件實(shí)現(xiàn)。 速度一直是RSA的缺陷痒蓬。一般來(lái)說(shuō)只用于少量數(shù)據(jù) 加密童擎。
RSAUtils工具類:
package com.example.rsa;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
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.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
public final class RSAUtils
{
private static String RSA = "RSA";
private static final String TransForMation = "RSA/None/PKCS1Padding";
/**
* 隨機(jī)生成RSA密鑰對(duì)(默認(rèn)密鑰長(zhǎng)度為1024)
*
* @return
*/
public static KeyPair generateRSAKeyPair()
{
return generateRSAKeyPair(1024);
}
/**
* 隨機(jī)生成RSA密鑰對(duì)
*
* @param keyLength
* 密鑰長(zhǎng)度,范圍:512~2048<br>
* 一般1024
* @return
*/
public static KeyPair generateRSAKeyPair(int keyLength)
{
try
{
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keyLength);
return kpg.genKeyPair();
} catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
return null;
}
}
/**
* 用公鑰加密 <br>
* 每次加密的字節(jié)數(shù)攻晒,不能超過(guò)密鑰的長(zhǎng)度值減去11
*
* @param data
* 需加密數(shù)據(jù)的byte數(shù)據(jù)
* @param pubKey
* 公鑰
* @return 加密后的byte型數(shù)據(jù)
*/
public static byte[] encryptData(byte[] data, PublicKey publicKey)
{
try
{
Cipher cipher = Cipher.getInstance(TransForMation);
// 編碼前設(shè)定編碼方式及密鑰
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 傳入編碼數(shù)據(jù)并返回編碼結(jié)果
return cipher.doFinal(data);
} catch (Exception e)
{
e.printStackTrace();
return null;
}
}
/**
* 用私鑰解密
*
* @param encryptedData
* 經(jīng)過(guò)encryptedData()加密返回的byte數(shù)據(jù)
* @param privateKey
* 私鑰
* @return
*/
public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey)
{
try
{
Cipher cipher = Cipher.getInstance(TransForMation);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(encryptedData);
} catch (Exception e)
{
return null;
}
}
/**
* 通過(guò)公鑰byte[](publicKey.getEncoded())將公鑰還原顾复,適用于RSA算法
*
* @param keyBytes
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException,
InvalidKeySpecException
{
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 通過(guò)私鑰byte[]將公鑰還原,適用于RSA算法
*
* @param keyBytes
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException,
InvalidKeySpecException
{
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 使用N鲁捏、e值還原公鑰
*
* @param modulus
* @param publicExponent
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public static PublicKey getPublicKey(String modulus, String publicExponent)
throws NoSuchAlgorithmException, InvalidKeySpecException
{
BigInteger bigIntModulus = new BigInteger(modulus);
BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 使用N芯砸、d值還原私鑰
*
* @param modulus
* @param privateExponent
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public static PrivateKey getPrivateKey(String modulus, String privateExponent)
throws NoSuchAlgorithmException, InvalidKeySpecException
{
BigInteger bigIntModulus = new BigInteger(modulus);
BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 從字符串中加載公鑰
*
* @param publicKeyStr
* 公鑰數(shù)據(jù)字符串
* @throws Exception
* 加載公鑰時(shí)產(chǎn)生的異常
*/
public static PublicKey loadPublicKey(String publicKeyStr) throws Exception
{
try
{
byte[] buffer = Base64Utils.decode(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e)
{
throw new Exception("無(wú)此算法");
} catch (InvalidKeySpecException e)
{
throw new Exception("公鑰非法");
} catch (NullPointerException e)
{
throw new Exception("公鑰數(shù)據(jù)為空");
}
}
/**
* 從字符串中加載私鑰<br>
* 加載時(shí)使用的是PKCS8EncodedKeySpec(PKCS#8編碼的Key指令)。
*
* @param privateKeyStr
* @return
* @throws Exception
*/
public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception
{
try
{
byte[] buffer = Base64Utils.decode(privateKeyStr);
// X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e)
{
throw new Exception("無(wú)此算法");
} catch (InvalidKeySpecException e)
{
throw new Exception("私鑰非法");
} catch (NullPointerException e)
{
throw new Exception("私鑰數(shù)據(jù)為空");
}
}
/**
* 從文件中輸入流中加載公鑰
*
* @param in
* 公鑰輸入流
* @throws Exception
* 加載公鑰時(shí)產(chǎn)生的異常
*/
public static PublicKey loadPublicKey(InputStream in) throws Exception
{
try
{
return loadPublicKey(readKey(in));
} catch (IOException e)
{
throw new Exception("公鑰數(shù)據(jù)流讀取錯(cuò)誤");
} catch (NullPointerException e)
{
throw new Exception("公鑰輸入流為空");
}
}
/**
* 從文件中加載私鑰
*
* @param keyFileName
* 私鑰文件名
* @return 是否成功
* @throws Exception
*/
public static PrivateKey loadPrivateKey(InputStream in) throws Exception
{
try
{
return loadPrivateKey(readKey(in));
} catch (IOException e)
{
throw new Exception("私鑰數(shù)據(jù)讀取錯(cuò)誤");
} catch (NullPointerException e)
{
throw new Exception("私鑰輸入流為空");
}
}
/**
* 讀取密鑰信息
*
* @param in
* @return
* @throws IOException
*/
private static String readKey(InputStream in) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String readLine = null;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null)
{
if (readLine.charAt(0) == '-')
{
continue;
} else
{
sb.append(readLine);
sb.append('\r');
}
}
return sb.toString();
}
/**
* 打印公鑰信息
*
* @param publicKey
*/
public static void printPublicKeyInfo(PublicKey publicKey)
{
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
System.out.println("----------RSAPublicKey----------");
System.out.println("Modulus.length=" + rsaPublicKey.getModulus().bitLength());
System.out.println("Modulus=" + rsaPublicKey.getModulus().toString());
System.out.println("PublicExponent.length=" + rsaPublicKey.getPublicExponent().bitLength());
System.out.println("PublicExponent=" + rsaPublicKey.getPublicExponent().toString());
}
public static void printPrivateKeyInfo(PrivateKey privateKey)
{
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
System.out.println("----------RSAPrivateKey ----------");
System.out.println("Modulus.length=" + rsaPrivateKey.getModulus().bitLength());
System.out.println("Modulus=" + rsaPrivateKey.getModulus().toString());
System.out.println("PrivateExponent.length=" + rsaPrivateKey.getPrivateExponent().bitLength());
System.out.println("PrivatecExponent=" + rsaPrivateKey.getPrivateExponent().toString());
}
}
特別說(shuō)明:
1.以上的加解密只是針對(duì)單個(gè)Block塊的给梅,如果需要支持N個(gè)塊假丧,則需要自己?jiǎn)为?dú)對(duì)數(shù)據(jù)進(jìn)行切分。
比如1024位加解密动羽,單個(gè)block的size是128個(gè)字節(jié)包帚。
2.注意密鑰填充方式,這里用的是PKCS1运吓。