javaee论坛

普通会员

225648

帖子

355

回复

369

积分

楼主
发表于 2019-10-30 19:11:06 | 查看: 71 | 回复: 1

生成公钥私钥配对加解密

注意:

 

RSA加密或签名后的结果是不可读的二进制,使用时经常会转为BASE64码再传输。

RSA加密时,对要加密数据的大小有限制,最大不大于密钥长度。例如在使用1024bit的密钥时(genrsa-outrsa_private_key.pem1024),最大可以加密1024/8=128Bytes的数据。数据大于128Bytes时,需要对数据进行分组加密(如果数据超限,加解密时会失败,openssl函数会返回false),分组加密后的加密串拼接成一个字符串后发送给客户端。

为了保证每次加密的结果都不同,RSA加密时会在待加密数据后拼接一个随机字符串,再进行加密。不同的填充方式Padding表示这个字符串的不同长度,在对超限数据进行分组后,会按照这个Padding指定的长度填入随机字符串。例如如果Padding填充方式使用默认的OPENSSL_PKCS1_PADDING(需要占用11个字节用于填充),那么明文长度最多只能就是128-11=117Bytes。

一般默认使用OPENSSL_PKCS1_PADDING。PHP支持的Padding有OPENSSL_PKCS1_PADDING、OPENSSL_SSLV23_PADDING、OPENSSL_PKCS1_OAEP_PADDING和OPENSSL_NO_PADDING。

接收方解密时也需要分组。将加密后的原始二进制数据(对于经过BASE64的数据,需要解码),每128Bytes分为一组,然后再进行解密。解密后,根据Padding的长度丢弃随机字符串,把得到的原字符串拼接起来,就得到原始报文。

importjava.io.IOException;

importjava.security.KeyFactory;

importjava.security.NoSuchAlgorithmException;

importjava.security.PrivateKey;

importjava.security.PublicKey;

importjava.security.spec.InvalidKeySpecException;

importjava.security.spec.PKCS8EncodedKeySpec;

importjava.security.spec.X509EncodedKeySpec;

 

importjavax.crypto.BadPaddingException;

importjavax.crypto.Cipher;

importjavax.crypto.IllegalBlockSizeException;

 

importorg.apache.commons.io.output.ByteArrayOutputStream;

importorg.springframework.util.Base64Utils;

 

importcom.bessky.hrmis.common.uconfig.UConfigHelper;

importcom.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;

importcom.sun.org.apache.xml.internal.security.utils.Base64;

 

publicclassRSAHelper

