教学服务系统

 找回密码
 立即注册
搜索
查看: 979|回复: 6

信息计算2019级2班3号徐柳婧

[复制链接]

8

主题

24

帖子

100

积分

注册会员

Rank: 2

积分
100
发表于 2022-6-2 20:49:29 | 显示全部楼层 |阅读模式
RSA签名和加密

一、Java实现RSA签名和加密
在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA属于非对称加密算法,有两个密钥。区别于共享密钥的对称加密算法,如DES和AES。公钥可以共享给任何人,私钥自己进行保管。公钥用于加密数据,使得该加密数据只能用私钥进行解密;私钥也可用于签名数据,签名和数据一起发送,然后使用公钥验证数据是否被篡改。
二、RSA实现密钥对
在实际做任何形式加密之前,需要有公钥和私钥两个密钥对。幸运的是,Java提供了非常简单的方法,首先获得RSA KeyPairGenerator实例,然后使用2048为长度进行初始化并传入SecureRandom实例。后者用作生成器的熵或随机数据源。第三行生成密钥对,所有内容都就是这样,非常简单。如果需要使用密钥对存储器,需要使用Java KeyStore工具,后面会详细解释。
三、加密和解密
这里使用base64编码,主要是典型的REST API中很常用,我们当然也可以不用base64编码而直接使用字节数组。确保明确地且一致地为字符串指定字节编码。否则字节错位将导致密文和无法解密或验证签名。首先获得RSA密码实例并设置为加密模式,然后使用公钥加密消息。然后一次性传入消息字符串的字节数组并获得加密后的字节数组,最后转码并返回。运维RSA是相当慢,比对称加密算法如AES要慢的多。
四、签名与验证
我们使用公钥进行加密,然后使用私钥解密。理论上反过来也行(私钥加密,公钥解密),但这不安全且大多数库(包括java.security)也不支持。然而,这种方式在构建API时比较有用。使用私钥对消息进行签名,然后使用公钥进行验证签名。这种机制可以确保消息确实来着公钥创建者(私钥持有者),使得传输过程消息不会被篡改。
加密和签名都是为了安全性考虑,但略有不同。常有人问加密和签名是用私钥还是公钥?其实都是对加密和签名的作用有所混淆。简单的说,加密是为了防止信息被泄露,而签名是为了防止信息被篡改。


回复

使用道具 举报

8

主题

24

帖子

100

积分

注册会员

Rank: 2

积分
100
 楼主| 发表于 2022-6-2 20:51:09 | 显示全部楼层
