教学服务系统

 找回密码
 立即注册
搜索
查看: 580|回复: 4

信息计算2019级2班11号谢春晖

[复制链接]

9

主题

22

帖子

111

积分

注册会员

Rank: 2

积分
111
发表于 2022-6-1 17:41:19 | 显示全部楼层 |阅读模式
本帖最后由 谢春晖 于 2022-6-1 17:46 编辑

RSA加密、解密和签名算法

一、RSA加密、解密和签名算法简介
RSA加密是一种非对称加密。可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。它是由一对密钥来进行加解密的过程,分别称为公钥和私钥。两者之间有数学相关,该加密算法的原理就是对一极大整数做因数分解的困难性来保证安全性。通常个人保存私钥,公钥是公开的(可能同时多人持有)。
二、加密和签名的流程
RSA虽然是非对称加密,但是有独特的对称性:公钥加密、私钥解密 私钥加密、公钥解密
加密:接受方公钥加密、接受方私钥解密签名:发送方私钥加签、发送方公钥解签,加密和签名一起使用才能防止泄露和篡改,具体流程如下:
1、A给B发送信息STR
2、A先用SHA256对信息STR计算,得到摘要Z
3、A用A的私钥对Z进行加密,得到签名S(只有发送者的私钥才能代表发送者,只能使用发送方的私钥加密才能达到不可抵赖性)
4、A用B的公钥对信息STR和签名S加密,得到传输数据M
传输M
1、B用B的私钥对M解密,得到信息STR和签名S
2、B用SHA256对信息STR计算,得到摘要Z1
3、B用A的公钥对签名S解密,得到摘要Z(A的公钥可以解签S,证明签名也是A亲自加密的)
4、对比Z和Z1,相等证明信息没有被篡改
三、程序代码
RSAEncrypt.java
  1. package com.ihep;

  2. import java.security.KeyFactory;
  3. import java.security.PrivateKey;
  4. import java.security.PublicKey;
  5. import java.security.spec.PKCS8EncodedKeySpec;
  6. import java.security.spec.X509EncodedKeySpec;

  7. /**
  8. * RSA签名验签类
  9. */
  10. public class RSASignature {

  11.     /**
  12.      * 签名算法
  13.      */
  14.     public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

  15.     /**
  16.      * RSA签名
  17.      *
  18.      * @param content    待签名数据
  19.      * @param privateKey 商户私钥
  20.      * @param encode     字符集编码
  21.      * @return 签名值
  22.      */
  23.     public static String sign(String content, String privateKey, String encode) {
  24.         try {
  25.             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));

  26.             KeyFactory keyf = KeyFactory.getInstance("RSA");
  27.             PrivateKey priKey = keyf.generatePrivate(priPKCS8);

  28.             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

  29.             signature.initSign(priKey);
  30.             signature.update(content.getBytes(encode));

  31.             byte[] signed = signature.sign();

  32.             return Base64.encode(signed);
  33.         } catch (Exception e) {
  34.             e.printStackTrace();
  35.         }

  36.         return null;
  37.     }

  38.     /**
  39.      * 功能描述:私钥签名
  40.      *
  41.      * @param content    明文数据,以字符串形式存在
  42.      * @param privateKey 字符串私钥
  43.      * @return String 签名后的结果
  44.      * @author cakin
  45.      * @date 2020/11/12
  46.      */
  47.     public static String sign(String content, String privateKey) {
  48.         try {
  49.             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
  50.             KeyFactory keyf = KeyFactory.getInstance("RSA");
  51.             PrivateKey priKey = keyf.generatePrivate(priPKCS8);
  52.             // 这里签名使用的是 SHA1WithRSA
  53.             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  54.             // 以私钥字符串初始化签名
  55.             signature.initSign(priKey);
  56.             // 将原始串注入签名中
  57.             signature.update(content.getBytes());
  58.             // 签名后的结果,以字符数组形式存在
  59.             byte[] signed = signature.sign();
  60.             // 签名后的结果,以base64编码形式存在
  61.             return Base64.encode(signed);
  62.         } catch (Exception e) {
  63.             e.printStackTrace();
  64.         }
  65.         return null;
  66.     }

  67.     /**
  68.      * RSA验签名检查
  69.      *
  70.      * @param content   待签名数据
  71.      * @param sign      签名值
  72.      * @param publicKey 分配给开发商公钥
  73.      * @param encode    字符集编码
  74.      * @return 布尔值
  75.      */
  76.     public static boolean doCheck(String content, String sign, String publicKey, String encode) {
  77.         try {
  78.             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  79.             byte[] encodedKey = Base64.decode(publicKey);
  80.             PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));


  81.             java.security.Signature signature = java.security.Signature
  82.                     .getInstance(SIGN_ALGORITHMS);

  83.             signature.initVerify(pubKey);
  84.             signature.update(content.getBytes(encode));

  85.             boolean bverify = signature.verify(Base64.decode(sign));
  86.             return bverify;

  87.         } catch (Exception e) {
  88.             e.printStackTrace();
  89.         }

  90.         return false;
  91.     }

  92.     /**
  93.      * 功能描述:公钥校验签名
  94.      *
  95.      * @param content   签名原串
  96.      * @param sign      签名串
  97.      * @param publicKey 公钥字符串
  98.      * @return boolean 校验是否成功
  99.      * @author cakin
  100.      * @date 2020/11/12
  101.      * @description:
  102.      */
  103.     public static boolean doCheck(String content, String sign, String publicKey) {
  104.         try {
  105.             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  106.             byte[] encodedKey = Base64.decode(publicKey);
  107.             PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
  108.             // 使用 SHA1WithRSA 签名算法
  109.             java.security.Signature signature = java.security.Signature
  110.                     .getInstance(SIGN_ALGORITHMS);
  111.             // 用公钥初始化签名校验
  112.             signature.initVerify(pubKey);
  113.             // 原始串注入签名校验中
  114.             signature.update(content.getBytes());
  115.             // 验证签名结果
  116.             boolean bverify = signature.verify(Base64.decode(sign));
  117.             // 返回签名是否成功
  118.             return bverify;
  119.         } catch (Exception e) {
  120.             e.printStackTrace();
  121.         }
  122.         return false;
  123.     }
  124. }
