一、背景

  最近工作中涉及到RSA加密的相关需求任务,之前对加密算法了解不多,开发过程中遇到了一些坑记录一下。

二、RSA原理

RSA加密是非对称加密,公开私钥,保留私钥。通信时数据通过公开的公钥加密,接收方用私钥解密,达到安全传输的目的。RSA算法原理在这就不详述了,放个链接                     https://blog.csdn.net/raalghul/article/details/51883354

三、JAVA实现

    公钥和私钥 都是由 两个数的组合构成,这样储存不太方便。 用base64将PublicKey 和PrivateKey对象  转为公钥、私钥 字符串。

    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider());
    generator.initialize(2048, new SecureRandom());
    KeyPair keyPair = generator.generateKeyPair();
    PublicKey publicKey = keyPair.getPublic();
    String pubKey = new String(Base64.encodeBase64(publicKey.getEncoded()));
    System.out.println("公钥:"+pubKey);
    PrivateKey privateKey = keyPair.getPrivate();
    String priKey = new String(Base64.encodeBase64(privateKey.getEncoded()));
    System.out.println("私钥:"+priKey);

    在加密解密的过程中需要的仍是 PublicKey 和PrivateKey对象, 需要将 公钥、私钥字符串转换为 PublicKey 和PrivateKey对象 来实现加密 解密。

    //公钥string 转publicKey对象
    public static PublicKey getPublicKey(String key) throws Exception {
      byte[] keyBytes;
      keyBytes = (new sun.misc.BASE64Decoder()).decodeBuffer(key);
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      PublicKey publicKey = keyFactory.generatePublic(keySpec);
      return publicKey;
      }

    //公钥string 转publicKey对象
    public static PublicKey getPublicKey(String key) throws Exception {
      byte[] keyBytes;
      keyBytes = (new sun.misc.BASE64Decoder()).decodeBuffer(key);
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      PublicKey publicKey = keyFactory.generatePublic(keySpec);
      return publicKey;
      }  

    其他部分代码贴出,如果不注意编码问题会抛出javax.crypto.IllegalBlockSizeException,在代码中标出

public static PrivateKey getPrivateKey(String key) throws Exception{
byte[] keyBytes;
keyBytes = (new sun.misc.BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}

//加密
public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}