程序代码: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 {
  15.         for (int i = 0; i < BASELENGTH; ++i) {
  16.             base64Alphabet[i] = -1;
  17.         }
  18.         for (int i = 'Z'; i >= 'A'; i--) {
  19.             base64Alphabet[i] = (byte) (i - 'A');
  20.         }
  21.         for (int i = 'z'; i >= 'a'; i--) {
  22.             base64Alphabet[i] = (byte) (i - 'a' + 26);
  23.         }

  24.         for (int i = '9'; i >= '0'; i--) {
  25.             base64Alphabet[i] = (byte) (i - '0' + 52);
  26.         }

  27.         base64Alphabet['+'] = 62;
  28.         base64Alphabet['/'] = 63;

  29.         for (int i = 0; i <= 25; i++) {
  30.             lookUpBase64Alphabet[i] = (char) ('A' + i);
  31.         }

  32.         for (int i = 26, j = 0; i <= 51; i++, j++) {
  33.             lookUpBase64Alphabet[i] = (char) ('a' + j);
  34.         }

  35.         for (int i = 52, j = 0; i <= 61; i++, j++) {
  36.             lookUpBase64Alphabet[i] = (char) ('0' + j);
  37.         }
  38.         lookUpBase64Alphabet[62] = (char) '+';
  39.         lookUpBase64Alphabet[63] = (char) '/';

  40.     }

  41.     private static boolean isWhiteSpace(char octect) {
  42.         return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
  43.     }

  44.     private static boolean isPad(char octect) {
  45.         return (octect == PAD);
  46.     }

  47.     private static boolean isData(char octect) {
  48.         return (octect < BASELENGTH && base64Alphabet[octect] != -1);
  49.     }

  50.     public static String encode(byte[] binaryData) {

  51.         if (binaryData == null) {
  52.             return null;
  53.         }

  54.         int lengthDataBits = binaryData.length * EIGHTBIT;
  55.         if (lengthDataBits == 0) {
  56.             return "";
  57.         }

  58.         int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
  59.         int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
  60.         int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
  61.         char encodedData[] = null;

  62.         encodedData = new char[numberQuartet * 4];

  63.         byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;

  64.         int encodedIndex = 0;
  65.         int dataIndex = 0;
  66.         if (fDebug) {
  67.             System.out.println("number of triplets = " + numberTriplets);
  68.         }

  69.         for (int i = 0; i < numberTriplets; i++) {
  70.             b1 = binaryData[dataIndex++];
  71.             b2 = binaryData[dataIndex++];
  72.             b3 = binaryData[dataIndex++];

  73.             if (fDebug) {
  74.                 System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
  75.             }

  76.             l = (byte) (b2 & 0x0f);
  77.             k = (byte) (b1 & 0x03);

  78.             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  79.             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
  80.             byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);

  81.             if (fDebug) {
  82.                 System.out.println("val2 = " + val2);
  83.                 System.out.println("k4   = " + (k << 4));
  84.                 System.out.println("vak  = " + (val2 | (k << 4)));
  85.             }

  86.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  87.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  88.             encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
  89.             encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
  90.         }

  91.         // form integral number of 6-bit groups
  92.         if (fewerThan24bits == EIGHTBIT) {
  93.             b1 = binaryData[dataIndex];
  94.             k = (byte) (b1 & 0x03);
  95.             if (fDebug) {
  96.                 System.out.println("b1=" + b1);
  97.                 System.out.println("b1<<2 = " + (b1 >> 2));
  98.             }
  99.             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  100.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  101.             encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
  102.             encodedData[encodedIndex++] = PAD;
  103.             encodedData[encodedIndex++] = PAD;
  104.         } else if (fewerThan24bits == SIXTEENBIT) {
  105.             b1 = binaryData[dataIndex];
  106.             b2 = binaryData[dataIndex + 1];
  107.             l = (byte) (b2 & 0x0f);
  108.             k = (byte) (b1 & 0x03);

  109.             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  110.             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);

  111.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  112.             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  113.             encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
  114.             encodedData[encodedIndex++] = PAD;
  115.         }

  116.         return new String(encodedData);
  117.     }

  118.     public static byte[] decode(String encoded) {

  119.         if (encoded == null) {
  120.             return null;
  121.         }

  122.         char[] base64Data = encoded.toCharArray();
  123.         // remove white spaces
  124.         int len = removeWhiteSpace(base64Data);

  125.         if (len % FOURBYTE != 0) {
  126.             return null;//should be divisible by four
  127.         }

  128.         int numberQuadruple = (len / FOURBYTE);

  129.         if (numberQuadruple == 0) {
  130.             return new byte[0];
  131.         }

  132.         byte decodedData[] = null;
  133.         byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
  134.         char d1 = 0, d2 = 0, d3 = 0, d4 = 0;

  135.         int i = 0;
  136.         int encodedIndex = 0;
  137.         int dataIndex = 0;
  138.         decodedData = new byte[(numberQuadruple) * 3];

  139.         for (; i < numberQuadruple - 1; i++) {

  140.             if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
  141.                     || !isData((d3 = base64Data[dataIndex++]))
  142.                     || !isData((d4 = base64Data[dataIndex++]))) {
  143.                 return null;
  144.             }//if found "no data" just return null

  145.             b1 = base64Alphabet[d1];
  146.             b2 = base64Alphabet[d2];
  147.             b3 = base64Alphabet[d3];
  148.             b4 = base64Alphabet[d4];

  149.             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  150.             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  151.             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
  152.         }

  153.         if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
  154.             return null;//if found "no data" just return null
  155.         }

  156.         b1 = base64Alphabet[d1];
  157.         b2 = base64Alphabet[d2];

  158.         d3 = base64Data[dataIndex++];
  159.         d4 = base64Data[dataIndex++];
  160.         if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
  161.             if (isPad(d3) && isPad(d4)) {
  162.                 if ((b2 & 0xf) != 0)//last 4 bits should be zero
  163.                 {
  164.                     return null;
  165.                 }
  166.                 byte[] tmp = new byte[i * 3 + 1];
  167.                 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  168.                 tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
  169.                 return tmp;
  170.             } else if (!isPad(d3) && isPad(d4)) {
  171.                 b3 = base64Alphabet[d3];
  172.                 if ((b3 & 0x3) != 0)//last 2 bits should be zero
  173.                 {
  174.                     return null;
  175.                 }
  176.                 byte[] tmp = new byte[i * 3 + 2];
  177.                 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  178.                 tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  179.                 tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  180.                 return tmp;
  181.             } else {
  182.                 return null;
  183.             }
  184.         } else { //No PAD e.g 3cQl
  185.             b3 = base64Alphabet[d3];
  186.             b4 = base64Alphabet[d4];
  187.             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  188.             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  189.             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);

  190.         }

  191.         return decodedData;
  192.     }

  193.     private static int removeWhiteSpace(char[] data) {
  194.         if (data == null) {
  195.             return 0;
  196.         }

  197.         // count characters that's not whitespace
  198.         int newSize = 0;
  199.         int len = data.length;
  200.         for (int i = 0; i < len; i++) {
  201.             if (!isWhiteSpace(data[i])) {
  202.                 data[newSize++] = data[i];
  203.             }
  204.         }
  205.         return newSize;
  206.     }
  207. }
