教学服务系统

 找回密码
 立即注册
搜索
查看: 958|回复: 5

信息计算2019级2班23号唐天玮

[复制链接]

9

主题

20

帖子

87

积分

注册会员

Rank: 2

积分
87
发表于 2022-5-30 22:00:51 | 显示全部楼层 |阅读模式
本帖最后由 唐天玮 于 2022-5-30 22:03 编辑

                                                         RSA加密及签名的实现

一、加解密过程简述
AB进行通信加密,B要先生成一对RSA密钥,B自己持有私钥,A公钥 —>A使用B的公钥加密要发送的内容,然后B接收到密文后通过自己的私钥解密内容
二、签名验签过程简述
AB发送消息,A先计算出消息的消息摘要,然后使用自己的私钥加密消息摘要,被加密的消息摘要就是签名.(A用自己的私钥给消息摘要加密成为签名)
B收到消息后,也会使用和A相同的方法提取消息摘要,然后用A公钥解密签名,并与自己计算出来的消息摘要进行比较–>如果相同则说明消息是A发送给B,同时,A也无法否认自己发送消息给B的事实.(B使用A的公钥解密签名文件的过程,叫做"验签")
三、签名和验签过程详细理解
签名过程:
(1). A计算消息m的消息摘要,记为 h(m)
(2). A使用私钥(n,d)h(m)加密,生成签名s, s满足:s=(h(m))^d mod n;
   由于A是用自己的私钥对消息摘要加密,所以只用使用s的公钥才能解密该消息摘要,这样A就不可否认自己发送了该消息给B
(3). A发送消息和签名(m,s)B
验签过程:
(1). B计算消息m的消息摘要(计算方式和A相同),记为h(m)
(2). B使用A的公钥(n,e)解密s,得到 H(m), H(m) = s^e mod n
(3). B比较H(m)h(m),相同才能证明验签成功

