JAVA RSA 源碼

來源:互聯網
上載者:User

鑒於rsa加密的重要性和相關原始碼的匱乏,經過整理特此貼出。需要下載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 工具類。提供加密,解密,產生金鑰組等方法。
  * 需要到http://www.bouncycastle.org下載bcprov-jdk14-123.jar。
  *
  */
  public class RSAUtil {
  
  /**
  * 產生金鑰組
  * @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;//沒什麼好說的了,這個值關係到塊加密的大小,可以更改,但是不要太大,否則效率會低
  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 待加密的明文資料
  * @return 加密後的資料
  * @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();//獲得加密塊大小,如:加密前資料為128個byte,而key_size=1024 加密塊大小為127 byte,加密後為128個byte;因此共有2個加密塊,第一個127 byte第二個為1個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方法不可用,查看原始碼後發現每次doUpdate後並沒有什麼實際動作除了把byte[]放到ByteArrayOutputStream中,而最後doFinal的時候才將所有的byte[]進行加密,可是到了此時加密塊大小很可能已經超出了OutputSize所以只好用dofinal方法。
  
  i++;
  }
  return raw;
  } catch (Exception e) {
  throw new EncryptException(e.getMessage());
  }
  }
  /**
  * 解密
  * @param key 解密的密鑰
  * @param raw 已經加密的資料
  * @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();
  }
  }
  
  加密可以用公開金鑰,解密用私密金鑰;或者加密用私密金鑰。通常非對稱式加密是非常消耗資源的,因此可以對大資料用對稱式加密如:des(具體代碼可以看我以前發的貼子),而對其對稱金鑰進行非對稱式加密,這樣既保證了資料的安全,還能保證效率。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.