一、背景

  最近工作中涉及到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. 递归生成treeview树形节点(没有用递归函数之后会有补充,这里只用系统的内置方法去生成)

    using System;using System.Collections.Generic;using System.ComponentModel;using System.IO;using Syst ...

  2. JavaScript的replace方法与正则表达式结合应用讲解

    大家好!!今晚在华软G43*宿舍没什么事做,把javascript中replace方法讲解一下,如果讲得不对或不合理是情理之中的事,因为我不是老鸟,也不是菜鸟,我也不知道我当底是什么鸟??呵~~ re ...

  3. 2018.07.23[PA2015]Siano(线段树)

    [PA2015]Siano 描述 Description 农夫Byteasar买了一片n亩的土地,他要在这上面种草. 他在每一亩土地上都种植了一种独一无二的草,其中,第i亩土地的草每天会长高a[i]厘 ...

  4. C++之类和对象课后习题1

    建立一个对象数组,内放5个学生的(学号,成绩),设立一个函数max,用指向对象的指针作函数参数,在max函数中找出5个学生的最高成绩者,并输出其学号. #include<iostream> ...

  5. BZOJ 1007 [HNOI2008]水平可见直线 (栈)

    1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7940  Solved: 3030[Submit][Sta ...

  6. 深入浅析JavaScript中with语句的理解

    JavaScript 有个 with 关键字, with 语句的原本用意是为逐级的对象访问提供命名空间式的速写方式. 也就是在指定的代码区域, 直接通过节点名称调用对象. with语句的作用是暂时改变 ...

  7. ASYNC PROGRAMING IN JAVASCRIPT[转]

    本文从异步风格讲起,分析Javascript中异步变成的技巧.问题和解决方案.具体的,从回调造成的问题说起,并谈到了利用事件.Promise.Generator等技术来解决这些问题. 异步之殇 NON ...

  8. jmap的几个操作要慎用

    JDK中带有了一堆的工具是可以用来查看运行状况,排查问题的,但对于这些工具还是要比较清楚执行后会发生什么,否则有可能会因为执行了一个命令就导致严重故障,重点讲下影响比较大的jmap. 最主要的危险操作 ...

  9. SetFocus (GetDlgItem (hwnd, idFocus))函数的各参数的具体含义

    Setfocus(HWMD hwnd):将窗口hwnd设置成获得焦点 GetDlgItem (hwnd, idFocus):此函数返回一个句柄 具体参数的含义: hwnd:包含该窗口标志位的对话框的句 ...

  10. Android操作HTTP实现与服务器通信

    (转自http://www.cnblogs.com/hanyonglu/archive/2012/02/19/2357842.html) 本示例以Servlet为例,演示Android与Servlet ...