服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

java非对称加密的源代码(rsa)


  鉴于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(具体代码可以看我以前发的贴子),而对其对称密钥进行非对称加密,这样既保证了数据的安全,还能保证效率。

扫描关注微信公众号