四、代码部分
  1. import java.io.ByteArrayInputStream;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.InputStream;
  4. import java.security.Key;
  5. import java.security.KeyFactory;
  6. import java.security.KeyPair;
  7. import java.security.KeyPairGenerator;
  8. import java.security.PrivateKey;
  9. import java.security.PublicKey;
  10. import java.security.interfaces.RSAPrivateKey;
  11. import java.security.interfaces.RSAPublicKey;
  12. import java.security.spec.PKCS8EncodedKeySpec;
  13. import java.security.spec.X509EncodedKeySpec;
  14. import java.util.Base64;
  15. import javax.crypto.Cipher;

  16. public class RSAUtil{
  17.         
  18.         public static final String  SIGN_ALGORITHMS = "SHA1WithRSA";
  19.         
  20.     /**加密算法RSA*/
  21.     public static final String KEY_ALGORITHM = "RSA";
  22.    
  23.         /**RSA最大加密明文大小*/
  24.     private static final int MAX_ENCRYPT_BLOCK = 117;
  25.    
  26.     /**RSA最大解密密文大小*/
  27.     private static final int MAX_DECRYPT_BLOCK = 128;
  28.         
  29.         /**
  30.         * RSA签名
  31.         * @param content 待签名数据
  32.         * @param privateKey 商户私钥
  33.         * @param input_charset 编码格式
  34.         */
  35.         public static String sign(String content, String privateKey, String input_charset){
  36.         try {
  37.                 PKCS8EncodedKeySpec priPKCS8         = new PKCS8EncodedKeySpec(Base64_.decode(privateKey) );
  38.                 KeyFactory keyf                                 = KeyFactory.getInstance(KEY_ALGORITHM);
  39.                 PrivateKey priKey                                 = keyf.generatePrivate(priPKCS8);
  40.             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  41.             signature.initSign(priKey);
  42.             signature.update(content.getBytes(input_charset));
  43.             byte[] signed = signature.sign();
  44.             return Base64_.encode(signed);
  45.         }catch (Exception e) {
  46.                 e.printStackTrace();
  47.         }
  48.         return null;
  49.     }
  50.         
  51.         /**
  52.         * RSA验签名检查
  53.         * @param content 待签名数据
  54.         * @param sign 签名值
  55.         * @param ali_public_key 支付宝公钥
  56.         * @param input_charset 编码格式
  57.         */
  58.         public static boolean verify(String content, String sign, String ali_public_key, String input_charset){
  59.                 try {
  60.                         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  61.                 byte[] encodedKey = Base64_.decode(ali_public_key);
  62.                 PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
  63.                         java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  64.                         signature.initVerify(pubKey);
  65.                         signature.update(content.getBytes(input_charset) );
  66.                         boolean bverify = signature.verify( Base64_.decode(sign) );
  67.                         return bverify;
  68.                 } catch (Exception e) {
  69.                         e.printStackTrace();
  70.                 }
  71.                 return false;
  72.         }
  73.         
  74.         /**
  75.         * 私钥解密
  76.         * @param content 密文
  77.         * @param private_key 商户私钥
  78.         * @param input_charset 编码格式
  79.         */
  80.         public static String decrypt(String content, String private_key, String input_charset) throws Exception {
  81.         PrivateKey prikey = getPrivateKey(private_key);
  82.         Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
  83.         cipher.init(Cipher.DECRYPT_MODE, prikey);
  84.         InputStream ins = new ByteArrayInputStream(Base64_.decode(content));
  85.         ByteArrayOutputStream writer = new ByteArrayOutputStream();
  86.         //rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
  87.         byte[] buf = new byte[128];
  88.         int bufl;
  89.         while ((bufl = ins.read(buf)) != -1) {
  90.             byte[] block = null;
  91.             if (buf.length == bufl) {
  92.                 block = buf;
  93.             } else {
  94.                 block = new byte[bufl];
  95.                 for (int i = 0; i < bufl; i++) {
  96.                     block[i] = buf[i];
  97.                 }
  98.             }
  99.             writer.write(cipher.doFinal(block));
  100.         }
  101.         return new String(writer.toByteArray(), input_charset);
  102.     }
  103.         
  104.         /**
  105.      * 公钥加密
  106.      * @param data 源数据
  107.      * @param publicKey 公钥(BASE64编码)
  108.      */
  109.    
复制代码
回复

使用道具 举报

9

主题

20

帖子

87

积分

注册会员

Rank: 2

积分
87
 楼主| 发表于 2022-5-30 22:04:20 | 显示全部楼层
本帖最后由 唐天玮 于 2022-5-30 22:05 编辑
  1. public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
  2.         byte[] keyBytes = Base64_.decode(publicKey);
  3.         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  4.         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  5.         Key publicK = keyFactory.generatePublic(x509KeySpec);
  6.         // 对数据加密
  7.         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  8.         cipher.init(Cipher.ENCRYPT_MODE, publicK);
  9.         int inputLen = data.length;
  10.         ByteArrayOutputStream out = new ByteArrayOutputStream();
  11.         int offSet = 0;
  12.         byte[] cache;
  13.         int i = 0;
  14.         // 对数据分段加密
  15.         while (inputLen - offSet > 0) {
  16.             if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  17.                 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  18.             } else {
  19.                 cache = cipher.doFinal(data, offSet, inputLen - offSet);
  20.             }
  21.             out.write(cache, 0, cache.length);
  22.             i++;
  23.             offSet = i * MAX_ENCRYPT_BLOCK;
  24.         }
  25.         byte[] encryptedData = out.toByteArray();
  26.         out.close();
  27.         return encryptedData;
  28.     }
  29.    
  30.     public static String encryptByPublicKeyToStr(byte[] data, String publicKey) throws Exception {
  31.             byte[] bytes = encryptByPublicKey(data, publicKey);
  32.             String result = Base64_.encode(bytes);
  33.             return result;
  34.     }
  35.         
  36.         /**
  37.         * 得到私钥
  38.         * @param key 密钥字符串(经过base64编码)
  39.         * @throws Exception
  40.         */
  41.         public static PrivateKey getPrivateKey(String key) throws Exception {
  42.                 byte[] keyBytes;
  43.                 keyBytes = Base64_.decode(key);
  44.                 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
  45.                 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  46.                 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
  47.                 return privateKey;
  48.         }
  49.         
  50.         public static class Base64_ {
  51.                 private static final Base64.Decoder decoder = Base64.getDecoder();
  52.                 private static final Base64.Encoder encoder = Base64.getEncoder();
  53.                 public static byte[] decode(String key) {
  54.                         if (key == null) { return null;}
  55.                         byte[] decode = decoder.decode(key);
  56.                         return decode;
  57.                 }
  58.                 public static String encode(byte[] content) {
  59.                         if (content == null) {return null;}
  60.                         String encode = encoder.encodeToString(content);
  61.                         return encode;
  62.                 }
  63.         }
  64.         
  65.         /**
  66.          * 测试
  67.          */
  68.         public static void main(String args[]) throws Exception{
  69.         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
  70.         keyPairGen.initialize(1024);
  71.         KeyPair keyPair = keyPairGen.generateKeyPair();
  72.         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  73.         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  74.         String pubKey = Base64_.encode(publicKey.getEncoded()); //公钥
  75.         String priKey = Base64_.encode(privateKey.getEncoded()); //私钥
  76. //        System.out.println(pubKey);
  77. //        System.out.println(priKey);
  78.         
  79. //....公钥加密,私钥解密!
  80.         
  81.         String sourceStr = "密码学";
  82.         //公钥加密
  83.         byte[] ens = RSAUtil.encryptByPublicKey(sourceStr.getBytes(),pubKey);
  84.         String encodes = Base64_.encode(ens);
  85.         System.out.println(encodes);
  86.         //私钥解密
  87.         String res2 = RSAUtil.decrypt(encodes, priKey, "UTF-8");
  88.         System.out.println(res2);
  89.         
  90. //....签名验证,私钥签名,公钥验证是否正确!
  91.         
  92.         String source = "id=shoig&name=shoer&age=23dnjlegj;reg"; //模拟请求参数,然后对此请求参数进行签名。
  93.         
  94.         String sign = RSAUtil.sign(source, priKey, "UTF-8");
  95.         
  96.         System.out.println("签名是:"+sign);
  97.         
  98.         // 公钥验证签名是否正确.
  99.         // 具体流程是,请求参数+sign发送给公钥方,然后公钥方过滤掉sign,用公钥验证其他参数是否通过。
  100.         
  101.         boolean result = RSAUtil.verify(source, sign, pubKey, "UTF-8");
  102.         
  103.         System.out.println(result);
  104.         
  105.         }
  106. }
