教学服务系统

 找回密码
 立即注册
搜索
查看: 589|回复: 2

信息计算2019级1班26号陈宇扬

[复制链接]

8

主题

19

帖子

124

积分

注册会员

Rank: 2

积分
124
发表于 2022-6-2 16:09:55 | 显示全部楼层 |阅读模式
本帖最后由 1班27号陈宇扬 于 2022-6-2 16:15 编辑

RSA的加密解密和签名

RSA与传统加密方式不同的是,他是非对称加密,可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。
RSA加密方式是:
(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密。
但是公钥是可能给复数个其他系统的,你无法得知是哪个系统给你传输的这个数据,所以就有了签名这一说。举例的话就是现在有甲乙两个系统,甲系统要给乙系统传输数据,甲系统的数据使用自己的私钥对传递的信息进行加密,然后加一个签名字段放入要传输的数据中然后整体数据再使用公钥进行加密,传输给乙系统。乙系统拿到数据后,先使用自己的私钥解密数据,然后剔除签名字段,然后解密签名字段看与剔除签名字段的数据进行对比,这一步叫做验签,如果相等则代表此数据时由甲方传来且数据没有被篡改。
加密解密代码如下:
  1. /**
  2. * @ClassName: RSAUtil
  3. * @Description: RSA加密解密,加签解签工具类
  4. * @author 忙碌的菠萝
  5. * @date 2020年11月27日 下午1:19:55
  6. *
  7. */
  8. public class RSAUtil {

  9. /*
  10.          * 常见异常对照
  11.          * NoSuchAlgorithmException 无此算法,一般是环境问题,编译环境或者运行环境
  12.          * InvalidKeyException 秘钥非法,秘钥数据或者格式有问题,---begin--- 这种不需要
  13.          * IllegalBlockSizeException 明文长度非法,秘钥大小决定了可加密明文的长度,长度不符合会报出该异常
  14.          * BadPaddingException,NoSuchPaddingException 明文数据非法
  15.          * UnsupportedEncodingException 不支持的编码方式
  16.          * */

  17. /**
  18.          * @Fields RSA : RSA算法
  19.          */
  20.         public static final String RSA = "RSA";
  21.         /**
  22.          * @Fields SIGN_ALGORITHMS : 签名算法类型
  23.          */
  24.         public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

  25.         /**
  26.          * @Fields KEY_SIZE : 密钥长度 于原文长度对应 以及越长速度越慢
  27.          */
  28.         public static final int KEY_SIZE = 1024;

  29.         /**
  30.          * @Fields keyMap : 随机产生的公钥与私钥 0-公钥 1-私钥
  31.          */
  32.         public static Map<Integer, String> keyMap = new HashMap<Integer, String>();

  33.         /**
  34.          * @Title: genKeyPair
  35.          * @Description: Generator KeyPair
  36.          * @param getPrivate() 得到私钥 getPublic() 得到公钥
  37.          * @return KeyPair
  38.          * @throws NoSuchAlgorithmException 无此算法
  39.          */
  40.         public static KeyPair genKeyPair() throws NoSuchAlgorithmException {
  41.                 // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
  42.                 KeyPairGenerator keyPairGen = null;
  43.                 keyPairGen = KeyPairGenerator.getInstance(RSA);
  44.                 // 初始化密钥对生成器,密钥大小为96-1024位
  45.                 keyPairGen.initialize(KEY_SIZE, new SecureRandom());
  46.                 // 生成一个密钥对,保存在keyPair中
  47.                 KeyPair keyPair = keyPairGen.generateKeyPair();
  48.                 return keyPair;
  49.         }

  50.         /**
  51.          * @Title: GeneratorKey
  52.          * @Description: 随机生成密钥对
  53.          * @param
  54.          * @return Map<Integer, String> keyMap 秘钥对 0-公钥 1-私钥
  55.          * @throws Exception
  56.          */
  57.         public static void GeneratorKey() throws Exception {
  58.                 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
  59.                 keyPairGen.initialize(KEY_SIZE, new SecureRandom());
  60.                 KeyPair keyPair = keyPairGen.generateKeyPair();
  61.                 // 生成秘钥对
  62.                 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
  63.                 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
  64.                 // base64转码
  65.                 String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
  66.                 String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
  67.                 keyMap.put(0, publicKeyString); // 0表示公钥
  68.                 keyMap.put(1, privateKeyString); // 1表示私钥
  69.         }

  70. /**
  71.          * @Title: encrypt
  72.          * @Description: RSA公钥加密
  73.          * @param encryptData 待加密数据
  74.          * @param publicKey base64编码的公钥
  75.          * @return String 加密后的数据
  76.          * @throws
  77.          */
  78.         public static String encrypt(String encryptData, String publicKey) throws Exception {
  79.                 try {
  80.                         // base64编码的公钥,需要先decode
  81.                         byte[] decoded = Base64.decodeBase64(publicKey);
  82.                         RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(RSA)
  83.                                         .generatePublic(new X509EncodedKeySpec(decoded));
  84.                         // RSA加密
  85.                         Cipher cipher = Cipher.getInstance(RSA);
  86.                         cipher.init(Cipher.ENCRYPT_MODE, pubKey);
  87.                         String outStr = Base64.encodeBase64String(cipher.doFinal(encryptData.getBytes("UTF-8")));
  88.                         return outStr;
  89.                 } catch (NoSuchAlgorithmException e) {
  90.                         throw new NoSuchAlgorithmException("无此加密算法,请检查环境");
  91.                 } catch (NoSuchPaddingException e) {
  92.                         throw new NoSuchPaddingException("明文数据未找到");
  93.                 } catch (InvalidKeyException e) {
  94.                         throw new InvalidKeyException("加密秘钥非法,请检查");
  95.                 } catch (IllegalBlockSizeException e) {
  96.                         throw new IllegalBlockSizeException("明文长度非法");
  97.                 } catch (BadPaddingException e) {
  98.                         throw new BadPaddingException("明文数据已损坏");
  99.                 } catch (Exception e) {
  100.                         e.printStackTrace();
  101.                         throw new Exception("其他错误:", e);
  102.                 }
  103.         }

  104. /**
  105.         * @Title: decrypt
  106.         * @Description: RSA私钥解密
  107.         * @param privateKey base64编码的私钥
  108.         * @return String
  109.         * @throws Exception 解密过程中的异常信息
  110.         */
  111.         public static String decrypt(String decryptData, String privateKey) throws Exception {
  112.                 // 64位解码 加密后的字符串
  113.                 byte[] inputByte = Base64.decodeBase64(decryptData.getBytes("utf-8"));
  114.                 byte[] decoded = Base64.decodeBase64(privateKey);
  115.                 RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(RSA)
  116.                                 .generatePrivate(new PKCS8EncodedKeySpec(decoded));
  117.                 Cipher cipher = Cipher.getInstance(RSA);
  118.                 cipher.init(Cipher.DECRYPT_MODE, priKey);
  119.         
  120.                 String decryptStr = new String(cipher.doFinal(inputByte));
  121.                 return decryptStr;
  122.         }
复制代码




回复

使用道具 举报

8

主题

19

帖子

124

积分

注册会员

Rank: 2

积分
124
 楼主| 发表于 2022-6-2 16:14:11 | 显示全部楼层
RSA的签名和验签使用的是 java.security.Signature类,过程也是:获得秘钥 -> getInstance获得实例 -> initSign初始化 -> update数据 -> sign签名。代码如下:
  1. /**
  2.         * @Title: sign
  3.         * @Description: RSA签名
  4.         * @param signData 待签名数据
  5.         * @param privateKey 私钥字符串
  6.         * @return String 签名域
  7.         * @throws
  8.         */
  9.         public static String sign(String content, String privateKey) throws Exception {
  10.                 PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(BASE64.decode(privateKey));
  11.                 KeyFactory keyf = KeyFactory.getInstance(RSA);
  12.                 PrivateKey priKey = keyf.generatePrivate(priPKCS8);
  13.                 java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  14.                 signature.initSign(priKey);
  15.                 signature.update(content.getBytes());
  16.                 byte[] signed = signature.sign();
  17.                 return BASE64.encode(signed);
  18.         }

  19. /**
  20.         * @Title: verify
  21.         * @Description: RSA验签名检查
  22.         * @param content   待签名数据
  23.         * @param sign      签名域
  24.         * @param publicKey base64后的公钥字符串
  25.         * @return boolean 验签结果
  26.         * @throws
  27.         */
  28.         public static boolean verify(String content, String sign, String publicKey) throws Exception {
  29.                 KeyFactory keyFactory = KeyFactory.getInstance(RSA);
  30.                 byte[] encodedKey = BASE64.decode(publicKey);
  31.                 if (encodedKey == null) {
  32.                         return false;
  33.                 }
  34.                 PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
  35.                 // 用私钥对信息生成数字签名
  36.                 java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  37.                 signature.initVerify(pubKey);
  38.                 signature.update(content.getBytes());
  39.                 // 验证方法 返回true则为比对成功
  40.                 boolean bverify = signature.verify(BASE64.decode(sign));
  41.                 return bverify;
  42.         }
复制代码








回复

使用道具 举报

8

主题

19

帖子

124

积分

注册会员

Rank: 2

积分
124
 楼主| 发表于 2022-6-2 16:36:31 | 显示全部楼层
ECC椭圆曲线加密

ECC的英文全称是: Elliptic Curve Cryptography - 椭圆曲线密码学,是基于有限域的椭圆曲线和复杂的椭圆曲线离散对数.


ECC实现了非对称加密所需要的大部分能力,包括: 加密(encryption)、签名(signatures )、秘钥交换(key exchange).


ECC被认为是RSA密码系统的最好继承者,相对于RSA,ECC的keys更小,在于RSA相同等级下能够更快地生成Key.


ECC的加密原理为:(以下字母为举例说明,与代码无关)
描述一条Fp上的椭圆曲线,常用到六个参量:T=(p,a,b,n,x,y)。
(p 、a 、b) 用来确定一条椭圆曲线,p为素数域内点的个数,a和b是其内的两个大数;
x,y为G基点的坐标,也是两个大数;
n为点G基点的阶;
以上六个量就可以描述一条椭圆曲线,有时候我们还会用到h(椭圆曲线上所有点的个数p与n相除的整数部分)。
现在我们描述一个利用椭圆曲线进行加密通信的过程:
1、选定一条椭圆曲线 Ep(a,b) 并取椭圆曲线上一点,作为基点P。
2、选择一个大数k作为私钥,并生成公钥 Q=kP。
3、将 Ep(a,b) 和点Q、P传给用户。
4、用户接到信息后 ,将待传输的明文编码到Ep(a,b)上的一点M,并产生一个随机整数r。
5、公钥加密(密文C是一个点对):
C={rP, M+rQ}
6、私钥解密(M + rQ - k(rP) ,解密结果就是点M。

代码如下:
  1. #include <iostream>
  2. #define Ea 20
  3. #define Eb 4
  4. #define Ep 29
  5. using namespace std;
  6. int fast_pow(int a, int b, int c)
  7. {
  8.     int ans = 1;   ///记录结果
  9.     a = a % c;   ///预处理,使得a处于c的数据范围之下
  10.     while (b != 0)
  11.     {
  12.         if (b & 1)///奇数
  13.         {
  14.             ans = (ans * a) % c;///消除指数为奇数的影响
  15.         }
  16.         b >>= 1;    ///二进制的移位操作,不断的遍历b的二进制位
  17.         a = (a * a) % c;   ///不断的加倍
  18.     }
  19.     return ans;
  20. }
  21. struct point {
  22.     int x;
  23.     int y;
  24.     point():x(0),y(0){}
  25.     point(int a, int b):x(a),y(b) { }
  26.     bool operator==(const point& b) {
  27.         return this->x == b.x && this->y == b.y;
  28.     }
  29.     point operator+(const point& b) {
  30.         point result;
  31.         if (*this == b) {
  32.             long aaa = 3 * this->x * this->x + Ea;
  33.             long bbb = 2 * this->y;
  34.             //int m = (3 * this->x * this->x + Ea) / (2 * this->y) mod Ep;
  35.             long m;
  36.             if (aaa % bbb != 0) {
  37.                 m = ((aaa % Ep) * fast_pow(bbb, (Ep - 2), Ep)) % Ep;
  38.             }
  39.             else {
  40.                 m = (aaa / bbb) % Ep;
  41.             }
  42.             result.x = (m * m - 2 * this->x) % Ep;
  43.             result.y = (m * (this->x - result.x) - this->y) % Ep;  
  44.         }
  45.         else {
  46.             long aaa = b.y - this->y;
  47.             long bbb = b.x - this->x;
  48.             if (bbb == 0) {
  49.                 return point(13, 23);
  50.             }
  51.             long m;
  52.             if (aaa % bbb != 0) {
  53.                 m = ((aaa % Ep) * fast_pow(bbb, (Ep - 2), Ep)) % Ep;
  54.             }
  55.             else {
  56.                 m = (aaa / bbb) % Ep;
  57.             }
  58.             result.x = (m * m - this->x - b.x) % Ep;
  59.             result.y = (m * (this->x - result.x) - this->y) % Ep;
  60.         }
  61.         if (result.x < 0) {
  62.             result.x += Ep;
  63.         }
  64.         if (result.y < 0) {
  65.             result.y += Ep;
  66.         }
  67.         return result;
  68.     }
  69.     point operator-() {
  70.         this->y = Ep - this->y;
  71.         return *this;
  72.     }
  73. };
  74. void getG(point x,int& G) {
  75.     point Gx = x;
  76.     G = 1;
  77.     int num = 0;
  78.     do{
  79.         cout<<G<<"x:" << Gx.x << " " << Gx.y << endl;
  80.         Gx = Gx + x;
  81.         G++;
  82.     } while (Gx.x != x.x);
  83.     G++;
  84.     cout << G << "x:" << Gx.x << " " << Gx.y << endl;
  85. }
  86. point getNG(point x,int n) {
  87.     point result = x;
  88.     for (int i = 1; i < n; ++i) {
  89.         result = result + x;
  90.     }

  91.     return result;
  92. }
  93. void print(point p) {
  94.     cout << "[" << " " << p.x << "," << p.y << " " << "]" << endl;
  95. }
  96. int main()
  97. {
  98.     //Alice
  99.     //椭圆曲线 E29(20,4) 基点(13,23)
  100.     //第一步,计算椭圆曲线的阶数
  101.     int G;
  102.     point* x=new point(13, 23);
  103.     getG(*x, G);
  104.     cout << "阶数为:" << G << endl;
  105.     //求得G=36
  106.     //第二步,选择一个私有密钥p(p<G)
  107.     int p =25;
  108.     //第三步,公开密钥K=p*(13,23)
  109.     point K = getNG(*x, p);
  110.     //将 曲线 基点 密钥 公开
  111.     cout << "公开密钥:"<< endl;
  112.     print(K);
  113.     //Bob
  114.     //第四步,需要加密的信息msg,并将msg按照某种编码方式编码到曲线上一点M
  115.     int msg = 13;
  116.     cout << "需要加密的信息:" << msg << endl;;
  117.     point M(13,23);

  118.     //第五步,产生一个随机数r<G
  119.     //srand(unsigned(time(NULL)));
  120.     int r = 6;
  121.     //第六步,计算c1=M+r*K
  122.     //           c2=r*(13,23)
  123.     //(c1,c2)
  124.     point c1 = M;
  125.     for (int i = 0; i < r; ++i) {
  126.         c1 = c1 + K;
  127.     }
  128.     point c2=*x;
  129.     for (int i = 1; i < r; ++i) {
  130.         c2 = c2 + *x;
  131.     }
  132.     cout << "密文为:" << endl;;
  133.     print(c1);
  134.     print(c2);

  135.     //Alice解密
  136.     //第七步:计算c1-p*c2
  137.     point c3;
  138.     point c4=*x;
  139.     p = p*r % G;
  140.     for (int i = 1; i < p; ++i) {
  141.         c4 = c4 + *x;
  142.     }
  143.     c3 = c1 + (-c4);
  144.     cout << "明文为:" << c3.x << endl;
  145.     return 0;
  146. }
复制代码







回复

使用道具 举报

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

本版积分规则

教学服务系统

GMT+8, 2025-4-30 07:49 , Processed in 0.014300 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表