复制代码

四、运行结果截图

本帖子中包含更多资源

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

x
回复

使用道具 举报

9

主题

22

帖子

111

积分

注册会员

Rank: 2

积分
111
 楼主| 发表于 2022-6-1 18:15:35 | 显示全部楼层
RSA加密、解密和签名算法后续代码
RSAEncrypt.java
  1. package com.ihep;
  2. import javax.crypto.BadPaddingException;
  3. import javax.crypto.Cipher;
  4. import javax.crypto.IllegalBlockSizeException;
  5. import javax.crypto.NoSuchPaddingException;
  6. import java.io.*;
  7. import java.security.*;
  8. import java.security.interfaces.RSAPrivateKey;
  9. import java.security.interfaces.RSAPublicKey;
  10. import java.security.spec.InvalidKeySpecException;
  11. import java.security.spec.PKCS8EncodedKeySpec;
  12. import java.security.spec.X509EncodedKeySpec;
  13. public class RSAEncrypt {private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6','7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  14. public static void genKeyPair(String filePath) {// 密钥对生成器KeyPairGenerator keyPairGen = null;
  15. try {// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
  16. keyPairGen = KeyPairGenerator.getInstance("RSA");} catch (NoSuchAlgorithmException e) {
  17. // TODO Auto-generated catch block
  18. e.printStackTrace();}
  19. // 初始化密钥对生成器,密钥大小为96-1024位
  20. keyPairGen.initialize(1024, new SecureRandom());
  21. // 生成一个密钥对,保存在keyPair中
  22. KeyPair keyPair = keyPairGen.generateKeyPair();
  23. // 得到私钥
  24. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  25. // 得到公钥
  26. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  27. try {// 得到公钥字符串
  28. String publicKeyString = Base64.encode(publicKey.getEncoded());
  29.             // 得到私钥字符串
  30.             String privateKeyString = Base64.encode(privateKey.getEncoded());
  31.             // 将密钥对写入到文件
  32.             FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");
  33.             FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");
  34.             BufferedWriter pubbw = new BufferedWriter(pubfw);
  35.             BufferedWriter pribw = new BufferedWriter(prifw);
  36.             pubbw.write(publicKeyString);
  37.             pribw.write(privateKeyString);
  38.             pubbw.flush();
  39.             pubbw.close();
  40.             pubfw.close();
  41.             pribw.flush();
  42.             pribw.close();
  43.             prifw.close();} catch (Exception e) {e.printStackTrace();}}
  44.     public static String loadPublicKeyByFile(String path) throws Exception {try {
  45.             BufferedReader br = new BufferedReader(new FileReader(path + "/publicKey.keystore"));
  46.             String readLine = null;
  47.             StringBuilder sb = new StringBuilder();
  48.             while ((readLine = br.readLine()) != null) {sb.append(readLine);}br.close();
  49.             return sb.toString();} catch (IOException e) {throw new Exception("公钥数据流读取错误");
  50.         } catch (NullPointerException e) {throw new Exception("公钥输入流为空");}}
  51.     public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
  52.             throws Exception {try {byte[] buffer = Base64.decode(publicKeyStr);
  53.             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  54.             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
  55.             return (RSAPublicKey) keyFactory.generatePublic(keySpec);
  56.         } catch (NoSuchAlgorithmException e) {throw new Exception("无此算法");
  57.         } catch (InvalidKeySpecException e) {throw new Exception("公钥非法");
  58.         } catch (NullPointerException e) {throw new Exception("公钥数据为空");}}
  59.     public static String loadPrivateKeyByFile(String path) throws Exception {
  60.         try {BufferedReader br = new BufferedReader(new FileReader(path+ "/privateKey.keystore"));
  61.             String readLine = null;
  62.             StringBuilder sb = new StringBuilder();
  63.             while ((readLine = br.readLine()) != null) {
  64.                 sb.append(readLine);
  65.             }
  66.             br.close();
  67.             return sb.toString();
  68.         } catch (IOException e) {
  69.             throw new Exception("私钥数据读取错误");
  70.         } catch (NullPointerException e) {
  71.             throw new Exception("私钥输入流为空");
  72.         }
  73.     }
  74.     public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
  75.             throws Exception {
  76.         try {
  77.             byte[] buffer = Base64.decode(privateKeyStr);
  78.             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
  79.             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  80.             return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
  81.         } catch (NoSuchAlgorithmException e) {
  82.             throw new Exception("无此算法");
  83.         } catch (InvalidKeySpecException e) {
  84.             throw new Exception("私钥非法");
  85.         } catch (NullPointerException e) {
  86.             throw new Exception("私钥数据为空");
  87.         }
  88.     }
  89.     public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
  90.             throws Exception {
  91.         if (publicKey == null) {
  92.             throw new Exception("加密公钥为空, 请设置");
  93.         }
  94.         Cipher cipher = null;
  95.         try {
  96.             // 使用默认RSA
  97.             cipher = Cipher.getInstance("RSA");
  98.             // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  99.             // 初始化算法:公钥加密
  100.             cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  101.             // 公钥加密后的字节数组
  102.             byte[] output = cipher.doFinal(plainTextData);
  103.             return output;} catch (NoSuchAlgorithmException e) {
  104.             throw new Exception("无此加密算法"); } catch (NoSuchPaddingException e) { e.printStackTrace();
  105.             return null;} catch (InvalidKeyException e) {
  106.             throw new Exception("加密公钥非法,请检查");} catch (IllegalBlockSizeException e) {
  107.             throw new Exception("明文长度非法");} catch (BadPaddingException e) {
  108.             throw new Exception("明文数据已损坏"); }}
  109.     public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
  110.             throws Exception {if (privateKey == null) {throw new Exception("加密私钥为空, 请设置");}
  111.         Cipher cipher = null;
  112.         try {
  113.             // 使用默认RSA
  114.             cipher = Cipher.getInstance("RSA");
  115.             // 初始化算法:私钥加密
  116.             cipher.init(Cipher.ENCRYPT_MODE, privateKey);
  117.             // 加密后的密文数据,以字符数组的形式存在
  118.             byte[] output = cipher.doFinal(plainTextData);
  119.             return output;
  120.         } catch (NoSuchAlgorithmException e) {throw new Exception("无此加密算法");
  121.         } catch (NoSuchPaddingException e) {e.printStackTrace();
  122.             return null;
  123.         } catch (InvalidKeyException e) {throw new Exception("加密私钥非法,请检查");
  124.         } catch (IllegalBlockSizeException e) { throw new Exception("明文长度非法");
  125.         } catch (BadPaddingException e) {throw new Exception("明文数据已损坏");}}
  126.     public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)throws Exception {
  127.         if (privateKey == null) { throw new Exception("解密私钥为空, 请设置");}
  128.         Cipher cipher = null;
  129.         try {
  130.             // 使用默认RSA
  131.             cipher = Cipher.getInstance("RSA");
  132.             // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  133.             // 初始化解密算法:私钥解密
  134.             cipher.init(Cipher.DECRYPT_MODE, privateKey);
  135.             // 解密,生成以字符数组形式存在的明文数据
  136.             byte[] output = cipher.doFinal(cipherData);
  137.             return output;} catch (NoSuchAlgorithmException e) {
  138.             throw new Exception("无此解密算法");} catch (NoSuchPaddingException e) {
  139.             e.printStackTrace();
  140.             return null;} catch (InvalidKeyException e) {
  141.             throw new Exception("解密私钥非法,请检查");} catch (IllegalBlockSizeException e) {
  142.             throw new Exception("密文长度非法");} catch (BadPaddingException e) {
  143.             throw new Exception("密文数据已损坏");}}
  144.     public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
  145.             throws Exception {
  146.         if (publicKey == null) {
  147.             throw new Exception("解密公钥为空, 请设置");}
  148.         Cipher cipher = null;
  149.         try {
  150.             // 使用默认RSA
  151.             cipher = Cipher.getInstance("RSA");
  152.             // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  153.             // 初始化加密算法:公钥解密
  154.             cipher.init(Cipher.DECRYPT_MODE, publicKey);
  155.             byte[] output = cipher.doFinal(cipherData);
  156.             // 以字符数组形式存在的明文数据
  157.             return output;} catch (NoSuchAlgorithmException e) {
  158.             throw new Exception("无此解密算法");} catch (NoSuchPaddingException e) {
  159.   e.printStackTrace();return null;} catch (InvalidKeyException e) {throw new Exception("解密公钥非法,请检查");
  160.         } catch (IllegalBlockSizeException e) {throw new Exception("密文长度非法");
  161.         } catch (BadPaddingException e) {throw new Exception("密文数据已损坏"); }}
  162.     public static String byteArrayToString(byte[] data) {
  163.         StringBuilder stringBuilder = new StringBuilder();
  164.         for (int i = 0; i < data.length; i++) {
  165.             // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
  166.             stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
  167.             // 取出字节的低四位 作为索引得到相应的十六进制标识符
  168.             stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
  169.             if (i < data.length - 1) {
  170.                 stringBuilder.append(' ');}}
  171.         return stringBuilder.toString();}}