复制代码
回复

使用道具 举报

9

主题

20

帖子

87

积分

注册会员

Rank: 2

积分
87
 楼主| 发表于 2022-5-30 22:15:19 | 显示全部楼层
本帖最后由 唐天玮 于 2022-5-30 22:23 编辑

                                                                                                       ECC椭圆曲线上公钥密码
一、定义
椭圆曲线加密(ECC,Elliptic Curves Cryptography)也属于非对称加密公钥算法,与主流的RSA算法相比,ECC算法可以使用较短的密钥达到相同的安全程度。ECC是建立在基于椭圆曲线的离散对数问题上的密码体制,给定椭圆曲线上的一个点G,并选取一个整数k,求解K=kG很容易(注意根据kG求解出来的K也是椭圆曲线上的一个点);反过来,在椭圆曲线上给定两个点K和G,若使K=kG,求整数k是一个难题。ECC就是建立在此数学难题之上,这一数学难题称为椭圆曲线离散对数问题。近年来,ECC逐步进入实际应用,如国家密码管理局颁布的SM2算法就是基于ECC算法的。

二、ECC安全性原理
K=kG,其中K,G为Ep(a,b)上的点,k为小于n的整数,n是点G的阶。
因此:K为公钥,k为私钥,G为基点。

三、源代码
  1. #include<iostream>
  2. #include<math.h>
  3. #include<time.h>
  4. using namespace std;

  5. class point
  6. {
  7. public:
  8.         int x;
  9.         int y;
  10. };
  11. point P[100];
  12. int num = 0;

  13. //取模
  14. int my_mod(int a, int p)
  15. {
  16.         int i;
  17.         i = a / p;
  18.         int re = a - i * p;
  19.         if (re >= 0)
  20.         {
  21.                 return re;
  22.         }
  23.         else
  24.         {
  25.                 return re + p;
  26.         }
  27. }

  28. int my_pow(int a, int m, int p)
  29. {
  30.         int result = 1;
  31.         for (int i = 0; i < m; i++)
  32.         {
  33.                 result = (result * a) % p;
  34.         }
  35.         return result;
  36. }

  37. int my_sqrt(int s)
  38. {
  39.         int t;
  40.         t = (int)sqrt(s);
  41.         if (t * t == s)
  42.         {
  43.                 return t;
  44.         }
  45.         else {
  46.                 return -1;
  47.         }
  48. }

  49. void all_points(int a, int b, int p)
  50. {
  51.         for (int i = 0; i < p; i++)
  52.         {
  53.                 int s = i * i * i + a * i + b;
  54.                 while (s < 0)
  55.                 {
  56.                         s += p;
  57.                 }
  58.                 s = my_mod(s, p);

  59.                 int re = my_pow(s, (p - 1) / 2, p);
  60.                 if (re == 1)
  61.                 {
  62.                         //求y
  63.                         int n = 1, y;
  64.                         int f = my_sqrt(s);
  65.                         if (f != -1)
  66.                         {
  67.                                 y = f;
  68.                         }
  69.                         else
  70.                         {
  71.                                 for (; n <= p - 1;)
  72.                                 {
  73.                                         s = s + n * p;
  74.                                         f = my_sqrt(s);
  75.                                         if (f != -1)
  76.                                         {
  77.                                                 y = f;
  78.                                                 break;
  79.                                         }
  80.                                         n++;
  81.                                 }
  82.                         }
复制代码


回复

使用道具 举报

9

主题

20

帖子

87

积分

注册会员

Rank: 2

积分
87
 楼主| 发表于 2022-5-30 22:24:35 | 显示全部楼层
  1.                         y = my_mod(y, p);
  2.                         P[num].x = i;
  3.                         P[num].y = y;
  4.                         num++;
  5.                         if (y != 0)
  6.                         {
  7.                                 P[num].x = i;
  8.                                 P[num].y = (p - y) % p;
  9.                                 num++;
  10.                         }
  11.                 }
  12.         }
  13. }

  14. void show()
  15. {
  16.         for (int i = 0; i < num; i++)
  17.         {
  18.                 cout << P[i].x << " " << P[i].y << endl;
  19.         }
  20. }


  21. int extend(int a, int b, int& x, int& y)
  22. {
  23.         if (b == 0)
  24.         {
  25.                 x = 1;
  26.                 y = 0;
  27.                 return a;
  28.         }
  29.         int r = extend(b, a % b, x, y);
  30.         int t = x;
  31.         x = y;
  32.         y = t - a / b * y;
  33.         return r;
  34. }

  35. //递归扩展欧几里得求逆
  36. int inv(int a, int b)
  37. {
  38.         int x, y;
  39.         int r = extend(a, b, x, y);
  40.         if (r != 1)
  41.         {
  42.                 return 0;
  43.         }
  44.         x = x % b;
  45.         if (x < 0)
  46.         {
  47.                 x = x + b;
  48.         }
  49.         return x;
  50. }


  51. //加法运算
  52. point add(point p1, point p2, int a, int p)
  53. {
  54.         long t; int flag = 0;
  55.         int x1 = p1.x; int y1 = p1.y;
  56.         int x2 = p2.x; int y2 = p2.y;
  57.         int tx, ty; int x3, y3;

  58.         if ((x2 == x1) && (y2 == y1))
  59.         {
  60.                 //相同点
  61.                 if (y1 == 0)
  62.                 {
  63.                         flag = 1;
  64.                 }
  65.                 else
  66.                 {
  67.                         t = (3 * x1 * x1 + a) * inv(2 * y1, p) % p;
  68.                 }
  69.         }
  70.         else
  71.         {
  72.                 //不同点
  73.                 ty = y2 - y1;
  74.                 tx = x2 - x1;
  75.                 while (tx < 0)
  76.                 {
  77.                         tx = tx + p;
  78.                 }
  79.                 while (ty < 0)
  80.                 {
  81.                         ty = ty + p;
  82.                 }

  83.                 if (tx == 0 && ty != 0)
  84.                 {
  85.                         flag = 1;
  86.                 }
  87.                 else
  88.                 {
  89.                         //点不相等
  90.                         t = ty * inv(tx, p) % p;
  91.                 }
  92.         }

  93.         if (flag == 1)
  94.         {
  95.                 //无限点
  96.                 p2.x = -1;
  97.                 p2.y = -1;
  98.         }
  99.         else
  100.         {
  101.                 x3 = (t * t - x1 - x2) % p;
  102.                 y3 = (t * (x1 - x3) - y1) % p;
  103.                 while (x3 < 0)
  104.                 {
  105.                         x3 += p;
  106.                 }
  107.                 while (y3 < 0)
  108.                 {
  109.                         y3 += p;
  110.                 }
  111.                 p2.x = x3;
  112.                 p2.y = y3;
  113.         }
  114.         return p2;
  115. }

  116. //随机选取一个生成元并计算阶
  117. int jie(point& pp, int a, int p)
  118. {
  119.         int ii = rand() % num;
  120.         point P0 = P[ii];
  121.         point p1, p2;
  122.         int number = 1;
复制代码
回复

使用道具 举报

9

主题

20

帖子

87

积分

注册会员

Rank: 2

积分
87
 楼主| 发表于 2022-5-30 22:24:57 | 显示全部楼层
  1.         p1.x = P0.x; p2.x = P0.x;
  2.         p1.y = P0.y; p2.y = P0.y;
  3.         while (true)
  4.         {
  5.                 p2 = add(p1, p2, a, p);
  6.                 if (p2.x == -1 && p2.y == -1)
  7.                 {
  8.                         break;
  9.                 }
  10.                 number++;
  11.                 if (p2.x == p1.x)
  12.                 {
  13.                         break;
  14.                 }
  15.         }
  16.         pp.x = p1.x;
  17.         pp.y = p1.y;
  18.         int n = ++number;
  19.         return n;
  20. }

  21. //素数判断
  22. bool judge(int num)
  23. {
  24.         bool ret = true;
  25.         int ubound = sqrt(num) + 1;
  26.         for (int i = 2; i < ubound; i++)
  27.         {
  28.                 if (num % i == 0)
  29.                 {
  30.                         ret = false;
  31.                         break;
  32.                 }
  33.         }
  34.         return ret;
  35. }

  36. //计算kG
  37. point cal(point G, int k, int a, int p)
  38. {
  39.         point temp = G;
  40.         for (int i = 0; i < k - 1; i++)
  41.         {
  42.                 temp = add(temp, G, a, p);
  43.         }
  44.         return temp;
  45. }

  46. int main()
  47. {
  48.         srand(time(NULL));
  49.         int a, b, p;
  50.         point generator; int n;
  51.         char SE[10];
  52.         char CR[10];

  53.         cout << "请输入椭圆曲线群(a,b,p):";
  54.         cin >> a >> b >> p;
  55.         cout << "请输入明文:";
  56.         cin >> SE;
  57.         cout << "请输入密钥:";
  58.         cin >> CR;

  59.         //计算所有点
  60.         all_points(a, b, p);
  61.         //选取生成元,直到阶为素数
  62.         do
  63.         {
  64.                 n = jie(generator, a, p);
  65.         } while (judge(n) == false);
  66.         cout << endl << "选取生成元(" << generator.x << "," << generator.y << "),阶为:" << n << endl;
  67.         //选取私钥
  68.         int ka = int(CR[0]) % (n - 1) + 1;//选取使用的密钥
  69.         point pa = cal(generator, ka, a, p);//计算公钥
  70.         cout << "私钥:" << ka << endl;
  71.         cout << "公钥:(" << pa.x << "," << pa.y << ")" << endl;

  72.         //加密
  73.         int k = 0;//随机数k
  74.         k = rand() % (n - 2) + 1;
  75.         point C1 = cal(generator, k, a, p);//计算C1

  76.         //m嵌入到椭圆曲线
  77.         int t = rand() % num; //选择映射点
  78.         point Pt = P[t];
  79.         point P2 = cal(pa, k, a, p);
  80.         point Pm = add(Pt, P2, a, p);
  81.         cout << endl << "要发送的密文:" << endl;
  82.         cout << "kG=(" << C1.x << "," << C1.y << "),pt+kPa=(" << Pm.x << "," << Pm.y << ")";
  83.         int C[100];
  84.         cout << ",C = { ";
  85.         for (int i = 0; i < strlen(SE); i++)
  86.         {
  87.                 C[i] = int(SE[i]) * Pt.x + Pt.y;//选取要加密的明文
  88.                 cout << C[i] << " ";
  89.         }
  90.         cout << "}" << endl;


  91.         //解密
  92.         point temp, temp1;
  93.         int m;
  94.         temp = cal(C1, ka, a, p);
  95.         temp.y = 0 - temp.y;
  96.         temp1 = add(Pm, temp, a, p);//求解Pt
  97.         printf("\n解密结果:\n");
  98.         for (int i = 0; i < strlen(SE); i++)
  99.         {
  100.                 m = (C[i] - temp1.y) / temp1.x;
  101.                 printf("%c", char(m));//输出密文
  102.         }
  103.         printf("\n");

  104.         return 0;
  105. }
复制代码
回复

使用道具 举报

9

主题

20

帖子

87

积分

注册会员

Rank: 2

积分
87
 楼主| 发表于 2022-5-30 22:26:12 | 显示全部楼层

如图所示:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

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

本版积分规则

教学服务系统

GMT+8, 2025-4-30 07:56 , Processed in 0.016051 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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