/**
* byte[] b1 byte[] b2 byte[] b1 String
* String data----getBytes(默认编码)-----公钥加密(ISO字符集,使用其他字符集数据丢失)---------私钥解密----------new String(默认编码)----String data
*
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider());
generator.initialize(2048, new SecureRandom());
KeyPair keyPair = generator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
String pubKey = new String(Base64.encodeBase64(publicKey.getEncoded()));
System.out.println("公钥:"+pubKey);
PrivateKey privateKey = keyPair.getPrivate();
String priKey = new String(Base64.encodeBase64(privateKey.getEncoded()));
System.out.println("私钥:"+priKey);
//公钥加密 此时的getBytes() 的编码 为默认 应该和最后的 new String() 的编码一样
byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
//将密文字节数组转String时 不使用ISO编码 可能导致数据丢失 解密失败

//如果下面两句 没有指明编码,或者使用其他编码,会导致数据的错误,导致字节数组b1长度超出限制, 报出异常javax.crypto.IllegalBlockSizeException,具体原因可能是因为在公钥加密时使用的字符集问题。
String s1 = new String(encryptedBytes,"ISO8859-1");
byte[] b1 = s1.getBytes("ISO8859-1");
//解密
byte[] decryptedByte = decrypt(b1, privateKey);
System.out.println("解密后:"+new String(decryptedByte));

}

public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);

}
}

运行结果:

欢迎大家关注我的个人微信订阅号:Java从零单排   分享学习资料,交流学习经验~

RSA的JAVA实现 及javax.crypto.IllegalBlockSizeException的更多相关文章

  1. javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher--转载

    原文地址:http://songjianyong.iteye.com/blog/1571029 /** * AESHelper.java * cn.com.songjy.test * * Functi ...

  2. Android AES加密报错处理:javax.crypto.IllegalBlockSizeException: error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH

    一.问题说明 今天写AES加/解密功能的apk,设想是四个控件(测试用的,界面丑这种东西请忽略) 一个编缉框----用于输入要加密的字符串 一个文本框----用于输出加密后的字符串,和加密后点击解密按 ...

  3. url请求时,参数中的+在服务器接收时为空格,导致AES加密报出javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

    报错的意思的是使用该种解密方式出入长度应为16bit的倍数,但实际的错误却不是这个,错误原因根本上是因为在http请求是特殊字符编码错误,具体就是base64生成的+号,服务器接收时成了空格,然后导致 ...

  4. java rsa 解密报:javax.crypto.BadPaddingException: Decryption error

    Exception in thread "main" javax.crypto.BadPaddingException: Decryption error    at sun.se ...

  5. Liunx-https-java.lang.NoClassDefFoundError: javax/crypto/SunJCE_b

    错误信息: java.lang.NoClassDefFoundError: javax/crypto/SunJCE_b at javax.crypto.KeyGenerator.a(DashoA13* ...

  6. Unable to execute 'doFinal' with cipher instance [javax.crypto.Cipher@4e025e0a]

    org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal' with cipher instance [javax.cry ...

  7. AES算法,DES算法,RSA算法JAVA实现

    1     AES算法 1.1    算法描述 1.1.1      设计思想 Rijndael密码的设计力求满足以下3条标准: ① 抵抗所有已知的攻击. ② 在多个平台上速度快,编码紧凑. ③ 设计 ...

  8. Android网络传输中必用的两个加密算法:MD5 和 RSA (附java完成测试代码)

    MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,只能加密而不能解密.比如明 ...

  9. C# RSA和Java RSA互通

    今天调查了C# RSA和Java RSA,网上很多人说,C#加密或者java加密 ,Java不能解密或者C#不能解密 但是我尝试了一下,发现是可以的,下面就是我尝试的代码,如果您有什么问题,我想看看, ...

随机推荐

  1. 【转】Hibernate的getSQLQuery方法对char类型的解析问题

    [转]Hibernate的getSQLQuery方法对char类型的解析问题 建立数据库: create table T_TEST1( id char (32), name varchar (255) ...

  2. python之web开发利器

    http://docs.jinkan.org/docs/flask/ https://www.djangoproject.com/

  3. 2018.07.08 POJ 2481 Cows(线段树)

    Cows Time Limit: 3000MS Memory Limit: 65536K Description Farmer John's cows have discovered that the ...

  4. Git客户端命令总结

    一:常用命令 1.先进入项目目录,然后git init:则会为此 项目/目录 创建一个本地仓库(或重新初始化这个本地仓库),可以用ls -a ./看到多了.git目录: 或者git init /hom ...

  5. SIGPIPE导致cronttab和shell脚本等工作异常

    cron和sh等可能被某些共享库hook,而这些共享库可能会触发SIGPIPE,导致crontab和shell工作异常,解决办法是程序忽略SIGPIPE或脚本中使用"trap '' SIGP ...

  6. WriteableBitmap(二) 实例

    使用前面定义的WriteableBitmap,我们可以很容易地创建一个足够容纳整个100 x 100图像的数组: byte[] pixels = new byte[wbmap.PixelHeight* ...

  7. ( KMP 求循环节的个数)Power Strings -- poj -- 2406

    链接: http://poj.org/problem?id=2406 Power Strings Time Limit:3000MS     Memory Limit:65536KB     64bi ...

  8. 17、docker多机网络通信overlay

      理论上来说多台宿主机之间的docker容器之间是无法通讯的,但是多台宿主机之间的docker容器之间是可以通讯的,主要是通过VXLAN技术来实现的.   GitHub上对于docker-overl ...

  9. Jack Clark 的几句名言

    Grateful for everything; entitled to nothing. 沒有任何事情是你不该感激的:沒有任何东西是你该派得到的. Leadership is the ability ...

  10. 可移植类库无法使用async、await关键字

    今天遇到了如题所示的问题,平台已经选择了.net 4.5了,可是就是编译不通过,await关键字下出现了红色下划线. 解决方法:安装一个Bcl的补丁包. https://www.nuget.org/p ...