复制代码


回复

使用道具 举报

8

主题

24

帖子

100

积分

注册会员

Rank: 2

积分
100
 楼主| 发表于 2022-6-2 20:53:14 | 显示全部楼层
本帖最后由 徐柳婧 于 2022-6-2 23:35 编辑
主测试
  1. maintest.java
  2. package com.ihep;

  3. public class MainTest {

  4. public static void main(String[] args) throw exception {
  5. String filepath = “E:/tmp/”;

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

  8. System.out.println(“--------------公钥加密私钥解密过程-------------------”);
  9. String plainText = “徐柳婧”;
  10. // 公钥加密过程,得到加密后的数据
  11. byte[] cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)), plainText.getBytes());
  12. // 对加密数据进行编码处理,得到加密后的字符串
  13. String cipher = Base64.encode(cipherData);
  14. // 私钥解密过程
  15. byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)), Base64.decode(cipher));
  16. String restr = new String(res);
  17. System.out.println(“原文:” + plainText);
  18. System.out.println(“加密:” + cipher);
  19. System.out.println(“解密:” + restr);
  20. System.out.println();

  21. System.out.println(“--------------私钥加密公钥解密过程-------------------”);
  22. plainText = “徐柳婧”;
  23. //私钥加密过程
  24. cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)), plainText.getBytes());
  25. cipher = Base64.encode(cipherData);
  26. //公钥解密过程
  27. res = RSAEncrypt.decrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)), Base64.decode(cipher));
  28. restr = new String(res);
  29. System.out.println(“原文:” + plainText);
  30. System.out.println(“加密:” + cipher);
  31. System.out.println(“解密:” + restr);
  32. System.out.println();

  33. System.out.println(“---------------私钥签名过程------------------”);
  34. String content = “徐柳婧想喝奶茶”;
  35. String signstr = RSASignature.sign(content, RSAEncrypt.loadPrivateKeyByFile(filepath));
  36. System.out.println(“签名原串:” + content);
  37. System.out.println(“签名串:” + signstr);
  38. System.out.println();

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

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

  44.     }
  45. }
复制代码

回复

使用道具 举报

8

主题

24

帖子

100

积分

注册会员

Rank: 2

积分
100
 楼主| 发表于 2022-6-2 20:54:00 | 显示全部楼层
