教学服务系统

 找回密码
 立即注册
搜索
查看: 659|回复: 1

信息计算2019级1班29号敖若瑶

[复制链接]

8

主题

18

帖子

124

积分

注册会员

Rank: 2

积分
124
发表于 2022-5-28 16:21:04 | 显示全部楼层 |阅读模式

RSA的加密和签名

一、原理

RSA加密:A和B进行通信加密,B要先生成一对RSA密钥,B自己持有私钥,给A公钥 ->A使用B的公钥加密要发送的内容,然后B接收到密文后通过自己的私钥解密内容。

RSA签名:A给B发送消息,A先计算出消息的消息摘要,然后使用自己的私钥加密消息摘要,被加密的消息摘要就是签名(A用自己的私钥给消息摘要加密成为签名)。

二、环境

java

三、源代码
  1. import java.io.ByteArrayOutputStream;
  2. import java.security.KeyFactory;
  3. import java.security.KeyPair;
  4. import java.security.KeyPairGenerator;
  5. import java.security.PrivateKey;
  6. import java.security.PublicKey;
  7. import java.security.Signature;
  8. import java.security.spec.PKCS8EncodedKeySpec;
  9. import java.security.spec.X509EncodedKeySpec;
  10. import javax.crypto.Cipher;
  11. import org.apache.commons.codec.binary.Base64;

  12. public class Test {

  13.     /**
  14.      * RSA最大加密明文大小
  15.      */
  16.     private static final int MAX_ENCRYPT_BLOCK = 117;

  17.     /**
  18.      * RSA最大解密密文大小
  19.      */
  20.     private static final int MAX_DECRYPT_BLOCK = 128;

  21.     /**
  22.      * 获取密钥对
  23.      *
  24.      * @return 密钥对
  25.      */
  26.     public static KeyPair getKeyPair() throws Exception {
  27.         KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
  28.         generator.initialize(1024);
  29.         return generator.generateKeyPair();
  30.     }

  31.     /**
  32.      * 获取私钥
  33.      *
  34.      * @param privateKey 私钥字符串
  35.      * @return
  36.      */
  37.     public static PrivateKey getPrivateKey(String privateKey) throws Exception {
  38.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  39.         byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
  40.         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
  41.         return keyFactory.generatePrivate(keySpec);
  42.     }

  43.     /**
  44.      * 获取公钥
  45.      *
  46.      * @param publicKey 公钥字符串
  47.      * @return
  48.      */
  49.     public static PublicKey getPublicKey(String publicKey) throws Exception {
  50.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  51.         byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
  52.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
  53.         return keyFactory.generatePublic(keySpec);
  54.     }

  55.     /**
  56.      * RSA加密
  57.      *
  58.      * @param data 待加密数据
  59.      * @param publicKey 公钥
  60.      * @return
  61.      */
  62.     public static String encrypt(String data, PublicKey publicKey) throws Exception {
  63.         Cipher cipher = Cipher.getInstance("RSA");
  64.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  65.         int inputLen = data.getBytes().length;
  66.         ByteArrayOutputStream out = new ByteArrayOutputStream();
  67.         int offset = 0;
  68.         byte[] cache;
  69.         int i = 0;
  70.         // 对数据分段加密
  71.         while (inputLen - offset > 0) {
  72.             if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
  73.                 cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
  74.             } else {
  75.                 cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
  76.             }
  77.             out.write(cache, 0, cache.length);
  78.             i++;
  79.             offset = i * MAX_ENCRYPT_BLOCK;
  80.         }
  81.         byte[] encryptedData = out.toByteArray();
  82.         out.close();
  83.         // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
  84.         // 加密后的字符串
  85.         return new String(Base64.encodeBase64String(encryptedData));
  86.     }

  87.     /**
  88.      * RSA解密
  89.      *
  90.      * @param data 待解密数据
  91.      * @param privateKey 私钥
  92.      * @return
  93.      */
  94.     public static String decrypt(String data, PrivateKey privateKey) throws Exception {
  95.         Cipher cipher = Cipher.getInstance("RSA");
  96.         cipher.init(Cipher.DECRYPT_MODE, privateKey);
  97.         byte[] dataBytes = Base64.decodeBase64(data);
  98.         int inputLen = dataBytes.length;
  99.         ByteArrayOutputStream out = new ByteArrayOutputStream();
  100.         int offset = 0;
  101.         byte[] cache;
  102.         int i = 0;
  103.         // 对数据分段解密
  104.         while (inputLen - offset > 0) {
  105.             if (inputLen - offset > MAX_DECRYPT_BLOCK) {
  106.                 cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
  107.             } else {
  108.                 cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
  109.             }
  110.             out.write(cache, 0, cache.length);
  111.             i++;
  112.             offset = i * MAX_DECRYPT_BLOCK;
  113.         }
  114.         byte[] decryptedData = out.toByteArray();
  115.         out.close();
  116.         // 解密后的内容
  117.         return new String(decryptedData, "UTF-8");
  118.     }

  119.     /**
  120.      * 签名
  121.      *
  122.      * @param data 待签名数据
  123.      * @param privateKey 私钥
  124.      * @return 签名
  125.      */
  126.     public static String sign(String data, PrivateKey privateKey) throws Exception {
  127.         byte[] keyBytes = privateKey.getEncoded();
  128.         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
  129.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  130.         PrivateKey key = keyFactory.generatePrivate(keySpec);
  131.         Signature signature = Signature.getInstance("MD5withRSA");
  132.         signature.initSign(key);
  133.         signature.update(data.getBytes());
  134.         return new String(Base64.encodeBase64(signature.sign()));
  135.     }

  136.     /**
  137.      * 验签
  138.      *
  139.      * @param srcData 原始字符串
  140.      * @param publicKey 公钥
  141.      * @param sign 签名
  142.      * @return 是否验签通过
  143.      */
  144.     public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
  145.         byte[] keyBytes = publicKey.getEncoded();
  146.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  147.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  148.         PublicKey key = keyFactory.generatePublic(keySpec);
  149.         Signature signature = Signature.getInstance("MD5withRSA");
  150.         signature.initVerify(key);
  151.         signature.update(srcData.getBytes());
  152.         return signature.verify(Base64.decodeBase64(sign.getBytes()));
  153.     }

  154.     public static void main(String[] args) {
  155.         try {
  156.             // 生成密钥对
  157.             KeyPair keyPair = getKeyPair();
  158.             String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
  159.             String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
  160.             System.out.println("私钥:" + privateKey);
  161.             System.out.println("公钥:" + publicKey);
  162.             // RSA加密
  163.             String data = "待加密的文字内容";
  164.             String encryptData = encrypt(data, getPublicKey(publicKey));
  165.             System.out.println("加密后内容:" + encryptData);
  166.             // RSA解密
  167.             String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
  168.             System.out.println("解密后内容:" + decryptData);

  169.             // RSA签名
  170.             String sign = sign(data, getPrivateKey(privateKey));
  171.             // RSA验签
  172.             boolean result = verify(data, getPublicKey(publicKey), sign);
  173.             System.out.print("验签结果:" + result);
  174.         } catch (Exception e) {
  175.             e.printStackTrace();
  176.             System.out.print("加解密异常");
  177.         }
  178.     }
  179. }