复制代码
回复

使用道具 举报

9

主题

22

帖子

111

积分

注册会员

Rank: 2

积分
111
 楼主| 发表于 2022-6-1 18:17:40 | 显示全部楼层
RSA加密、解密和签名算法后续代码
MainTest.java
  1. package com.ihep;

  2. public class MainTest {

  3.     public static void main(String[] args) throws Exception {
  4.         String filepath = "D:\\密码学\\publicKey.keystore";

  5.         // 生成公钥和私钥文件
  6.         RSAEncrypt.genKeyPair(filepath);

  7.         System.out.println("--------------公钥加密私钥解密过程-------------------");
  8.         String plainText = "你总会遇见为了你的快乐费尽心思的人";
  9.         // 公钥加密过程,得到加密后的数据
  10.         byte[] cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)), plainText.getBytes());
  11.         // 对加密数据进行编码处理,得到加密后的字符串
  12.         String cipher = Base64.encode(cipherData);
  13.         // 私钥解密过程
  14.         byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)), Base64.decode(cipher));
  15.         String restr = new String(res);
  16.         System.out.println("原文:" + plainText);
  17.         System.out.println("加密:" + cipher);
  18.         System.out.println("解密:" + restr);
  19.         System.out.println();

  20.         System.out.println("--------------私钥加密公钥解密过程-------------------");
  21.         plainText = "你总会遇见为了你的快乐费尽心思的人";
  22.         //私钥加密过程
  23.         cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)), plainText.getBytes());
  24.         cipher = Base64.encode(cipherData);
  25.         //公钥解密过程
  26.         res = RSAEncrypt.decrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)), Base64.decode(cipher));
  27.         restr = new String(res);
  28.         System.out.println("原文:" + plainText);
  29.         System.out.println("加密:" + cipher);
  30.         System.out.println("解密:" + restr);
  31.         System.out.println();

  32.         System.out.println("---------------私钥签名过程------------------");
  33.         String content = "你总会遇见为了你的快乐费尽心思的人";
  34.         String signstr = RSASignature.sign(content, RSAEncrypt.loadPrivateKeyByFile(filepath));
  35.         System.out.println("签名原串:" + content);
  36.         System.out.println("签名串:" + signstr);
  37.         System.out.println();

  38.         System.out.println("---------------公钥校验签名------------------");
  39.         System.out.println("签名原串:" + content);
  40.         System.out.println("签名串:" + signstr);

  41.         System.out.println("验签结果:" + RSASignature.doCheck(content, signstr, RSAEncrypt.loadPublicKeyByFile(filepath)));
  42.         System.out.println();

  43.     }
  44. }