本帖最后由 徐柳婧 于 2022-6-2 23:35 编辑

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. private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6',
  14. '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  15. public static void genKeyPair(String filePath) {
  16. // 密钥对生成器
  17. KeyPairGenerator keyPairGen = null;
  18. try {
  19. // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
  20. keyPairGen = KeyPairGenerator.getInstance("RSA");
  21. } catch (NoSuchAlgorithmException e) {
  22. // TODO Auto-generated catch block
  23. e.printStackTrace();
  24. }
  25. // 初始化密钥对生成器,密钥大小为96-1024位
  26. keyPairGen.initialize(1024, new SecureRandom());
  27. // 生成一个密钥对,保存在keyPair中
  28. KeyPair keyPair = keyPairGen.generateKeyPair();
  29. // 得到私钥
  30. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  31. // 得到公钥
  32. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  33. try {
  34. // 得到公钥字符串
  35. String publicKeyString = Base64.encode(publicKey.getEncoded());
  36. // 得到私钥字符串
  37. String privateKeyString = Base64.encode(privateKey.getEncoded());
  38. // 将密钥对写入到文件
  39. FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");
  40. FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");
  41. BufferedWriter pubbw = new BufferedWriter(pubfw);
  42. BufferedWriter pribw = new BufferedWriter(prifw);
  43. pubbw.write(publicKeyString);
  44. pribw.write(privateKeyString);
  45. pubbw.flush();
  46. pubbw.close();
  47. pubfw.close();
  48. pribw.flush();
  49. pribw.close();
  50. prifw.close();
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. public static String loadPublicKeyByFile(String path) throws Exception {
  56. try {
  57. BufferedReader br = new BufferedReader(new FileReader(path
  58. + "/publicKey.keystore"));
  59. String readLine = null;
  60. StringBuilder sb = new StringBuilder();
  61. while ((readLine = br.readLine()) != null) {
  62. sb.append(readLine);
  63. }
  64. br.close();
  65. return sb.toString();
  66. } catch (IOException e) {
  67. throw new Exception("公钥数据流读取错误");
  68. } catch (NullPointerException e) {
  69. throw new Exception("公钥输入流为空");
  70. }
  71. }
  72. public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
  73. throws Exception {
  74. try {
  75. byte[] buffer = Base64.decode(publicKeyStr);
  76. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  77. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
  78. return (RSAPublicKey) keyFactory.generatePublic(keySpec);
  79. } catch (NoSuchAlgorithmException e) {
  80. throw new Exception("无此算法");
  81. } catch (InvalidKeySpecException e) {
  82. throw new Exception("公钥非法");
  83. } catch (NullPointerException e) {
  84. throw new Exception("公钥数据为空");
  85. }
  86. }
  87. public static String loadPrivateKeyByFile(String path) throws Exception {
  88. try {
  89. BufferedReader br = new BufferedReader(new FileReader(path
  90. + "/privateKey.keystore"));
  91. String readLine = null;
  92. StringBuilder sb = new StringBuilder();
  93. while ((readLine = br.readLine()) != null) {
  94. sb.append(readLine);
  95. }
  96. br.close();
  97. /** 该字符串从私钥文件中获取,称之为私钥字符串
  98. * MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALaIDyyav7J8oD/8sONfP772aa1foDlHmoXRArqe+2po14c1q7nGR8DLk
  99. * 55J0sgxt/EOvtvxtwo4cPFtoLSBzdKVn/ZmR7uyHQXsMzqcmz7n7DGAzNNqxlu0SLHVjZ4HscWxnC+dGa037Ec9m5DKRT6aMckNmxZp3G
  100. * xic9wzId6zAgMBAAECgYEAhpOUFH/XvEH0aJjm1gzA1AubaI8rc2/edrDeQTe8B/1agr7IaMTO3E97++VT+fPmOV10zHbPTELGysnYBZ3
  101. * 6X/wLaKs+GMO/uewNAsyu46u3izwNVCygBiM62mlmhk3Y9J8ZcmoQHzXGV0p0TuGJsIlAofCAN1ielWLPcEVUPckCQQDoQm4GKe2C26oU
  102. * aXRwLy2WLczfmqLTlJ8QyJs8ruL78JikhDgLWaLPBJ+lHmTxahC4HjJ9LhNxNVcpbyMiHhM1AkEAyTBjkOGwBJTlYMmS1hn6BoqA5xCRF
  103. * Iv8gZZMxj+xcvSSEfZU9ObVArOBQRUoIO3GdsyaVfG/DNwuP7zGI16/RwJBAMfyIEu4HpsvxeyKmE3Xn5QQ27WHpzMkWAeX22RTXl7r0k
  104. * yW8rR6txkm7tS0JMxbtgb7IBX564zjEaU+4u0FHR0CQG+v+zYM9Ag3GHd4r5lH5nMHJLQhkEjVxaGy7IAKD9p/Ry/NjjA+jPXo7NJSimp
  105. * tVYXR48PeZm8fNFWR2HT+PjUCQFu3yN71iiXA0EW35Y1HHIE814gUV/O5T4gpUNzK9NLvHLFQNbzgoZER5yIGgBWDju1keBkojm8P69A7
  106. * qdtXILU=
  107. */
  108. return sb.toString();
  109. } catch (IOException e) {
  110. throw new Exception("私钥数据读取错误");
  111. } catch (NullPointerException e) {
  112. throw new Exception("私钥输入流为空");
  113. }
  114. }
  115. public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
  116. throws Exception {
  117. try {
  118. byte[] buffer = Base64.decode(privateKeyStr);
  119. PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
  120. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  121. return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
  122. } catch (NoSuchAlgorithmException e) {
  123. throw new Exception("无此算法");
  124. } catch (InvalidKeySpecException e) {
  125. throw new Exception("私钥非法");
  126. } catch (NullPointerException e) {
  127. throw new Exception("私钥数据为空");
  128. }
  129. }
  130. public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
  131. throws Exception {
  132. if (publicKey == null) {
  133. throw new Exception("加密公钥为空, 请设置");
  134. }
  135. Cipher cipher = null;
  136. try {
  137. // 使用默认RSA
  138. cipher = Cipher.getInstance("RSA");
  139. // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  140. // 初始化算法:公钥加密
  141. cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  142. // 公钥加密后的字节数组
  143. byte[] output = cipher.doFinal(plainTextData);
  144. return output;
  145. } catch (NoSuchAlgorithmException e) {
  146. throw new Exception("无此加密算法");
  147. } catch (NoSuchPaddingException e) {
  148. e.printStackTrace();
  149. return null;
  150. } catch (InvalidKeyException e) {
  151. throw new Exception("加密公钥非法,请检查");
  152. } catch (IllegalBlockSizeException e) {
  153. throw new Exception("明文长度非法");
  154. } catch (BadPaddingException e) {
  155. throw new Exception("明文数据已损坏");
  156. }
  157. }

  158. public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
  159. throws Exception {
  160. if (privateKey == null) {
  161. throw new Exception("加密私钥为空, 请设置");
  162. }
  163. Cipher cipher = null;
  164. try {
  165. // 使用默认RSA
  166. cipher = Cipher.getInstance("RSA");
  167. // 初始化算法:私钥加密
  168. cipher.init(Cipher.ENCRYPT_MODE, privateKey);
  169. // 加密后的密文数据,以字符数组的形式存在
  170. byte[] output = cipher.doFinal(plainTextData);
  171. return output;
  172. } catch (NoSuchAlgorithmException e) {
  173. throw new Exception("无此加密算法");
  174. } catch (NoSuchPaddingException e) {
  175. e.printStackTrace();
  176. return null;
  177. } catch (InvalidKeyException e) {
  178. throw new Exception("加密私钥非法,请检查");
  179. } catch (IllegalBlockSizeException e) {
  180. throw new Exception("明文长度非法");
  181. } catch (BadPaddingException e) {
  182. throw new Exception("明文数据已损坏");
  183. }
  184. }

  185. public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
  186. throws Exception {
  187. if (privateKey == null) {
  188. throw new Exception("解密私钥为空, 请设置");
  189. }
  190. Cipher cipher = null;
  191. try {
  192. // 使用默认RSA
  193. cipher = Cipher.getInstance("RSA");
  194. // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  195. // 初始化解密算法:私钥解密
  196. cipher.init(Cipher.DECRYPT_MODE, privateKey);
  197. // 解密,生成以字符数组形式存在的明文数据
  198. byte[] output = cipher.doFinal(cipherData);
  199. return output;
  200. } catch (NoSuchAlgorithmException e) {
  201. throw new Exception("无此解密算法");
  202. } catch (NoSuchPaddingException e) {
  203. e.printStackTrace();
  204. return null;
  205. } catch (InvalidKeyException e) {
  206. throw new Exception("解密私钥非法,请检查");
  207. } catch (IllegalBlockSizeException e) {
  208. throw new Exception("密文长度非法");
  209. } catch (BadPaddingException e) {
  210. throw new Exception("密文数据已损坏");
  211. }
  212. }
  213. public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
  214. throws Exception {
  215. if (publicKey == null) {
  216. throw new Exception("解密公钥为空, 请设置");
  217. }
  218. Cipher cipher = null;
  219. try {
  220. // 使用默认RSA
  221. cipher = Cipher.getInstance("RSA");
  222. // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  223. // 初始化加密算法:公钥解密
  224. cipher.init(Cipher.DECRYPT_MODE, publicKey);
  225. byte[] output = cipher.doFinal(cipherData);
  226. // 以字符数组形式存在的明文数据
  227. return output;
  228. } catch (NoSuchAlgorithmException e) {
  229. throw new Exception("无此解密算法");
  230. } catch (NoSuchPaddingException e) {
  231. e.printStackTrace();
  232. return null;
  233. } catch (InvalidKeyException e) {
  234. throw new Exception("解密公钥非法,请检查");
  235. } catch (IllegalBlockSizeException e) {
  236. throw new Exception("密文长度非法");
  237. } catch (BadPaddingException e) {
  238. throw new Exception("密文数据已损坏");
  239. }
  240. }
  241. public static String byteArrayToString(byte[] data) {
  242. StringBuilder stringBuilder = new StringBuilder();
  243. for (int i = 0; i < data.length; i++) {
  244. // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
  245. stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
  246. // 取出字节的低四位 作为索引得到相应的十六进制标识符
  247. stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
  248. if (i < data.length - 1) {
  249. stringBuilder.append(' ');
  250. }
  251. }
  252. return stringBuilder.toString();
  253. }
  254. }