{

  privatestaticfinalStringpublicKeyBase64="";

 

  privatestaticfinalStringprivateKeyBase64="";

   

  /**

   *RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024

   */

  publicstaticfinalintKEY_SIZE=2048;

 

  /**

   *获取公钥对象

   *

   *@parampublicKeyBase64

   *@return

   *@throwsInvalidKeySpecException

   *@throwsNoSuchAlgorithmException

   */

  publicstaticPublicKeygetPublicKey(StringpublicKeyBase64)throwsInvalidKeySpecException,NoSuchAlgorithmException,Base64DecodingException

  {

    KeyFactorykeyFactory=KeyFactory.getInstance("RSA");

    X509EncodedKeySpecpublicpkcs8KeySpec=newX509EncodedKeySpec(Base64.decode(publicKeyBase64));

    PublicKeypublicKey=keyFactory.generatePublic(publicpkcs8KeySpec);

    returnpublicKey;

  }

 

  /**

   *获取私钥对象

   *

   *@paramprivateKeyBase64

   *@return

   *@throwsNoSuchAlgorithmException

   *@throwsInvalidKeySpecException

   */

  publicstaticPrivateKeygetPrivateKey(StringprivateKeyBase64)throwsNoSuchAlgorithmException,InvalidKeySpecException,Base64DecodingException

  {

    KeyFactorykeyFactory=KeyFactory.getInstance("RSA");

    PKCS8EncodedKeySpecprivatekcs8KeySpec=newPKCS8EncodedKeySpec(Base64.decode(privateKeyBase64));

    PrivateKeyprivateKey=keyFactory.generatePrivate(privatekcs8KeySpec);

    returnprivateKey;

  }

 

  /**

   *使用工钥加密

   *

   *@paramcontent     待加密内容

   *@parampublicKeyBase64公钥base64编码

   *@return经过base64编码后的字符串

   */

  publicstaticStringencipher(Stringcontent)

  {

    returnencipher(content,publicKeyBase64,KEY_SIZE/8-11);

  }

 

  /**

   *使用公司钥加密(分段加密)

   *

   *@paramcontent     待加密内容

   *@parampublicKeyBase64公钥base64编码

   *@paramsegmentSize   分段大小,一般小于keySize/8(段小于等于0时,将不使用分段加密)

   *@return经过base64编码后的字符串

   */

  publicstaticStringencipher(Stringcontent,StringpublicKeyBase64,intsegmentSize)

  {

    try

    {

      PublicKeypublicKey=getPublicKey(publicKeyBase64);

      returnencipher(content,publicKey,segmentSize);

    }

    catch(Exceptione)

    {

      e.printStackTrace();

      returnnull;

    }

  }

 

  /**

   *分段加密

   *

   *@paramciphertext 密文

   *@paramkey     加密秘钥

   *@paramsegmentSize分段大小,<=0不分段

   *@return

   */

  publicstaticStringencipher(Stringciphertext,java.security.Keykey,intsegmentSize)

  {

    try

    {

      //用公钥加密

      byte[]srcBytes=ciphertext.getBytes();

 

      //Cipher负责完成加密或解密工作,基于RSA

      Ciphercipher=Cipher.getInstance("RSA");

      //根据公钥,对Cipher对象进行初始化

      cipher.init(Cipher.ENCRYPT_MODE,key);

      byte[]resultBytes=null;

 

      if(segmentSize>0)

        resultBytes=cipherDoFinal(cipher,srcBytes,segmentSize);//分段加密

      else

        resultBytes=cipher.doFinal(srcBytes);

      Stringbase64Str=Base64Utils.encodeToString(resultBytes);

      returnbase64Str;

    }

    catch(Exceptione)

    {

      e.printStackTrace();

      returnnull;

    }

  }

 

  /**

   *分段大小

   *

   *@paramcipher

   *@paramsrcBytes

   *@paramsegmentSize

   *@return

   *@throwsIllegalBlockSizeException

   *@throwsBadPaddingException

   *@throwsIOException

   */

  publicstaticbyte[]cipherDoFinal(Ciphercipher,byte[]srcBytes,intsegmentSize)throwsIllegalBlockSizeException,BadPaddingException,IOException

  {

    if(segmentSize<=0)

      thrownewRuntimeException("分段大小必须大于0");

    ByteArrayOutputStreamout=newByteArrayOutputStream();

    intinputLen=srcBytes.length;

    intoffSet=0;

    byte[]cache;

    inti=0;

    //对数据分段解密

    while(inputLen-offSet>0)

    {

      if(inputLen-offSet>segmentSize)

      {

        cache=cipher.doFinal(srcBytes,offSet,segmentSize);

      }

      else

      {

        cache=cipher.doFinal(srcBytes,offSet,inputLen-offSet);

      }

      out.write(cache,0,cache.length);

      i++;

      offSet=i*segmentSize;

    }

    byte[]data=out.toByteArray();

    out.close();

    returndata;

  }

 

  /**

   *使用私钥解密

   *

   *@paramcontentBase64  待加密内容,base64编码

   *@paramprivateKeyBase64私钥base64编码

   *@return

   *@segmentSize分段大小

   */

  publicstaticStringdecipher(StringcontentBase64)

  {

    returndecipher(contentBase64,privateKeyBase64,KEY_SIZE/8);

  }

 

  /**

   *使用私钥解密(分段解密)

   *

   *@paramcontentBase64  待加密内容,base64编码

   *@paramprivateKeyBase64私钥base64编码

   *@return

   *@segmentSize分段大小

   */

  publicstaticStringdecipher(StringcontentBase64,StringprivateKeyBase64,intsegmentSize)

  {

    try

    {

      PrivateKeyprivateKey=getPrivateKey(privateKeyBase64);

      returndecipher(contentBase64,privateKey,segmentSize);

    }

    catch(Exceptione)

    {

      e.printStackTrace();

      returnnull;

    }

  }

 

  /**

   *分段解密

   *

   *@paramcontentBase64密文

   *@paramkey      解密秘钥

   *@paramsegmentSize  分段大小(小于等于0不分段)

   *@return

   */

  publicstaticStringdecipher(StringcontentBase64,java.security.Keykey,intsegmentSize)

  {

    try

    {

      //用私钥解密

      byte[]srcBytes=Base64Utils.decodeFromString(contentBase64);

      //Cipher负责完成加密或解密工作,基于RSA

      CipherdeCipher=Cipher.getInstance("RSA");

      //根据公钥,对Cipher对象进行初始化

      deCipher.init(Cipher.DECRYPT_MODE,key);

      byte[]decBytes=null;//deCipher.doFinal(srcBytes);

      if(segmentSize>0)

        decBytes=cipherDoFinal(deCipher,srcBytes,segmentSize);//分段加密

      else

        decBytes=deCipher.doFinal(srcBytes);

 

      StringdecrytStr=newString(decBytes);

      returndecrytStr;

    }

    catch(Exceptione)

    {

      e.printStackTrace();

    }  }}

 

 


普通会员

0

帖子

331

回复

339

积分
沙发
发表于 2019-11-13 15:36:17

信春哥,得永生!

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017