复制代码
回复

使用道具 举报

9

主题

22

帖子

111

积分

注册会员

Rank: 2

积分
111
 楼主| 发表于 2022-6-1 18:23:59 | 显示全部楼层
RSA加密、解密和签名算法后续代码
Base64.java
  1. package com.ihep;
  2. public final class Base64 {
  3.     static private final int     BASELENGTH           = 128;
  4.     static private final int     LOOKUPLENGTH         = 64;
  5.     static private final int     TWENTYFOURBITGROUP   = 24;
  6.     static private final int     EIGHTBIT             = 8;
  7.     static private final int     SIXTEENBIT           = 16;
  8.     static private final int     FOURBYTE             = 4;
  9.     static private final int     SIGN                 = -128;
  10.     static private final char    PAD                  = '=';
  11.     static private final boolean fDebug               = false;
  12.     static final private byte[]  base64Alphabet       = new byte[BASELENGTH];
  13.     static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH];
  14.     static {for (int i = 0; i < BASELENGTH; ++i) {base64Alphabet[i] = -1;}
  15.         for (int i = 'Z'; i >= 'A'; i--) {base64Alphabet[i] = (byte) (i - 'A');}
  16.         for (int i = 'z'; i >= 'a'; i--) {base64Alphabet[i] = (byte) (i - 'a' + 26);}
  17.         for (int i = '9'; i >= '0'; i--) {base64Alphabet[i] = (byte) (i - '0' + 52);}
  18.         base64Alphabet['+'] = 62;
  19.         base64Alphabet['/'] = 63;
  20.         for (int i = 0; i <= 25; i++) {lookUpBase64Alphabet[i] = (char) ('A' + i);}
  21.         for (int i = 26, j = 0; i <= 51; i++, j++) {lookUpBase64Alphabet[i] = (char) ('a' + j);}
  22.         for (int i = 52, j = 0; i <= 61; i++, j++) {lookUpBase64Alphabet[i] = (char) ('0' + j);}
  23.         lookUpBase64Alphabet[62] = (char) '+';
  24.         lookUpBase64Alphabet[63] = (char) '/';}
  25.     private static boolean isWhiteSpace(char octect) {
  26.         return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);}
  27.     private static boolean isPad(char octect) {
  28.         return (octect == PAD);
  29.     }
  30.     private static boolean isData(char octect) {
  31.         return (octect < BASELENGTH && base64Alphabet[octect] != -1);
  32.     }
  33.     public static String encode(byte[] binaryData) {

  34.         if (binaryData == null) {
  35.             return null;
  36.         }
  37.         int lengthDataBits = binaryData.length * EIGHTBIT;
  38.         if (lengthDataBits == 0) {
  39.             return "";
  40.         }
  41.         int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
  42.         int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
  43.         int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
  44.         char encodedData[] = null;
  45.         encodedData = new char[numberQuartet * 4];
  46.         byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
  47.         int encodedIndex = 0;
  48.         int dataIndex = 0;
  49.         if (fDebug) {
  50.             System.out.println("number of triplets = " + numberTriplets);
  51.         }
  52.         for (int i = 0; i < numberTriplets; i++) {
  53.             b1 = binaryData[dataIndex++];
  54.             b2 = binaryData[dataIndex++];
  55.             b3 = binaryData[dataIndex++];
  56.             if (fDebug) {
  57.                 System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
  58.             }
  59.             l = (byte) (b2 & 0x0f);
  60.             k = (byte) (b1 & 0x03);
  61.             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  62.             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
  63.             byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
  64.             if (fDebug) {
  65.                 System.out.println("val2 = " + val2);
  66.                 System.out.println("k4   = " + (k << 4));
  67.                 System.out.println("vak  = " + (val2 | (k << 4)));
  68.             }
  69.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  70.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  71.             encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
  72.             encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
  73.         }
  74.         // form integral number of 6-bit groups
  75.         if (fewerThan24bits == EIGHTBIT) {
  76.             b1 = binaryData[dataIndex];
  77.             k = (byte) (b1 & 0x03);
  78.             if (fDebug) {
  79.                 System.out.println("b1=" + b1);
  80.                 System.out.println("b1<<2 = " + (b1 >> 2));
  81.             }
  82.             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  83.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  84.             encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
  85.             encodedData[encodedIndex++] = PAD;
  86.             encodedData[encodedIndex++] = PAD;
  87.         } else if (fewerThan24bits == SIXTEENBIT) {
  88.             b1 = binaryData[dataIndex];
  89.             b2 = binaryData[dataIndex + 1];
  90.             l = (byte) (b2 & 0x0f);
  91.             k = (byte) (b1 & 0x03);
  92.             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  93.             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
  94.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  95.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  96.             encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
  97.             encodedData[encodedIndex++] = PAD;
  98.         }
  99.         return new String(encodedData);
  100.     }
  101.     public static byte[] decode(String encoded) {

  102.         if (encoded == null) {
  103.             return null;
  104.         }
  105.         char[] base64Data = encoded.toCharArray();
  106.         // remove white spaces
  107.         int len = removeWhiteSpace(base64Data);
  108.         if (len % FOURBYTE != 0) {
  109.             return null;//should be divisible by four
  110.         }
  111.         int numberQuadruple = (len / FOURBYTE);
  112.         if (numberQuadruple == 0) {
  113.             return new byte[0];
  114.         }
  115.         byte decodedData[] = null;
  116.         byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
  117.         char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
  118.         int i = 0;
  119.         int encodedIndex = 0;
  120.         int dataIndex = 0;
  121.         decodedData = new byte[(numberQuadruple) * 3];
  122.         for (; i < numberQuadruple - 1; i++) {
  123.             if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
  124.                     || !isData((d3 = base64Data[dataIndex++]))
  125.                     || !isData((d4 = base64Data[dataIndex++]))) {
  126.                 return null;
  127.             }//if found "no data" just return null
  128.             b1 = base64Alphabet[d1];
  129.             b2 = base64Alphabet[d2];
  130.             b3 = base64Alphabet[d3];
  131.             b4 = base64Alphabet[d4];
  132.             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  133.             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  134.             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
  135.         }
  136.         if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
  137.             return null;//if found "no data" just return null
  138.         }
  139.         b1 = base64Alphabet[d1];
  140.         b2 = base64Alphabet[d2];
  141.         d3 = base64Data[dataIndex++];
  142.         d4 = base64Data[dataIndex++];
  143.         if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
  144.             if (isPad(d3) && isPad(d4)) {
  145.                 if ((b2 & 0xf) != 0)//last 4 bits should be zero
  146.                 {return null;}
  147.                 byte[] tmp = new byte[i * 3 + 1];
  148.                 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  149.                 tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
  150.                 return tmp;} else if (!isPad(d3) && isPad(d4)) {
  151.                 b3 = base64Alphabet[d3];
  152.                 if ((b3 & 0x3) != 0)//last 2 bits should be zero
  153.                 {return null;}
  154.                 byte[] tmp = new byte[i * 3 + 2];
  155.                 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  156.                 tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  157.                 tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  158.                 return tmp;} else {
  159.                 return null;}
  160.         } else { //No PAD e.g 3cQl
  161.             b3 = base64Alphabet[d3];
  162.             b4 = base64Alphabet[d4];
  163.             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  164.             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  165.             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);}
  166.         return decodedData;}
  167.     private static int removeWhiteSpace(char[] data) {
  168.         if (data == null) {
  169.             return 0;}
  170.         // count characters that's not whitespace
  171.         int newSize = 0;
  172.         int len = data.length;
  173.         for (int i = 0; i < len; i++) {
  174.             if (!isWhiteSpace(data[i])) {data[newSize++] = data[i];}}
  175.         return newSize;}}