复制代码


回复

使用道具 举报

8

主题

24

帖子

100

积分

注册会员

Rank: 2

积分
100
 楼主| 发表于 2022-6-2 20:54:44 | 显示全部楼层

RSASignature.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.     public static String sign(String content, String privateKey, String encode) {
  16.         try {
  17.             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));

  18.             KeyFactory keyf = KeyFactory.getInstance("RSA");
  19.             PrivateKey priKey = keyf.generatePrivate(priPKCS8);

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

  21.             signature.initSign(priKey);
  22.             signature.update(content.getBytes(encode));

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

  24.             return Base64.encode(signed);
  25.         } catch (Exception e) {
  26.             e.printStackTrace();
  27.         }

  28.         return null;
  29.     }

  30.     public static String sign(String content, String privateKey) {
  31.         try {
  32.             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
  33.             KeyFactory keyf = KeyFactory.getInstance("RSA");
  34.             PrivateKey priKey = keyf.generatePrivate(priPKCS8);
  35.             // 这里签名使用的是 SHA1WithRSA
  36.             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
  37.             // 以私钥字符串初始化签名
  38.             signature.initSign(priKey);
  39.             // 将原始串注入签名中
  40.             signature.update(content.getBytes());
  41.             // 签名后的结果,以字符数组形式存在
  42.             byte[] signed = signature.sign();
  43.             // 签名后的结果,以base64编码形式存在
  44.             return Base64.encode(signed);
  45.         } catch (Exception e) {
  46.             e.printStackTrace();
  47.         }
  48.         return null;
  49.     }

  50.     public static boolean doCheck(String content, String sign, String publicKey, String encode) {
  51.         try {
  52.             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  53.             byte[] encodedKey = Base64.decode(publicKey);
  54.             PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));


  55.             java.security.Signature signature = java.security.Signature
  56.                     .getInstance(SIGN_ALGORITHMS);

  57.             signature.initVerify(pubKey);
  58.             signature.update(content.getBytes(encode));

  59.             boolean bverify = signature.verify(Base64.decode(sign));
  60.             return bverify;

  61.         } catch (Exception e) {
  62.             e.printStackTrace();
  63.         }

  64.         return false;
  65.     }

  66.     public static boolean doCheck(String content, String sign, String publicKey) {
  67.         try {
  68.             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  69.             byte[] encodedKey = Base64.decode(publicKey);
  70.             PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
  71.             // 使用 SHA1WithRSA 签名算法
  72.             java.security.Signature signature = java.security.Signature
  73.                     .getInstance(SIGN_ALGORITHMS);
  74.             // 用公钥初始化签名校验
  75.             signature.initVerify(pubKey);
  76.             // 原始串注入签名校验中
  77.             signature.update(content.getBytes());
  78.             // 验证签名结果
  79.             boolean bverify = signature.verify(Base64.decode(sign));
  80.             // 返回签名是否成功
  81.             return bverify;
  82.         } catch (Exception e) {
  83.             e.printStackTrace();
  84.         }
  85.         return false;
  86.     }
  87. }