复制代码

回复

使用道具 举报

8

主题

18

帖子

124

积分

注册会员

Rank: 2

积分
124
 楼主| 发表于 2022-5-28 19:00:14 | 显示全部楼层

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),公式:M + rQ - k(rP) = M + r(kP) - k(rP) = M
      7、对点M进行解码就可以得到明文
      假设在加密过程中,有一个第三者H,H只能知道椭圆曲线 Ep(a,b)、公钥Q、基点P、密文点C,而通过公钥Q、基点P求私钥k或者通过密文点C、基点P求随机数r都是非常困难的,因此得以保证数据传输的安全。
二、环境
     C
三、源代码
  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <openssl/ec.h>
  4. #include <openssl/ecdsa.h>
  5. #include <openssl/objects.h>
  6. #include <openssl/err.h>

  7. int    main()
  8. {
  9.       EC_KEY                *key1,*key2;
  10.       EC_POINT            *pubkey1,*pubkey2;
  11.       EC_GROUP           *group1,*group2;
  12.       int                         ret,nid,size,i,sig_len;
  13.       unsigned char*signature,digest[20];
  14.       BIO                      *berr;
  15.       EC_builtin_curve    *curves;
  16.       int                                crv_len;
  17.       char               shareKey1[128],shareKey2[128];
  18.       int                         len1,len2;

  19.       /* 构造EC_KEY数据结构 */
  20.       key1=EC_KEY_new();
  21.       if(key1==NULL)
  22.       {
  23.              printf("EC_KEY_new err!\n");
  24.              return -1;
  25.       }
  26.       key2=EC_KEY_new();
  27.       if(key2==NULL)
  28.       {
  29.              printf("EC_KEY_new err!\n");
  30.              return -1;
  31.       }
  32.       /* 获取实现的椭圆曲线个数 */
  33.       crv_len = EC_get_builtin_curves(NULL, 0);
  34.       curves = (EC_builtin_curve *)malloc(sizeof(EC_builtin_curve) * crv_len);
  35.       /* 获取椭圆曲线列表 */
  36.       EC_get_builtin_curves(curves, crv_len);
  37.       /*
  38.       nid=curves[0].nid;会有错误,原因是密钥太短
  39.       */
  40.       /* 选取一种椭圆曲线 */
  41.       nid=curves[25].nid;
  42.       /* 根据选择的椭圆曲线生成密钥参数group */
  43.       group1=EC_GROUP_new_by_curve_name(nid);
  44.       if(group1==NULL)
  45.       {
  46.              printf("EC_GROUP_new_by_curve_name err!\n");
  47.              return -1;
  48.       }
  49.       group2=EC_GROUP_new_by_curve_name(nid);
  50.       if(group1==NULL)
  51.       {
  52.              printf("EC_GROUP_new_by_curve_name err!\n");
  53.              return -1;
  54.       }
  55.       /* 设置密钥参数 */
  56.       ret=EC_KEY_set_group(key1,group1);
  57.       if(ret!=1)
  58.       {
  59.              printf("EC_KEY_set_group err.\n");
  60.              return -1;
  61.       }
  62.       ret=EC_KEY_set_group(key2,group2);
  63.       if(ret!=1)
  64.       {
  65.              printf("EC_KEY_set_group err.\n");
  66.              return -1;
  67.       }
  68.       /* 生成密钥 */
  69.       ret=EC_KEY_generate_key(key1);
  70.       if(ret!=1)
  71.       {
  72.              printf("EC_KEY_generate_key err.\n");
  73.              return -1;
  74.       }
  75.       ret=EC_KEY_generate_key(key2);
  76.       if(ret!=1)
  77.       {
  78.              printf("EC_KEY_generate_key err.\n");
  79.              return -1;
  80.       }
  81.       /* 检查密钥 */
  82.       ret=EC_KEY_check_key(key1);
  83.       if(ret!=1)
  84.       {
  85.              printf("check key err.\n");
  86.              return -1;
  87.       }
  88.       /* 获取密钥大小 */
  89.       size=ECDSA_size(key1);
  90.       printf("size %d \n",size);
  91.       for(i=0;i<20;i++)
  92.              memset(&digest[i],i+1,1);
  93.       signature=malloc(size);
  94.       ERR_load_crypto_strings();
  95.       berr=BIO_new(BIO_s_file());
  96.       BIO_set_fp(berr,stdout,BIO_NOCLOSE);
  97.       /* 签名数据,本例未做摘要,可将digest中的数据看作是sha1摘要结果 */
  98.       ret=ECDSA_sign(0,digest,20,signature,&sig_len,key1);
  99.       if(ret!=1)
  100.       {
  101.              ERR_print_errors(berr);
  102.              printf("sign err!\n");
  103.              return -1;
  104.       }
  105.       /* 验证签名 */
  106.       ret=ECDSA_verify(0,digest,20,signature,sig_len,key1);
  107.       if(ret!=1)
  108.       {
  109.              ERR_print_errors(berr);
  110.              printf("ECDSA_verify err!\n");
  111.              return -1;
  112.       }
  113.       /* 获取对方公钥,不能直接引用 */
  114.       pubkey2 = EC_KEY_get0_public_key(key2);
  115.       /* 生成一方的共享密钥 */
  116.       len1=ECDH_compute_key(shareKey1, 128, pubkey2, key1, NULL);
  117.       pubkey1 = EC_KEY_get0_public_key(key1);
  118.       /* 生成另一方共享密钥 */
  119.       len2=ECDH_compute_key(shareKey2, 128, pubkey1, key2, NULL);
  120.       if(len1!=len2)
  121.       {
  122.              printf("err\n");
  123.       }
  124.       else
  125.       {
  126.              ret=memcmp(shareKey1,shareKey2,len1);
  127.              if(ret==0)
  128.                     printf("生成共享密钥成功\n");
  129.              else
  130.                     printf("生成共享密钥失败\n");
  131.       }
  132.       printf("test ok!\n");
  133.       BIO_free(berr);
  134.       EC_KEY_free(key1);
  135.       EC_KEY_free(key2);
  136.       free(signature);
  137.       free(curves);
  138.       return 0;
  139. }
复制代码


回复

使用道具 举报

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

本版积分规则

教学服务系统

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

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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