复制代码
回复

使用道具 举报

9

主题

22

帖子

111

积分

注册会员

Rank: 2

积分
111
 楼主| 发表于 2022-6-1 18:40:54 | 显示全部楼层
ECC椭圆曲线上公钥密码算法

一、ECC椭圆曲线上公钥密码简介
椭圆加密算法(ECC)是一种公钥加密体制,最初由KoblitzMiller两人于1985年提出,其数学基础是利用椭圆曲线上的有理点构成Abel加法群上椭圆离散对数的计算困难性。ECC的主要优势是在某些情况下,它比其他的方法使用更小的密钥,比如RSA加密算法,提供相当的或更高等级的安全。ECC的另一个优势是可以定义群之间的双线性映射,基于Weil对或是Tate对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。
二、ECC椭圆曲线上公钥密码加解密过程
1、服务端生成配对的公钥和私钥
2、私钥保存在服务端,公钥发送给客户端
3、客户端使用公钥加密明文传输给服务端
4、服务端使用私钥解密密文得到明文
三、程序代码
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<math.h>
  5. #include<time.h>
  6. #define MAX 100
  7. typedef struct point{
  8.         int point_x;
  9.         int point_y;
  10. }Point;
  11. typedef struct ecc{
  12.         struct point p[MAX];
  13.         int len;
  14. }ECCPoint;
  15. typedef struct generator{
  16.         Point p;
  17.         int p_class;
  18. }GENE_SET;
  19. void get_all_points();
  20. int int_sqrt(int s);
  21. Point timesPiont(int k,Point p);
  22. Point add_two_points(Point p1,Point p2);
  23. int inverse(int n,int b);
  24. void get_generetor_class();
  25. void encrypt_ecc();
  26. void decrypt_ecc();
  27. int mod_p(int s);
  28. void print();
  29. int isPrime(int n);
  30. char alphabet[30]="abcdefghijklmnopqrstuvwxyz";
  31. int a=-1,b=0,p=89;//椭圆曲线为E89(-1,0): y2=x3-x (mod 89)
  32. ECCPoint eccPoint;
  33. GENE_SET geneSet[MAX];
  34. int geneLen;
  35. char plain[]="yes";
  36. int m[MAX];
  37. int cipher[MAX];
  38. int nB;//私钥
  39. Point P1,P2,Pt,G,PB;
  40. Point Pm;
  41. int C[MAX];

  42. int main()
  43. {       
  44.         get_generetor_class();
  45.         encrypt_ecc();
  46.         decrypt_ecc();
  47.         return 0;
  48. }
  49. //task4:加密
  50. void encrypt_ecc()
  51. {
  52.         int num,i,j;
  53.         int gene_class;
  54.         int num_t;
  55.         int k;
  56.         srand(time(NULL));
  57.         //明文转换过程
  58.         for(i=0;i<strlen(plain);i++)
  59.         {
  60.                 for(j=0;j<26;j++) //for(j=0;j<26;j++)
  61.                 {
  62.                         if(plain[i]==alphabet[j])
  63.                         {
  64.                                 m[i]=j;//将字符串明文换成数字,并存到整型数组m里面
  65.                         }
  66.                 }         
  67.         }
  68.         //选择生成元
  69.         num=rand()%geneLen;
  70.         gene_class=geneSet[num].p_class;
  71.         while(isPrime(gene_class)==-1)//不是素数
  72.         {
  73.                  num=rand()%(geneLen-3)+3;
  74.                  gene_class=geneSet[num].p_class;
  75.         }       
  76.         //printf("gene_class=%d\n",gene_class);
  77.         G=geneSet[num].p;
  78.         //printf("G:(%d,%d)\n",geneSet[num].p.point_x,geneSet[num].p.point_y);
  79.         nB=rand()%(gene_class-1)+1;//选择私钥
  80.         PB=timesPiont(nB,G);
  81.         printf("\n公钥:\n");
  82.         printf("{y^2=x^3%d*x+%d,%d,(%d,%d),(%d,%d)}\n",a,b,gene_class,G.point_x,G.point_y,PB.point_x,PB.point_y);
  83.         printf("私钥:\n");
  84.         printf("nB=%d\n",nB);
  85.         //加密
  86.         //
  87.         k=rand()%(gene_class-2)+1;
  88.         P1=timesPiont(k,G);
  89.         //
  90.         num_t=rand()%eccPoint.len; //选择映射点
  91.         Pt=eccPoint.p[num_t];
  92.         //printf("Pt:(%d,%d)\n",Pt.point_x,Pt.point_y);
  93.         P2=timesPiont(k,PB);
  94.         Pm=add_two_points(Pt,P2);
  95.         printf("加密数据:\n");
  96.         printf("kG=(%d,%d),Pt+kPB=(%d,%d),C={",P1.point_x,P1.point_y,Pm.point_x,Pm.point_y);
  97.         for(i=0;i<strlen(plain);i++)
  98.         {
  99. //                num_t=rand()%eccPoint.len; //选择映射点
  100. //                Pt=eccPoint.p[num_t];
  101.                 C[i]=m[i]*Pt.point_x+Pt.point_y;
  102.                 printf("{%d}",C[i]);
  103.         }       
  104.         printf("}\n");
  105. }
  106. //task5:解密
  107. void decrypt_ecc()
  108. {
  109.         Point temp,temp1;
  110.         int m,i;
  111.         temp=timesPiont(nB,P1);
  112.         temp.point_y=0-temp.point_y;
  113.         temp1=add_two_points(Pm,temp);//求解Pt
  114. //        printf("(%d,%d)\n",temp.point_x,temp.point_y);
  115. //        printf("(%d,%d)\n",temp1.point_x,temp1.point_y);
  116.         printf("\n解密结果:\n");
  117.         for(i=0;i<strlen(plain);i++)
  118.         {
  119.                 m=(C[i]-temp1.point_y)/temp1.point_x;
  120.                 printf("%c",alphabet[m]);//输出密文
  121.         }
  122.         printf("\n");
  123. }
  124. //判断是否为素数
  125. int isPrime(int n)
  126. {
  127.         int i,k;
  128.     k = sqrt(n);
  129.     for (i = 2; i <= k;i++)
  130.     {
  131.             if (n%i == 0)
  132.                         break;
  133.         }      
  134.     if (i <=k){
  135.             return -1;
  136.         }
  137.     else {
  138.              return 0;
  139.         }
  140. }
  141. //task3:求生成元以及阶
  142. void get_generetor_class()
  143. {       
  144.         int i,j=0;
  145.         int count=1;
  146.         Point p1,p2;
  147.         get_all_points();       
  148. //        p1.point_x=p2.point_x=3;
  149. //        p1.point_y=p2.point_y=2;
  150. //        while(1)
  151. //        {
  152. //                printf("(%d,%d)+(%d,%d)---%d\n",p1.point_x,p1.point_y,p2.point_x,p2.point_y,count);
  153. //                p2=add_two_points(p1,p2);
  154. //                count++;
  155. //                if(p2.point_x==-1 && p2.point_y==-1)
  156. //                {
  157. //                        break;
  158. //                }
  159. //        }
  160. //        printf("\n\n(%d,%d)---%d\n",p1.point_x,p1.point_y,count);
  161.         //
  162. //        do{
  163. //                        printf("(%d,%d)+(%d,%d)---%d\n",p1.point_x,p1.point_y,p2.point_x,p2.point_y,count);
  164. //                        p2=add_two_points(p1,p2);
  165. //                        count++;
  166. //                       
  167. //        } while(!((p2.point_x==p1.point_x)&&(p2.point_y==p1.point_y)));
  168. //        printf("(%d,%d)+(%d,%d)---%d\n",p1.point_x,p1.point_y,p2.point_x,p2.point_y,count);
  169. //        count ++ ;
  170. //        printf("\n\n(%d,%d)---%d\n",p1.point_x,p1.point_y,count);
  171.         printf("\n**********************************输出生成元以及阶:*************************************\n");
  172.         for(i=0;i<eccPoint.len;i++)
  173.         {
  174.                 count=1;
  175.                 p1.point_x=p2.point_x=eccPoint.p[i].point_x;
  176.                 p1.point_y=p2.point_y=eccPoint.p[i].point_y;               
  177.                 while(1)
  178.                 {       
  179.                         p2=add_two_points(p1,p2);                                       
  180.                         if(p2.point_x==-1 && p2.point_y==-1)
  181.                         {
  182.                                 break;
  183.                         }
  184.                         count++;
  185.                         if(p2.point_x==p1.point_x)
  186.                         {
  187.                                 break;
  188.                         }                                               
  189.                 }
  190.                 count++;
  191.                 if(count<=eccPoint.len+1)
  192.                 {
  193.                         geneSet[j].p.point_x=p1.point_x;
  194.                         geneSet[j].p.point_y=p1.point_y;
  195.                         geneSet[j].p_class=count;
  196.                         printf("(%d,%d)--->>%d\t",geneSet[j].p.point_x,geneSet[j].p.point_y,geneSet[j].p_class);
  197.                         j++;
  198.                         if(j % 6 ==0){
  199.                                 printf("\n");
  200.                         }
  201.                 }
  202.                 geneLen=j;       
  203.         }
  204. }

  205. //task2:倍点运算的递归算法
  206. Point timesPiont(int k,Point p0)
  207. {
  208.         if(k==1){
  209.                 return p0;
  210.         }                
  211.         else if(k==2){
  212.                 return add_two_points(p0,p0);
  213.         }else{
  214.                 return add_two_points(p0,timesPiont(k-1,p0));
  215.         }
  216. }
  217. //两点的加法运算
  218. Point add_two_points(Point p1,Point p2)
  219. {
  220.         long t;
  221.         int x1=p1.point_x;
  222.         int y1=p1.point_y;
  223.         int x2=p2.point_x;
  224.         int y2=p2.point_y;
  225.         int tx,ty;
  226.         int x3,y3;
  227.         int flag=0;
  228.         //求
  229.         if((x2==x1)&& (y2==y1) )
  230.         {
  231.                 //相同点相加
  232.                 if(y1==0)
  233.                 {
  234.                         flag=1;
  235.                 }else{
  236.                         t=(3*x1*x1+a)*inverse(p,2*y1) % p;
  237.                 }
  238.                 //printf("inverse(p,2*y1)=%d\n",inverse(p,2*y1));
  239.         }else{
  240.                 //不同点相加
  241.                 ty=y2-y1;
  242.                 tx=x2-x1;
  243.                 while(ty<0)
  244.                 {
  245.                         ty+=p;
  246.                 }
  247.                 while(tx<0)
  248.                 {
  249.                         tx+=p;
  250.                 }
  251.                 if(tx==0 && ty !=0)
  252.                 {
  253.                         flag=1;
  254.                 }else{
  255.                         t=ty*inverse(p,tx) % p;
  256.                 }
  257.         }
  258.         if(flag==1)
  259.         {
  260.                 p2.point_x=-1;
  261.                 p2.point_y=-1;
  262.         }else{
  263.                 x3=(t*t-x1-x2) % p;
  264.                 y3=(t*(x1-x3)-y1) % p;
  265.         //使结果在有限域GF(P)上
  266.                 while(x3<0)
  267.                 {
  268.                         x3+=p;
  269.                 }
  270.                 while(y3<0)
  271.                 {
  272.                         y3+=p;
  273.                 }
  274.                 p2.point_x=x3;
  275.                 p2.point_y=y3;
  276.         }       
  277.         return p2;
  278. }
  279. //求b关于n的逆元
  280. int inverse(int n,int b)
  281. {
  282.         int q,r,r1=n,r2=b,t,t1=0,t2=1,i=1;
  283.         while(r2>0)
  284.         {
  285.                 q=r1/r2;
  286.                 r=r1%r2;
  287.                 r1=r2;
  288.                 r2=r;
  289.                 t=t1-q*t2;
  290.                 t1=t2;
  291.                 t2=t;
  292.         }
  293.         if(t1>=0)
  294.                 return t1%n;
  295.         else{  
  296.                 while((t1+i*n)<0)
  297.                         i++;
  298.                 return t1+i*n;
  299.         }
  300. }
  301. //task1:求出椭圆曲线上所有点
  302. void get_all_points()
  303. {
  304.         int i=0;
  305.         int j=0;
  306.         int s,y=0;
  307.         int n=0,q=0;
  308.         int modsqrt=0;
  309.         int flag=0;
  310.         if (4 * a * a * a + 27 * b * b != 0)
  311.         {
  312.                 for(i=0;i<=p-1;i++)
  313.                 {
  314.                         flag=0;
  315.                         n=1;
  316.                         y=0;
  317.                         s= i * i * i + a * i + b;
  318.                         while(s<0)
  319.                         {
  320.                                 s+=p;
  321.                         }
  322.                         s=mod_p(s);
  323.                         modsqrt=int_sqrt(s);
  324.                         if(modsqrt!=-1)
  325.                         {
  326.                                 flag=1;
  327.                                 y=modsqrt;
  328.                         }else{
  329.                                 while(n<=p-1)
  330.                                 {
  331.                                         q=s+n*p;
  332.                                         modsqrt=int_sqrt(q);
  333.                                         if(modsqrt!=-1)
  334.                                         {
  335.                                                 y=modsqrt;
  336.                                                 flag=1;
  337.                                                 break;
  338.                                         }
  339.                                                 flag=0;
  340.                                                 n++;
  341.                                 }
  342.                         }
  343.                         if(flag==1)
  344.                         {
  345.                                 eccPoint.p[j].point_x=i;
  346.                                 eccPoint.p[j].point_y=y;
  347.                                 j++;
  348.                                 if(y!=0)
  349.                                 {
  350.                                         eccPoint.p[j].point_x=i;
  351.                                         eccPoint.p[j].point_y=(p-y) % p;
  352.                                         j++;
  353.                                 }                               
  354.                         }
  355.                 }
  356.                 eccPoint.len=j;//点集个数
  357.                 print(); //打印点集
  358.         }       
  359. }

  360. //取模函数
  361. int mod_p(int s)
  362. {
  363.         int i;        //保存s/p的倍数
  364.         int result;        //模运算的结果
  365.         i = s / p;
  366.         result = s - i * p;
  367.         if (result >= 0)
  368.         {
  369.                 return result;
  370.         }
  371.         else
  372.         {
  373.                 return result + p;
  374.         }
  375. }

  376. //判断平方根是否为整数
  377. int int_sqrt(int s)
  378. {
  379.         int temp;
  380.         temp=(int)sqrt(s);//转为整型
  381.         if(temp*temp==s)
  382.         {
  383.                 return temp;
  384.         }else{
  385.                 return -1;
  386.         }
  387. }
  388. //打印点集
  389. void print()
  390. {
  391.         int i;
  392.         int len=eccPoint.len;
  393.         printf("\n该椭圆曲线上共有%d个点(包含无穷远点)\n",len+1);
  394.         for(i=0;i<len;i++)
  395.         {
  396.                 if(i % 8==0)
  397.                 {
  398.                         printf("\n");
  399.                 }
  400.                 printf("(%2d,%2d)\t",eccPoint.p[i].point_x,eccPoint.p[i].point_y);
  401.         }
  402.         printf("\n");
  403. }
复制代码
四、运行结果截图

本帖子中包含更多资源

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

x
回复

使用道具 举报

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

本版积分规则

教学服务系统

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

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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