复制代码


回复

使用道具 举报

8

主题

24

帖子

100

积分

注册会员

Rank: 2

积分
100
 楼主| 发表于 2022-6-2 21:06:24 | 显示全部楼层
本帖最后由 徐柳婧 于 2022-6-2 23:51 编辑

ECC-椭圆曲线加密算法

一、算法简介
椭圆加密算法(ECC)是一种公钥加密体制,最初由Koblitz和Miller两人于1985年提出,其数学基础是利用椭圆曲线上的有理点构成Abel加法群上椭圆离散对数的计算困难性。公钥密码体制根据其所依据的难题一般分为三类:大素数分解问题类、离散对数问题类、椭圆曲线类。有时也把椭圆曲线类归为离散对数类。
ECC的主要优势是在某些情况下它比其他的方法使用更小的密钥——比如RSA加密算法——提供相当的或更高等级的安全。ECC的另一个优势是可以定义群之间的双线性映射,基于Weil对或是Tate对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。
ECC是基于椭圆曲线数学理论实现的一种非对称加密算法。 相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全,RSA加密算法也是一种非对称加密算法,在公开密钥加密和电子商业中RSA被广泛使用。 据研究,160位ECC加密安全性相当于1024位RSA加密,210位ECC加密安全性相当于2048位RSA加密。
二、基本原理
设私钥、公钥分别为d、Q,即Q = dG,其中G为基点,椭圆曲线上的已知G和dG,求d是非常困难的,也就是说已知公钥和基点,想要算出私钥是非常困难的。
公钥加密:选择随机数r,将消息M生成密文C,该密文是一个点对,C = {rG, M+rQ},其中Q为公钥。
私钥解密:M + rQ - d(rG) = M + r(dG) - d(rG) = M,其中d、Q分别为私钥、公钥。



