云服务常见安全算法之RSA介绍

举报
我还没用力 发表于 2020/08/27 17:32:15 2020/08/27
【摘要】 介绍一种数字加密及签名算法-RSA的数学原理及推导,简易实现及jdk实现

RSA加密算法是唯一广泛接受并实现,第一个既能用于数据加密也能用于数字签名的算法。云服务中RSA的身影随处可见,如token,加密证书等,这篇文章就为大家解开RSA的神秘面纱。


1.数据加密

对称加密:对信息的加解密都采用相同的密钥Key。

                  优点:简化加解密处理过程,只要在交换阶段,密钥没有泄露,那么加密数据的机密性跟报文完整性就                   可以得到保证。

 缺点:都要用到同一个key,更容易泄露。

非对称加密:密钥被分解为一对:公钥PK加密, 密钥SK解密(可互换)。公钥通过非保密方式公开,而私钥由解密方保存。

优点:安全性高。

 缺点:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。


2.RSA算法基础

  • 互质关系:如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系。

    任意两个质数构成互质关系

    一个数是质数,另一个数只要不是前者的倍数,两者就构成互质关系

    如果两个数之中,较大的那个数是质数,则两者构成互质关系

    ......

  • 欧拉函数:求任意给定正整数n,在小于等于n的正整数之中,有多少个数与n构成互质关系?

                                              n=1;  T=ψ(n)=1;

                                           n为质数;T=ψ(n)=n-1;

                 n为两个质数的乘积;n=PQ, T=ψ(n)=ψ(P)ψ(Q)=(P-1)(Q-1);

    ......

  • 欧拉定理:如果两个正整数a和n互质,则n的欧拉函数 φ(n) 可以让下面的等式成立

                                                      T=ψ(n),a^T=1(mod(n))

  • 模反元素:如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除。

                                                    ab=1(mod(n))

推出——————》RSA定理

若P,Q是互异质数,n=PQ, T=ψ(n),另有正整数E与D,E与T互质,并使得(ED)mod(T)=1。

有正整数A,且A<PQ,设:

                                      A^Emod(n)=C ,  C^Dmod(n)=B

则有A=B。

   public static void simple() {
       // 1.任选两个质数
       Integer P = 11;
       Integer Q = 13;
       // 2.PQ相乘得到N
       Integer N = P * Q;
       // 3.N的欧拉函数
       Integer T = (P - 1) * (Q - 1);// T = ψ(n)
       // 4.任选一个与T互质的整数(小于T)作为密钥,
       Integer E = 7; // 一般选择65537
       // 5.计算另一个密钥
       Integer D = null;
       for (Integer i = 0; i < N; i++) {
           if ((E * i) % T == 1) {
               D = i;
          }
      }
       // 明文为3 经过对公钥(N,E)的模指运算得到密文
       System.out.println(new BigInteger("3").modPow(new BigInteger(E.toString()), new BigInteger(N.toString())));
       // 密文为42 经过对密钥(N,D)的模指运算得到密文
       System.out.println(new BigInteger("42").modPow(new BigInteger(D.toString()), new BigInteger(N.toString())));
  }

被破解的可能性:

P、Q、N、T、E、D

传播中暴露的是:N、E、C

解密信息需要:N、D

数学难题:大数因式分解  N = P * Q

3.RSA加密 jdk类包实现

public static void cipher() {
       try {
           // 初始化密钥
           KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
           keyPairGenerator.initialize(3072);
           KeyPair keyPair = keyPairGenerator.generateKeyPair();
           RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
           RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
           System.out.println("public key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
           System.out.println("private key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
           // 私钥加密、公钥解密--加密
           PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
           KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
           Cipher cipher = Cipher.getInstance("RSA");
           cipher.init(Cipher.ENCRYPT_MODE, privateKey);
           byte[] result = cipher.doFinal(str.getBytes());
           System.out.println("私钥加密、公钥解密--加密:" + Base64.encodeBase64String(result));

           // 私钥加密、公钥解密--解密
           X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
           keyFactory = KeyFactory.getInstance("RSA");
           PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
           cipher = Cipher.getInstance("RSA");
           cipher.init(Cipher.DECRYPT_MODE, publicKey);
           result = cipher.doFinal(result);
           System.out.println("私钥加密、公钥解密--解密:" + new String(result));

           // 公钥加密、私钥解密--加密
           x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
           keyFactory = KeyFactory.getInstance("RSA");
           publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
           cipher.init(Cipher.ENCRYPT_MODE, publicKey);
           result = cipher.doFinal(str.getBytes());
           System.out.println("公钥加密、私钥解密--加密:" + Base64.encodeBase64String(result));

           // 公钥加密、私钥解密--解密
           pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
           keyFactory = KeyFactory.getInstance("RSA");
           privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
           cipher.init(Cipher.DECRYPT_MODE, privateKey);
           result = cipher.doFinal(result);
           System.out.println("公钥加密、私钥解密--解密:" + new String(result));
      } catch (Exception e) {
      }
  }


image-20200730141244189

4.数字签名及实现

带有密钥(公钥、私钥)的消息摘要算法

用途:验证数据完整性,认证数据来源,抗否认

过程:1.对发送内容先生成有限长度的摘要(MD,SHA),再使用私钥进行加密,进而生成数字签名。

 2.用公钥对数字签名进行解密获取加密内容(其实也就是摘要),再用与发送方相同的摘要算法对发送内空 生成摘要。

常见算法:RSA、DSA、ECDSA

public static void signature() {
       try {
           // 初始化密钥
           KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
           keyPairGenerator.initialize(3072);
           KeyPair keyPair = keyPairGenerator.generateKeyPair();
           RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
           RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

           // 执行签名
           PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
           KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
           Signature signature = Signature.getInstance("MD5withRSA");
           signature.initSign(privateKey);
           signature.update(str.getBytes());
           byte[] result = signature.sign();
           System.out.println("rsa sign :" + Hex.encodeHexString(result));

           // 验证签名
           X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
           keyFactory = KeyFactory.getInstance("RSA");
           PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
           signature = Signature.getInstance("MD5withRSA");
           signature.initVerify(publicKey);
           signature.update(str.getBytes());
           boolean bool = signature.verify(result);
           System.out.println("rsa verify :" + bool);
      } catch (Exception e) {

      }
  }

image-20200730141312433


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。