<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      1、SM2簡述

        RSA算法的危機在于其存在亞指數算法,對ECC算法而言一般沒有亞指數攻擊算法。

        SM2橢圓曲線公鑰密碼算法:我國自主知識產權的商用密碼算法,是ECC(Elliptic Curve Cryptosystem)算法的一種,基于橢圓曲線離散對數問題,計算復雜度是指數級,求解難度較大,同等安全程度要求下,橢圓曲線密碼較其他公鑰算法所需密鑰長度小很多。

        ECC算法描述:

      • 用戶A選定一條適合加密的橢圓曲線Ep(a,b)(如:y2=x3+ax+b),并取橢圓曲線上一點,作為基點G。
      • 用戶A選擇一個私有密鑰k,并生成公開密鑰(公鑰PB)K=kG。
      • 用戶A將Ep(a,b)和點(公鑰)K,G傳給用戶B。
      • 用戶B接到信息后 ,將待傳輸的明文(M)編碼到Ep(a,b)上一點M,并產生一個隨機整數r(r<n)。加密開始
      • 用戶B計算點C1=M+rK;C2=rG。
      • 用戶B將C1、C2傳給用戶A。
      • 用戶A接到信息后,計算C1-kC2,結果就是點M。因為C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M

        再對點M進行解碼就可以得到明文。

        密碼學中,描述一條Fp上的橢圓曲線,常用到六個參量:T=(p,a,b,G,n,h)。
        (p 、a 、b 用來確定一條橢圓曲線,G為基點,n為點G的階,h 是橢圓曲線上所有點的個數m與n相除的整數部分)

        這幾個參量取值的選擇,直接影響了加密的安全性。參量值一般要求滿足以下幾個條件:

      • p 當然越大越安全,但越大,計算速度會變慢,200位左右可以滿足一般安全要求;
      • p≠n×h;
      • pt≠1 (mod n),1≤t<20;
      • 4a3+27b2≠0 (mod p);
      • n 為素數;
      • h≤4。

      2、前后端代碼示例

        1、Maven依賴

      <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
      <dependency>
          <groupId>org.bouncycastle</groupId>
          <artifactId>bcprov-jdk15on</artifactId>
          <version>1.56</version>
      </dependency>

        2、工具類Util

      import java.math.BigInteger;
      
      public class Util {
          /**
           * 整形轉換成網絡傳輸的字節流(字節數組)型數據
           *
           * @param num 一個整型數據
           * @return 4個字節的自己數組
           */
          public static byte[] intToBytes(int num) {
              byte[] bytes = new byte[4];
              bytes[0] = (byte) (0xff & (num >> 0));
              bytes[1] = (byte) (0xff & (num >> 8));
              bytes[2] = (byte) (0xff & (num >> 16));
              bytes[3] = (byte) (0xff & (num >> 24));
              return bytes;
          }
      
          /**
           * 四個字節的字節數據轉換成一個整形數據
           *
           * @param bytes 4個字節的字節數組
           * @return 一個整型數據
           */
          public static int byteToInt(byte[] bytes) {
              int num = 0;
              int temp;
              temp = (0x000000ff & (bytes[0])) << 0;
              num = num | temp;
              temp = (0x000000ff & (bytes[1])) << 8;
              num = num | temp;
              temp = (0x000000ff & (bytes[2])) << 16;
              num = num | temp;
              temp = (0x000000ff & (bytes[3])) << 24;
              num = num | temp;
              return num;
          }
      
          /**
           * 長整形轉換成網絡傳輸的字節流(字節數組)型數據
           *
           * @param num 一個長整型數據
           * @return 4個字節的自己數組
           */
          public static byte[] longToBytes(long num) {
              byte[] bytes = new byte[8];
              for (int i = 0; i < 8; i++) {
                  bytes[i] = (byte) (0xff & (num >> (i * 8)));
              }
      
              return bytes;
          }
      
          /**
           * 大數字轉換字節流(字節數組)型數據
           *
           * @param n
           * @return
           */
          public static byte[] byteConvert32Bytes(BigInteger n) {
              byte tmpd[] = (byte[]) null;
              if (n == null) {
                  return null;
              }
      
              if (n.toByteArray().length == 33) {
                  tmpd = new byte[32];
                  System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);
              } else if (n.toByteArray().length == 32) {
                  tmpd = n.toByteArray();
              } else {
                  tmpd = new byte[32];
                  for (int i = 0; i < 32 - n.toByteArray().length; i++) {
                      tmpd[i] = 0;
                  }
                  System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);
              }
              return tmpd;
          }
      
          /**
           * 換字節流(字節數組)型數據轉大數字
           *
           * @param b
           * @return
           */
          public static BigInteger byteConvertInteger(byte[] b) {
              if (b[0] < 0) {
                  byte[] temp = new byte[b.length + 1];
                  temp[0] = 0;
                  System.arraycopy(b, 0, temp, 1, b.length);
                  return new BigInteger(temp);
              }
              return new BigInteger(b);
          }
      
          /**
           * 根據字節數組獲得值(十六進制數字)
           *
           * @param bytes
           * @return
           */
          public static String getHexString(byte[] bytes) {
              return getHexString(bytes, true);
          }
      
          /**
           * 根據字節數組獲得值(十六進制數字)
           *
           * @param bytes
           * @param upperCase
           * @return
           */
          public static String getHexString(byte[] bytes, boolean upperCase) {
              String ret = "";
              for (int i = 0; i < bytes.length; i++) {
                  ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
              }
              return upperCase ? ret.toUpperCase() : ret;
          }
      
          /**
           * 打印十六進制字符串
           *
           * @param bytes
           */
          public static void printHexString(byte[] bytes) {
              for (int i = 0; i < bytes.length; i++) {
                  String hex = Integer.toHexString(bytes[i] & 0xFF);
                  if (hex.length() == 1) {
                      hex = '0' + hex;
                  }
                  System.out.print("0x" + hex.toUpperCase() + ",");
              }
              System.out.println("");
          }
      
          /**
           * Convert hex string to byte[]
           *
           * @param hexString the hex string
           * @return byte[]
           */
          public static byte[] hexStringToBytes(String hexString) {
              if (hexString == null || hexString.equals("")) {
                  return null;
              }
      
              hexString = hexString.toUpperCase();
              int length = hexString.length() / 2;
              char[] hexChars = hexString.toCharArray();
              byte[] d = new byte[length];
              for (int i = 0; i < length; i++) {
                  int pos = i * 2;
                  d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
              }
              return d;
          }
      
          /**
           * Convert char to byte
           *
           * @param c char
           * @return byte
           */
          public static byte charToByte(char c) {
              return (byte) "0123456789ABCDEF".indexOf(c);
          }
      
          /**
           * 用于建立十六進制字符的輸出的小寫字符數組
           */
          private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
                  '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
      
          /**
           * 用于建立十六進制字符的輸出的大寫字符數組
           */
          private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
                  '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
      
          /**
           * 將字節數組轉換為十六進制字符數組
           *
           * @param data byte[]
           * @return 十六進制char[]
           */
          public static char[] encodeHex(byte[] data) {
              return encodeHex(data, true);
          }
      
          /**
           * 將字節數組轉換為十六進制字符數組
           *
           * @param data        byte[]
           * @param toLowerCase <code>true</code> 傳換成小寫格式 , <code>false</code> 傳換成大寫格式
           * @return 十六進制char[]
           */
          public static char[] encodeHex(byte[] data, boolean toLowerCase) {
              return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
          }
      
          /**
           * 將字節數組轉換為十六進制字符數組
           *
           * @param data     byte[]
           * @param toDigits 用于控制輸出的char[]
           * @return 十六進制char[]
           */
          protected static char[] encodeHex(byte[] data, char[] toDigits) {
              int l = data.length;
              char[] out = new char[l << 1];
              // two characters form the hex value.
              for (int i = 0, j = 0; i < l; i++) {
                  out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
                  out[j++] = toDigits[0x0F & data[i]];
              }
              return out;
          }
      
          /**
           * 將字節數組轉換為十六進制字符串
           *
           * @param data byte[]
           * @return 十六進制String
           */
          public static String encodeHexString(byte[] data) {
              return encodeHexString(data, true);
          }
      
          /**
           * 將字節數組轉換為十六進制字符串
           *
           * @param data        byte[]
           * @param toLowerCase <code>true</code> 傳換成小寫格式 , <code>false</code> 傳換成大寫格式
           * @return 十六進制String
           */
          public static String encodeHexString(byte[] data, boolean toLowerCase) {
              return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
          }
      
          /**
           * 將字節數組轉換為十六進制字符串
           *
           * @param data     byte[]
           * @param toDigits 用于控制輸出的char[]
           * @return 十六進制String
           */
          protected static String encodeHexString(byte[] data, char[] toDigits) {
              return new String(encodeHex(data, toDigits));
          }
      
          /**
           * 將十六進制字符數組轉換為字節數組
           *
           * @param data 十六進制char[]
           * @return byte[]
           * @throws RuntimeException 如果源十六進制字符數組是一個奇怪的長度,將拋出運行時異常
           */
          public static byte[] decodeHex(char[] data) {
              int len = data.length;
      
              if ((len & 0x01) != 0) {
                  throw new RuntimeException("Odd number of characters.");
              }
      
              byte[] out = new byte[len >> 1];
      
              // two characters form the hex value.
              for (int i = 0, j = 0; j < len; i++) {
                  int f = toDigit(data[j], j) << 4;
                  j++;
                  f = f | toDigit(data[j], j);
                  j++;
                  out[i] = (byte) (f & 0xFF);
              }
      
              return out;
          }
      
          /**
           * 將十六進制字符轉換成一個整數
           *
           * @param ch    十六進制char
           * @param index 十六進制字符在字符數組中的位置
           * @return 一個整數
           * @throws RuntimeException 當ch不是一個合法的十六進制字符時,拋出運行時異常
           */
          protected static int toDigit(char ch, int index) {
              int digit = Character.digit(ch, 16);
              if (digit == -1) {
                  throw new RuntimeException("Illegal hexadecimal character " + ch
                          + " at index " + index);
              }
              return digit;
          }
      
          /**
           * 數字字符串轉ASCII碼字符串
           *
           * @param content 字符串
           * @return ASCII字符串
           */
          public static String StringToAsciiString(String content) {
              String result = "";
              int max = content.length();
              for (int i = 0; i < max; i++) {
                  char c = content.charAt(i);
                  String b = Integer.toHexString(c);
                  result = result + b;
              }
              return result;
          }
      
          /**
           * 十六進制轉字符串
           *
           * @param hexString  十六進制字符串
           * @param encodeType 編碼類型4:Unicode,2:普通編碼
           * @return 字符串
           */
          public static String hexStringToString(String hexString, int encodeType) {
              String result = "";
              int max = hexString.length() / encodeType;
              for (int i = 0; i < max; i++) {
                  char c = (char) hexStringToAlgorism(hexString
                          .substring(i * encodeType, (i + 1) * encodeType));
                  result += c;
              }
              return result;
          }
      
          /**
           * 十六進制字符串裝十進制
           *
           * @param hex 十六進制字符串
           * @return 十進制數值
           */
          public static int hexStringToAlgorism(String hex) {
              hex = hex.toUpperCase();
              int max = hex.length();
              int result = 0;
              for (int i = max; i > 0; i--) {
                  char c = hex.charAt(i - 1);
                  int algorism = 0;
                  if (c >= '0' && c <= '9') {
                      algorism = c - '0';
                  } else {
                      algorism = c - 55;
                  }
                  result += Math.pow(16, max - i) * algorism;
              }
              return result;
          }
      
          /**
           * 十六轉二進制
           *
           * @param hex 十六進制字符串
           * @return 二進制字符串
           */
          public static String hexStringToBinary(String hex) {
              hex = hex.toUpperCase();
              String result = "";
              int max = hex.length();
              for (int i = 0; i < max; i++) {
                  char c = hex.charAt(i);
                  switch (c) {
                      case '0':
                          result += "0000";
                          break;
                      case '1':
                          result += "0001";
                          break;
                      case '2':
                          result += "0010";
                          break;
                      case '3':
                          result += "0011";
                          break;
                      case '4':
                          result += "0100";
                          break;
                      case '5':
                          result += "0101";
                          break;
                      case '6':
                          result += "0110";
                          break;
                      case '7':
                          result += "0111";
                          break;
                      case '8':
                          result += "1000";
                          break;
                      case '9':
                          result += "1001";
                          break;
                      case 'A':
                          result += "1010";
                          break;
                      case 'B':
                          result += "1011";
                          break;
                      case 'C':
                          result += "1100";
                          break;
                      case 'D':
                          result += "1101";
                          break;
                      case 'E':
                          result += "1110";
                          break;
                      case 'F':
                          result += "1111";
                          break;
                  }
              }
              return result;
          }
      
          /**
           * ASCII碼字符串轉數字字符串
           *
           * @param content ASCII字符串
           * @return 字符串
           */
          public static String AsciiStringToString(String content) {
              String result = "";
              int length = content.length() / 2;
              for (int i = 0; i < length; i++) {
                  String c = content.substring(i * 2, i * 2 + 2);
                  int a = hexStringToAlgorism(c);
                  char b = (char) a;
                  String d = String.valueOf(b);
                  result += d;
              }
              return result;
          }
      
          /**
           * 將十進制轉換為指定長度的十六進制字符串
           *
           * @param algorism  int 十進制數字
           * @param maxLength int 轉換后的十六進制字符串長度
           * @return String 轉換后的十六進制字符串
           */
          public static String algorismToHexString(int algorism, int maxLength) {
              String result = "";
              result = Integer.toHexString(algorism);
      
              if (result.length() % 2 == 1) {
                  result = "0" + result;
              }
              return patchHexString(result.toUpperCase(), maxLength);
          }
      
          /**
           * 字節數組轉為普通字符串(ASCII對應的字符)
           *
           * @param bytearray byte[]
           * @return String
           */
          public static String byteToString(byte[] bytearray) {
              String result = "";
              char temp;
      
              int length = bytearray.length;
              for (int i = 0; i < length; i++) {
                  temp = (char) bytearray[i];
                  result += temp;
              }
              return result;
          }
      
          /**
           * 二進制字符串轉十進制
           *
           * @param binary 二進制字符串
           * @return 十進制數值
           */
          public static int binaryToAlgorism(String binary) {
              int max = binary.length();
              int result = 0;
              for (int i = max; i > 0; i--) {
                  char c = binary.charAt(i - 1);
                  int algorism = c - '0';
                  result += Math.pow(2, max - i) * algorism;
              }
              return result;
          }
      
          /**
           * 十進制轉換為十六進制字符串
           *
           * @param algorism int 十進制的數字
           * @return String 對應的十六進制字符串
           */
          public static String algorismToHEXString(int algorism) {
              String result = "";
              result = Integer.toHexString(algorism);
      
              if (result.length() % 2 == 1) {
                  result = "0" + result;
      
              }
              result = result.toUpperCase();
      
              return result;
          }
      
          /**
           * HEX字符串前補0,主要用于長度位數不足。
           *
           * @param str       String 需要補充長度的十六進制字符串
           * @param maxLength int 補充后十六進制字符串的長度
           * @return 補充結果
           */
          static public String patchHexString(String str, int maxLength) {
              String temp = "";
              for (int i = 0; i < maxLength - str.length(); i++) {
                  temp = "0" + temp;
              }
              str = (temp + str).substring(0, maxLength);
              return str;
          }
      
          /**
           * 將一個字符串轉換為int
           *
           * @param s          String 要轉換的字符串
           * @param defaultInt int 如果出現異常,默認返回的數字
           * @param radix      int 要轉換的字符串是什么進制的,如16 8 10.
           * @return int 轉換后的數字
           */
          public static int parseToInt(String s, int defaultInt, int radix) {
              int i = 0;
              try {
                  i = Integer.parseInt(s, radix);
              } catch (NumberFormatException ex) {
                  i = defaultInt;
              }
              return i;
          }
      
          /**
           * 將一個十進制形式的數字字符串轉換為int
           *
           * @param s          String 要轉換的字符串
           * @param defaultInt int 如果出現異常,默認返回的數字
           * @return int 轉換后的數字
           */
          public static int parseToInt(String s, int defaultInt) {
              int i = 0;
              try {
                  i = Integer.parseInt(s);
              } catch (NumberFormatException ex) {
                  i = defaultInt;
              }
              return i;
          }
      
          /**
           * 十六進制串轉化為byte數組
           *
           * @return the array of byte
           */
          public static byte[] hexToByte(String hex)
                  throws IllegalArgumentException {
              if (hex.length() % 2 != 0) {
                  throw new IllegalArgumentException();
              }
              if (hex.length() < 1) {
                  return null;
              } else {
                  byte[] result = new byte[hex.length() / 2];
                  int j = 0;
                  for(int i = 0; i < hex.length(); i+=2) {
                      result[j++] = (byte)Integer.parseInt(hex.substring(i,i+2), 16);
                  }
                  return result;
              }
          }
      
          /**
           * 字節數組轉換為十六進制字符串
           *
           * @param b byte[] 需要轉換的字節數組
           * @return String 十六進制字符串
           */
          public static String byteToHex(byte b[]) {
              if (b == null) {
                  return "";
              }
              StringBuffer sb = new StringBuffer();
              for(int i = 0; i < b.length; i++) {
                  String hex = Integer.toHexString(b[i] & 0xFF);
                  if(hex.length() < 2) {
                      hex = "0" + hex;
                  }
                  sb.append(hex.toUpperCase());
              }
              return sb.toString();
          }
      
          public static byte[] subByte(byte[] input, int startIndex, int length) {
              byte[] bt = new byte[length];
              for (int i = 0; i < length; i++) {
                  bt[i] = input[i + startIndex];
              }
              return bt;
          }
      }

        3、參數類SM2

      import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
      import org.bouncycastle.crypto.params.ECDomainParameters;
      import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
      import org.bouncycastle.math.ec.ECCurve;
      import org.bouncycastle.math.ec.ECFieldElement;
      import org.bouncycastle.math.ec.ECFieldElement.Fp;
      import org.bouncycastle.math.ec.ECPoint;
      
      import java.math.BigInteger;
      import java.security.SecureRandom;
      
      public class SM2 {
      
          //國密參數
          public static String[] ecc_param = {
                  "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
                  "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
                  "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
                  "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
                  "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
                  "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
          };
      
          public static SM2 Instance() {
              return new SM2();
          }
      
          /** 素數p */
          public final BigInteger ecc_p;
          /** 系數a */
          public final BigInteger ecc_a;
          /** 系數b */
          public final BigInteger ecc_b;
          /** 基點G, G=(xg,yg),其介記為n */
          public final BigInteger ecc_n;
          /** 坐標x */
          public final BigInteger ecc_gx;
          /** 坐標y */
          public final BigInteger ecc_gy;
          public final ECCurve ecc_curve;
          public final ECPoint ecc_point_g;
          public final ECDomainParameters ecc_bc_spec;
          public final ECKeyPairGenerator ecc_key_pair_generator;
          public final ECFieldElement ecc_gx_fieldelement;
          public final ECFieldElement ecc_gy_fieldelement;
      
          public SM2() {
              this.ecc_p = new BigInteger(ecc_param[0], 16);
              this.ecc_a = new BigInteger(ecc_param[1], 16);
              this.ecc_b = new BigInteger(ecc_param[2], 16);
              this.ecc_n = new BigInteger(ecc_param[3], 16);
              this.ecc_gx = new BigInteger(ecc_param[4], 16);
              this.ecc_gy = new BigInteger(ecc_param[5], 16);
      
              this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);
              this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);
      
              this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);
              this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);
      
              this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);
      
              ECKeyGenerationParameters ecc_ecgenparam;
              ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
      
              this.ecc_key_pair_generator = new ECKeyPairGenerator();
              this.ecc_key_pair_generator.init(ecc_ecgenparam);
          }
      }

        4、Cipher

      import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
      import org.bouncycastle.crypto.digests.SM3Digest;
      import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
      import org.bouncycastle.crypto.params.ECPublicKeyParameters;
      import org.bouncycastle.math.ec.ECPoint;
      
      import java.math.BigInteger;
      
      public class Cipher {
          private int ct;
          private ECPoint p2;
          private SM3Digest sm3keybase;
          private SM3Digest sm3c3;
          private byte key[];
          private byte keyOff;
      
          public Cipher()
          {
              this.ct = 1;
              this.key = new byte[32];
              this.keyOff = 0;
          }
      
          private void Reset()
          {
              this.sm3keybase = new SM3Digest();
              this.sm3c3 = new SM3Digest();
      
              byte p[] = Util.byteConvert32Bytes(p2.getX().toBigInteger());
              this.sm3keybase.update(p, 0, p.length);
              this.sm3c3.update(p, 0, p.length);
      
              p = Util.byteConvert32Bytes(p2.getY().toBigInteger());
              this.sm3keybase.update(p, 0, p.length);
              this.ct = 1;
              NextKey();
          }
      
          private void NextKey()
          {
              SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
              sm3keycur.update((byte) (ct >> 24 & 0xff));
              sm3keycur.update((byte) (ct >> 16 & 0xff));
              sm3keycur.update((byte) (ct >> 8 & 0xff));
              sm3keycur.update((byte) (ct & 0xff));
              sm3keycur.doFinal(key, 0);
              this.keyOff = 0;
              this.ct++;
          }
      
          public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
          {
              AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
              ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
              ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
              BigInteger k = ecpriv.getD();
              ECPoint c1 = ecpub.getQ();
              this.p2 = userKey.multiply(k);
              Reset();
              return c1;
          }
      
          public void Encrypt(byte data[])
          {
              this.sm3c3.update(data, 0, data.length);
              for (int i = 0; i < data.length; i++)
              {
                  if (keyOff == key.length)
                  {
                      NextKey();
                  }
                  data[i] ^= key[keyOff++];
              }
          }
      
          public void Init_dec(BigInteger userD, ECPoint c1)
          {
              this.p2 = c1.multiply(userD);
              Reset();
          }
      
          public void Decrypt(byte data[])
          {
              for (int i = 0; i < data.length; i++)
              {
                  if (keyOff == key.length)
                  {
                      NextKey();
                  }
                  data[i] ^= key[keyOff++];
              }
      
              this.sm3c3.update(data, 0, data.length);
          }
      
          public void Dofinal(byte c3[])
          {
              byte p[] = Util.byteConvert32Bytes(p2.getY().toBigInteger());
              this.sm3c3.update(p, 0, p.length);
              this.sm3c3.doFinal(c3, 0);
              Reset();
          }
      }

        5、功能類SM2EncDecUtils

      import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
      import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
      import org.bouncycastle.crypto.params.ECPublicKeyParameters;
      import org.bouncycastle.math.ec.ECPoint;
      
      import java.io.IOException;
      import java.math.BigInteger;
      import java.util.HashMap;
      import java.util.Map;
      
      public class SM2EncDecUtils {
      
          public static final String public_key = "public_key";
          public static final String private_key = "private_key";
      
          // 生成隨機秘鑰對
          public static Map<String, String> generateKeyPair() {
              SM2 sm2 = SM2.Instance();
              AsymmetricCipherKeyPair key = null;
              while (true) {
                  key = sm2.ecc_key_pair_generator.generateKeyPair();
                  if (((ECPrivateKeyParameters) key.getPrivate()).getD().toByteArray().length == 32) {
                      break;
                  }
              }
              ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
              ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
              BigInteger privateKey = ecpriv.getD();
              ECPoint publicKey = ecpub.getQ();
              String pubk = Util.byteToHex(publicKey.getEncoded());
              String prik = Util.byteToHex(privateKey.toByteArray());
              System.out.println("公鑰: " + pubk);
              System.out.println("私鑰: " + prik);
              Map<String, String> result = new HashMap<>();
      
              result.put(public_key, pubk);
              result.put(private_key, prik);
      
              return result;
          }
      
          // 數據加密
          public static String encrypt(byte[] publicKey, byte[] data) throws IOException {
              if (publicKey == null || publicKey.length == 0) {
                  return null;
              }
      
              if (data == null || data.length == 0) {
                  return null;
              }
      
              byte[] source = new byte[data.length];
              System.arraycopy(data, 0, source, 0, data.length);
              Cipher cipher = new Cipher();
              SM2 sm2 = SM2.Instance();
              ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
              ECPoint c1 = cipher.Init_enc(sm2, userKey);
              cipher.Encrypt(source);
              byte[] c3 = new byte[32];
              cipher.Dofinal(c3);
              return new StringBuffer(Util.byteToHex(c1.getEncoded())).append(Util.byteToHex(c3)).append(Util.byteToHex(source)).toString();
          }
      
          // 數據解密
          public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException {
              if (privateKey == null || privateKey.length == 0) {
                  return null;
              }
      
              if (encryptedData == null || encryptedData.length == 0) {
                  return null;
              }
              // 加密字節數組轉換為十六進制的字符串 長度變為encryptedData.length * 2
              String data = Util.byteToHex(encryptedData);
      
              byte[] c1Bytes = Util.hexToByte(data.substring(0, 130));
              int c2Len = encryptedData.length - 97;
              byte[] c3 = Util.hexToByte(data.substring(130, 130 + 64));
              byte[] c2 = Util.hexToByte(data.substring(194, 194 + 2 * c2Len));
      
              SM2 sm2 = SM2.Instance();
              BigInteger userD = new BigInteger(1, privateKey);
      
              // 通過C1實體字節來生成ECPoint
              ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
              Cipher cipher = new Cipher();
              cipher.Init_dec(userD, c1);
              cipher.Decrypt(c2);
              cipher.Dofinal(c3);
      
              // 返回解密結果
              return c2;
          }
      
          public static void main(String[] args) throws Exception {
      
              singleThreadTest();
      //        mutiThreadTest();
          }
      
          private static void singleThreadTest() throws Exception {
              String plainText = "sourceText";
              byte[] sourceData = plainText.getBytes();
              Map<String, String> keymap = generateKeyPair();
      
              long start = System.currentTimeMillis();
              int counts = 100;
              for (int j = 0; j < counts; j++) {
                  String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(keymap.get(public_key)), sourceData);
                  System.out.println("加密前長度: " + plainText.length() + ";加密后長度: " + cipherText.length());
                  String plainTextEncripted = new String(SM2EncDecUtils.decrypt(Util.hexToByte(keymap.get(private_key)), Util.hexToByte(cipherText)));
                  if (plainText.equals(plainTextEncripted)) {
                      System.out.println("------解密后同原文是否一致: " + plainText.equals(plainTextEncripted) + "----------------------");
                  }
              }
              long end = System.currentTimeMillis();
              System.out.println("平均耗時:" + (end - start) / counts + "ms。");
          }
      
          private static void mutiThreadTest() {
              String plainText = "sourceText";
              byte[] sourceData = plainText.getBytes();
      
              Map<String, String> keymap = generateKeyPair();
              int counts = 10;
              for (int i = 0; i < counts; i++) {
                  new Thread(() -> {
                      try {
                          for (int j = 0; j < counts; j++) {
                              String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(keymap.get(public_key)), sourceData);
                              if (!plainText.equals(new String(SM2EncDecUtils.decrypt(Util.hexToByte(keymap.get(private_key)), Util.hexToByte(cipherText))))) {
                                  System.out.println("------解密后同原文不一致:" + Thread.currentThread().getName() + "--------------");
                              }
                          }
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                      System.out.println(" --------------->線程" + Thread.currentThread().getName() + "執行完成.---------------------");
                  }
                  ).start();
              }
          }
      }

        6、測試

        測試結果如下:

      公鑰: 04D4BDF1A660C728418D685A702C5E16EAA2463471BC23107CBDBBB4AD7AF526F88E89EBC7D3075D826F8323657858A351A709423B18A685CDAD141E671C32E8D4
      私鑰: 0AC55910CF19346F35324577E7F3F0C544A7823B154B756D63160FD1167992B2
      
      加密前長度: 10,明文為: sourceText
      加密后長度: 214,加密后密文為: 0408F3F31B4B19D7C9E655A7711F3901B908EFA8C38F9F06B1B43622D01657B6BED9A7F61DF01DDFF91DDB82C69004C910E70550A982FEDBD87839756F035E8EA653DEAEAB58D35696A16A10BC943CF98776ECEB4DF81823B535A3DDEA71FF46932677EECB2A98077617B5
      ------解密后同原文是否一致: true----------------------
      
      加密前長度: 10,明文為: sourceText
      加密后長度: 214,加密后密文為: 04788D945B48902DF9C3D445849A97E86C37E65F6A9E1B3A126DD4942CF0545EE485401EF0F240B7F7CEE69926E42C7697F1064349594E29C7A715F5BC0CE3968B959DB64D0AB53F9CC692ED97E32FBB3CE579AB31B4116F40A8BF380A3B8BB550A525ED92E3233B457336
      ------解密后同原文是否一致: true----------------------
      平均耗時:22ms。

        可以看出加密長度每次是穩定的,但是加密后密文是不一樣的,但是解密后結果都是一樣的。

        7、VUE代碼

      const sm2 = require('sm-crypto').sm2
      const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默認為1
      const publicKey = "04D4BDF1A660C728418D685A702C5E16EAA2463471BC23107CBDBBB4AD7AF526F88E89EBC7D3075D826F8323657858A351A709423B18A685CDAD141E671C32E8D4"
       
      // 加密
      export function encrypt(txt) {
          let encryptData = sm2.doEncrypt(txt, publicKey, 1) // 加密結果
          return '04' + encryptData;
      }

        注意:最關鍵的是VUE加密完的密文要加“04”,后端解密才能成功,否則后端解密16進制字符串轉字節數組的時候會有問題;

        同理后端加密的密文要刪除開頭的“04”,VUE才能解密成功。通過上面測試結果可以看出密文是以“04”開頭的。

      posted on 2021-06-22 20:10  kosamino  閱讀(7447)  評論(7)    收藏  舉報

      主站蜘蛛池模板: 亚洲一区二区精品偷拍| 亚洲精品无码久久毛片| 不卡乱辈伦在线看中文字幕| 亚洲熟妇av一区二区三区宅男| 亚洲精品自产拍在线观看动漫| 日本喷奶水中文字幕视频| 日本阿v片在线播放免费| 丰满人妻无码∧v区视频| 国产又黄又爽又不遮挡视频| 亚洲欧洲成人a∨在线| 国产精品爆乳在线播放第一人称| 女人张开腿无遮无挡视频| 可以在线观看的亚洲视频| 于田县| 人妻在线无码一区二区三区| 久久人妻无码一区二区三区av| 奇米四色7777中文字幕| 免费大黄网站在线观看| 99国产欧美另类久久久精品| 无码福利写真片视频在线播放| 波多野结衣av高清一区二区三区 | 成人午夜国产内射主播| 亚洲精品一区二区三区不| 97欧美精品系列一区二区| 涟水县| 国产精品露脸视频观看| 国内精品伊人久久久久AV一坑| 亚洲蜜臀av乱码久久| 国产成人精品无人区一区| 成人中文在线| 免费人成再在线观看视频| 精品一区二区中文字幕| 国产av午夜精品福利| 日韩人妻av一区二区三区| √天堂资源网最新版在线| 九九热爱视频精品视频| 免费无码AV一区二区波多野结衣| 武功县| 四虎影院176| 亚洲成a人无码av波多野| 色欲综合久久中文字幕网|