鑒于rsa加密的重要性和相關(guān)源代碼的匱乏,經(jīng)過整理特此貼出。需要下載bcprov-jdk14-123.jar。
  
  import javax.crypto.Cipher;
  import java.security.*;
  import java.security.spec.RSAPublicKeySpec;
  import java.security.spec.RSAPrivateKeySpec;
  import java.security.spec.InvalidKeySpecException;
  import java.security.interfaces.RSAPrivateKey;
  import java.security.interfaces.RSAPublicKey;
  import java.io.*;
  import java.math.BigInteger;
  
  /**
  * RSA 工具類。提供加密,解密,生成密鑰對(duì)等方法。
  * 需要到http://www.bouncycastle.org下載bcprov-jdk14-123.jar。
  *
  */
  public class RSAUtil {
  
  /**
  * 生成密鑰對(duì)
  * @return KeyPair
  * @throws EncryptException
  */
  public static KeyPair generateKeyPair() throws EncryptException {
  try {
  KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
  new org.bouncycastle.jce.provider.BouncyCastleProvider());
  final int KEY_SIZE = 1024;//沒什么好說的了,這個(gè)值關(guān)系到塊加密的大小,可以更改,但是不要太大,否則效率會(huì)低
  keyPairGen.initialize(KEY_SIZE, new SecureRandom());
  KeyPair keyPair = keyPairGen.genKeyPair();
  return keyPair;
  } catch (Exception e) {
  throw new EncryptException(e.getMessage());
  }
  }
  /**
  * 生成公鑰
  * @param modulus
  * @param publicExponent
  * @return RSAPublicKey
  * @throws EncryptException
  */
  public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws EncryptException {
  KeyFactory keyFac = null;
  try {
  keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  } catch (NoSuchAlgorithmException ex) {
  throw new EncryptException(ex.getMessage());
  }
  
  RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
  try {
  return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
  } catch (InvalidKeySpecException ex) {
  throw new EncryptException(ex.getMessage());
  }
  }
  /**
  * 生成私鑰
  * @param modulus
  * @param privateExponent
  * @return RSAPrivateKey
  * @throws EncryptException
  */
  public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws EncryptException {
  KeyFactory keyFac = null;
  try {
  keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  } catch (NoSuchAlgorithmException ex) {
  throw new EncryptException(ex.getMessage());
  }
  
  RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
  try {
  return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
  } catch (InvalidKeySpecException ex) {
  throw new EncryptException(ex.getMessage());
  }
  }
  /**
  * 加密
  * @param key 加密的密鑰
  * @param data 待加密的明文數(shù)據(jù)
  * @return 加密后的數(shù)據(jù)
  * @throws EncryptException
  */
  public static byte[] encrypt(Key key, byte[] data) throws EncryptException {
  try {
  Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  cipher.init(Cipher.ENCRYPT_MODE, key);
  int blockSize = cipher.getBlockSize();//獲得加密塊大小,如:加密前數(shù)據(jù)為128個(gè)byte,而key_size=1024 加密塊大小為127 byte,加密后為128個(gè)byte;因此共有2個(gè)加密塊,第一個(gè)127 byte第二個(gè)為1個(gè)byte
  int outputSize = cipher.getOutputSize(data.length);//獲得加密塊加密后塊大小
  int leavedSize = data.length % blockSize;
  int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
  byte[] raw = new byte[outputSize * blocksSize];
  int i = 0;
  while (data.length - i * blockSize > 0) {
  if (data.length - i * blockSize > blockSize)
  cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
  else
  cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
  //這里面doUpdate方法不可用,查看源代碼后發(fā)現(xiàn)每次doUpdate后并沒有什么實(shí)際動(dòng)作除了把byte[]放到ByteArrayOutputStream中,而最后doFinal的時(shí)候才將所有的byte[]進(jìn)行加密,可是到了此時(shí)加密塊大小很可能已經(jīng)超出了OutputSize所以只好用dofinal方法。
  
  i++;
  }
  return raw;
  } catch (Exception e) {
  throw new EncryptException(e.getMessage());
  }
  }
  /**
  * 解密
  * @param key 解密的密鑰
  * @param raw 已經(jīng)加密的數(shù)據(jù)
  * @return 解密后的明文
  * @throws EncryptException
  */
  public static byte[] decrypt(Key key, byte[] raw) throws EncryptException {
  try {
  Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  cipher.init(cipher.DECRYPT_MODE, key);
  int blockSize = cipher.getBlockSize();
  ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
  int j = 0;
  
  while (raw.length - j * blockSize > 0) {
  bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
  j++;
  }
  return bout.toByteArray();
  } catch (Exception e) {
  throw new EncryptException(e.getMessage());
  }
  }
  /**
  *
  * @param args
  * @throws Exception
  */
  public static void main(String[] args) throws Exception {
  File file = new File("test.html");
  FileInputStream in = new FileInputStream(file);
  ByteArrayOutputStream bout = new ByteArrayOutputStream();
  byte[] tmpbuf = new byte[1024];
  int count = 0;
  while ((count = in.read(tmpbuf)) != -1) {
  bout.write(tmpbuf, 0, count);
  tmpbuf = new byte[1024];
  }
  in.close();
  byte[] orgData = bout.toByteArray();
  KeyPair keyPair = RSAUtil.generateKeyPair();
  RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
  RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
  
  byte[] pubModBytes = pubKey.getModulus().toByteArray();
  byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();
  byte[] priModBytes = priKey.getModulus().toByteArray();
  byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();
  RSAPublicKey recoveryPubKey = RSAUtil.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
  RSAPrivateKey recoveryPriKey = RSAUtil.generateRSAPrivateKey(priModBytes,priPriExpBytes);
  
  byte[] raw = RSAUtil.encrypt(priKey, orgData);
  file = new File("encrypt_result.dat");
  OutputStream out = new FileOutputStream(file);
  out.write(raw);
  out.close();
  byte[] data = RSAUtil.decrypt(recoveryPubKey, raw);
  file = new File("decrypt_result.html");
  out = new FileOutputStream(file);
  out.write(data);
  out.flush();
  out.close();
  }
  }
  
  加密可以用公鑰,解密用私鑰;或者加密用私鑰。通常非對(duì)稱加密是非常消耗資源的,因此可以對(duì)大數(shù)據(jù)用對(duì)稱加密如:des(具體代碼可以看我以前發(fā)的貼子),而對(duì)其對(duì)稱密鑰進(jìn)行非對(duì)稱加密,這樣既保證了數(shù)據(jù)的安全,還能保證效率。