rsa~对接第三方rsa问题排查


对称加加密

  1. 甲方选择某一种加密规则,对信息进行加密;
  2. 乙方使用同一种规则,对信息进行解密。

由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法"(Symmetric-key algorithm)。
这种加密模式有一个最大弱点:甲方必须把加密规则告诉乙方,否则无法解密。保存和传递密钥,就成了最头疼的问题。

非对称加密

  1. 乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
  2. 甲方获取乙方的公钥,然后用它对信息加密。
  3. 乙方得到加密后的信息,用私钥解密。

如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。
这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位,4096位的密钥极其安全。

rsa原理

参考:https://blog.csdn.net/wjiabin/article/details/85228078

数学基础知识

素数:又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数;最小的合数是4,最小的质数是2
互质:又称互素。若N个整数的最大公因子是1,则称这N个整数互质。
模运算即求余运算:“模”是“Mod”的音译。和模运算紧密相关的一个概念是“同余”。数学上,当两个整数除以同一个正整数,若得相同余数,则二整数同余。

欧拉函数

任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?(比如,在1到8之中,有多少个数与8构成互质关系?)计算这个值的方法就叫做欧拉函数,以φ(n)表示。

  • 计算8的欧拉函数,和8互质的 1、2、3、4、5、6、7、8
    φ(8) = 4
    如果n是质数的某一个次方,即 n = p^k (p为质数,k为大于等于1的整数),则φ(n) = φ(p^k) = p^k - p^(k-1)。也就是φ(8) = φ(2^3) =2^3 - 2^2 = 8 -4 = 4
  • 计算7的欧拉函数,和7互质的 1、2、3、4、5、6、7
    φ(7) = 6
    如果n是质数,则 φ(n)=n-1 。因为质数与小于它的每一个数,都构成互质关系。比如5与1、2、3、4都构成互质关系。
  • 计算56的欧拉函数
    φ(56) = φ(8) * φ(7) = 4 * 6 = 24
    如果n可以分解成两个互质的整数之积,即 n = p * k ,则φ(n) = φ(p * k) = φ(p1)*φ(p2)

欧拉定理:如果两个正整数m和n互质,那么m的φ(n)次方减去1,可以被n整除。
费马小定理:欧拉定理的特殊情况,如果两个正整数m和n互质,而且n为质数!那么φ(n)结果就是n-1。

模反元素

还剩下最后一个概念,模反元素:如果两个正整数e和x互质,那么一定可以找到整数d,使得 ed-1 被x整除,或者说ed被x除的余数是1。
那么d就是e相对于x的模反元素。

第三方升级的文本解密

  1. 需要知道它rsa的密钥长度,下面总结了长度与加密和解密时的对应关系,两个值相差11
  • 长度:1024 加密块长度:117 解密块长度:128
  • 长度:2048 加密块长度:245 解密块长度:256
  • 长度:4096 加密块长度:501 解密块长度:512

测试

@Test
  public void test() throws Exception {
    // 生成密钥对
    KeyPair keyPair = RSAUtils.getKeyPair();
    String privateKey = new String(Base64Utils.encode(keyPair.getPrivate().getEncoded()));
    String publicKey = new String(Base64Utils.encode(keyPair.getPublic().getEncoded()));
    System.out.println("私钥:" + privateKey);
    System.out.println("公钥:" + publicKey);
    // RSA加密
    String data = "123456";
    String encryptData = RSAUtils.encrypt(data, RSAUtils.getPublicKey(publicKey));
    System.out.println("加密后内容:" + encryptData);
    // RSA解密
    String decryptData = RSAUtils.decrypt(encryptData, RSAUtils.getPrivateKey(privateKey));
    System.out.println("解密后内容:" + decryptData);
    // RSA签名
    String sign = RSAUtils.sign(data, RSAUtils.getPrivateKey(privateKey));
    // RSA验签
    boolean result = RSAUtils.verify(data, RSAUtils.getPublicKey(publicKey), sign);
    System.out.print("验签结果:" + result);
  }