回复

使用道具 举报

8

主题

24

帖子

100

积分

注册会员

Rank: 2

积分
100
 楼主| 发表于 2022-6-2 21:07:49 | 显示全部楼层
本帖最后由 徐柳婧 于 2022-6-2 23:43 编辑

徐柳婧 发表于 2022-6-2 21:06
  1. #include “stdafx.h”
  2. #include <弦>
  3. #include <iostream>
  4. 使用命名空间标准;
  5. const int k = 9;
  6. const int a = 5;
  7. const int b = 37;
  8. const int p = 127;
  9. const int r =7;

  10. int getX_1(int x,int mod){
  11. 国际 Q,X1,X2,X3,Y1,Y2,Y3,T1,T2,T3;
  12. X1 = 1;
  13. X2 = 0;
  14. X3 = mod;
  15. Y1 = 0;
  16. Y2 = 1;
  17. Y3 = (x%mod + mod) %mod;//获得正整数
  18. 而(Y3 != 1){
  19. Q = X3 / Y3;
  20. T1 = X1 - Q * Y1;
  21. T2 = X2 - Q * Y2;
  22. T3 = X3 - Q * Y3;
  23. X1 = Y1;
  24. X2 = Y2;
  25. X3 = Y3;
  26. Y1 = T1;
  27. Y2 = T2;
  28. Y3 = T3;
  29.         }
  30. 返回 Y2;
  31. }//获得其乘法逆元

  32. 结构点{
  33. 整型 x;
  34. int y;
  35. };
  36. A点,B点;//公钥
  37. 类型定义对<点,点>两点;
  38. bool operator == (point pa,point pb){
  39. return pa.x == pb.x && pa.y == pb.y;
  40. }
  41. 点运算符 + (点 pa , 点 pb){
  42. 整型 k;
  43.         
  44. if(pa == pb)
  45. k = ((3 * pa.x * pa.x + a) * getX_1(2* pa.y ,p)) % p ;

  46. k = (pb.y - pa.y) * getX_1(pb.x - pa.x , p) %p;
  47. c点;
  48. c.x = (k*k - pa.x -pb.x) %p;
  49. c.y = (k * (pa.x - c.x) - pa.y)%p ;
  50. c.x = (c.x + p) %p;
  51. c.y = (c.y + p) %p;
  52.                
  53. 返回 c;
  54. }
  55. 点运算符 * (点 &b,int n){
  56. 点 q = b;
  57. n = n -1;
  58. for(int i = 1 ; i < n;i++){
  59. q = q + b ;
  60.                 }
  61. 返回 q;
  62. }
  63. 两点 ECodePoint(point m){
  64. 点 c1,c2;
  65. c1 = A * r ;
  66. 点 Y = B * r ;
  67. c2.x = Y.x * m.x % p ;
  68. c2.y = Y.y * m.y % p ;
  69. 返回两点(c1,c2);
  70. }
  71. 点 DCodePoint(两点 t){
  72. 点 Z = t.first * k;
  73. 点 m;
  74. m.x = t.second.x * getX_1(Z.x,p) % p ;
  75. m.y = t.second.y * getX_1(Z.y,p) % p ;
  76. 返回 m;
  77. }
  78. 字符串代码(字符串输入){
  79. 字符串输出 = “”;
  80. M点;
  81. 两点 C;
  82. for(int i =0; i < input.length();i++){
  83. M.x = i;
  84. M.y = 输入[i];
  85. C = ECodePoint(M);
  86. 输出 += (字符)C.first.x ;
  87. 输出 += (字符)C.first.y ;
  88. 输出 += (字符)C.second.x ;
  89. 输出 += (字符)C.second.y ;
  90.         }
  91. 返回输出;
  92. }
  93. 字符串 DCode(字符串输入){
  94. 字符串输出 = “”;
  95. M点;
  96. 两点 C;
  97. if(input.length()%4 != 0)
  98. 返回 “错误输入”;
  99. for(int i = 0;i < input.length();){
  100. C.first.x = input[i++];
  101. C.first.y = input[i++];
  102. C.second.x = input[i++];
  103. C.second.y = input[i++];
  104. M = DCodePoint(C);
  105. 输出 += (字符)M.y;
  106.         }
  107. 返回输出;
  108. }
  109. int main()
  110. {
  111. A.x = 11;
  112. A.y = 4;
  113. B = A*k;
  114. 字符串 s = “”;
  115. cout<<“使用在素域上的曲线 y^2 = x^3 + 5*x +37 ,使用Menezes-Vanstone的算法:”<<endl;
  116. cout<<“在素域p=127上,私钥为k=9,公钥A(11,4),B(120,41),对明文字符串直接转换为int进行加密”<<endl;
  117. cout<<“请输入要加密的内容:”<<endl;
  118. 辛>>斯;
  119. cout<<“密文如下:”<<“\r\n”;
  120. s = ECode(s);
  121. cout<<s<<endl;
  122. cout<<“对之前密文解密,得到明文如下(由于输入密文不正确绝对会使这个程序出错,所以只能解密绝对安全的密文):”<<“\r\n”;
  123. s = DCode(s);
  124. cout<<s<<“\r\n”<<“完成”<<endl;
  125. 辛>>斯;
  126. 返回 0;
  127. }
复制代码

回复

使用道具 举报

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

本版积分规则

教学服务系统

GMT+8, 2025-4-30 01:28 , Processed in 0.020486 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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