1. What is SM2?
The SM2 algorithm is a more advanced and secure algorithm that is used to replace the RSA algorithm in our country's commercial cryptography system.
2. Use steps
1. Introduce the Maven library
The code is as follows (example):
<!--National Secret--> <dependency> <groupId></groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.56</version> </dependency>
2. Password tool category
The code is as follows (example):
/** * @author weis * @version 1.0.0 * @ClassName * @Description Password Tool Class * @createTime October 28, 2018 14:29:00 */ public class Cipher { private int ct; private ECPoint p2; private Sm3Digest sm3keybase; private Sm3Digest sm3c3; private byte key[]; private byte keyOff; public Cipher() { = 1; = new byte[32]; = 0; } private void reset() { this.sm3keybase = new Sm3Digest(); this.sm3c3 = new Sm3Digest(); byte p[] = SecurityUtils.byteConvert32Bytes(().toBigInteger()); this.(p, 0, ); this.(p, 0, ); p = SecurityUtils.byteConvert32Bytes(().toBigInteger()); this.(p, 0, ); = 1; nextKey(); } private void nextKey() { Sm3Digest sm3keycur = new Sm3Digest(this.sm3keybase); ((byte) (ct >> 24 & 0xff)); ((byte) (ct >> 16 & 0xff)); ((byte) (ct >> 8 & 0xff)); ((byte) (ct & 0xff)); (key, 0); = 0; ++; } public ECPoint encInit(Sm2Tool sm2Tool, ECPoint userKey) { AsymmetricCipherKeyPair key = sm2Tool.ecc_key_pair_generator.generateKeyPair(); ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) (); ECPublicKeyParameters ecpub = (ECPublicKeyParameters) (); BigInteger k = (); ECPoint c1 = (); this.p2 = (k); reset(); return c1; } public void encrypt(byte data[]) { this.(data, 0, ); for (int i = 0; i < ; i++) { if (keyOff == ) { nextKey(); } data[i] ^= key[keyOff++]; } } public void decInit(BigInteger userD, ECPoint c1) { this.p2 = (userD); reset(); } public void Decrypt(byte data[]) { for (int i = 0; i < ; i++) { if (keyOff == ) { nextKey(); } data[i] ^= key[keyOff++]; } this.(data, 0, ); } public void dofinal(byte c3[]) { byte p[] = SecurityUtils.byteConvert32Bytes(().toBigInteger()); this.(p, 0, ); this.(c3, 0); reset(); } }
3. Security tools
/** * @author weis * @version 1.0.0 * @ClassName * @Description Security Tools Class * @createTime October 28, 2018 14:29:00 */ public class SecurityUtils { /** * Convert byte stream (byte array) data to network transmission * * @param num <P>Incoming data</P> * @Version: 1.0.0 * @return: byte <p>Array of 4 bytes</p> * @date: October 28, 2018 14:29:00 */ 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; } /** * Four bytes of byte data are converted into a plastic shaping data * * @param bytes <p>Array of 4 bytes</p> * @Version: 1.0.0 * @return: int <p>an integer data</p> * @date: October 28, 2018 14:29:00 */ 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; } /** * <p>Long shaping converts to byte stream (byte array) data transmitted by the network</p> * * @param num <p>A long integer data</p> * @Version: 1.0.0 * @return: byte <p>4 bytes of its own array</p> * @date: October 28, 2018 14:29:00 */ 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; } /** * Large digitally converted byte stream (byte array) type data * * @param n <p>A BigInteger data</p> * @Version: 1.0.0 * @return: byte <p>Return byte byte</p> * @date: October 28, 2018 14:29:00 */ public static byte[] byteConvert32Bytes(BigInteger n) { byte[] tamped = null; if (n == null) { return null; } if (().length == 33) { tamped = new byte[32]; ((), 1, tamped, 0, 32); } else if (().length == 32) { tamped = (); } else { tamped = new byte[32]; for (int i = 0; i < 32 - ().length; i++) { tamped[i] = 0; } ((), 0, tamped, 32 - ().length, ().length); } return tamped; } /** * Change byte stream (byte array) data to large numbers * * @param bytes <p>Passing into byte array</p> * @Version: 1.0.0 * @return: BigInteger * @date: October 28, 2018 14:29:00 */ public static BigInteger byteConvertInteger(byte[] bytes) { if (bytes[0] < 0) { byte[] temp = new byte[ + 1]; temp[0] = 0; (bytes, 0, temp, 1, ); return new BigInteger(temp); } return new BigInteger(bytes); } /** * Get value from byte array (hexadecimal number) * * @param bytes <p>Passing into byte array</p> * @Version: 1.0.0 * @return: String * @date: October 28, 2018 14:29:00 */ public static String getHexString(byte[] bytes) { return getHexString(bytes, true); } /** * Get value from byte array (hexadecimal number) * * @param bytes <p>Passing into byte array</p> * @param upperCase <p>boolean</p> * @Version: 1.0.0 * @return: String * @date: October 28, 2018 14:29:00 */ public static String getHexString(byte[] bytes, boolean upperCase) { String ret = ""; for (int i = 0; i < ; i++) { ret += ((bytes[i] & 0xff) + 0x100, 16).substring(1); } return upperCase ? () : ret; } /** * Print hexadecimal string * * @param bytes <p>Passing into byte array</p> * @Version: 1.0.0 * @return: void * @date: October 28, 2018 14:29:00 */ public static void printHexString(byte[] bytes) { for (int i = 0; i < ; i++) { String hex = (bytes[i] & 0xFF); if (() == 1) { hex = '0' + hex; } ("0x" + () + ","); } (""); } /** * Convert hexadecimal string to byte[] * * @param hexString <p>HexString</p> * @Version: 1.0.0 * @return: byte * @date: October 28, 2018 14:29:00 */ public static byte[] hexStringToBytes(String hexString) { if (hexString == null || ("")) { return null; } hexString = (); int length = () / 2; char[] hexChars = (); 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 characters to bytes * * @param c <p>char type</p> * @Version: 1.0.0 * @return: byte * @date: October 28, 2018 14:29:00 */ public static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } /** * Lowercase character array used to create the output of hexadecimal characters */ private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * The uppercase character array used to create the output of hexadecimal characters */ private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; /** * Convert byte array to hexadecimal character array * * @param data <p>byte[]</p> * @return char[] <p>Hex char[]</p> * @Version: 1.0.0 * @date: October 28, 2018 14:29:00 */ public static char[] encodeHex(byte[] data) { return encodeHex(data, true); } /** * Convert byte array to hexadecimal character array * * @param data <p>byte[]</p> * @param toLowerCase <p><code>true</code> Transfer to lowercase format, <code>false</code> Transfer to uppercase format</p> * @return char[] <p>Hex char[]</p> * @Version: 1.0.0 * @date: October 28, 2018 14:29:00 */ public static char[] encodeHex(byte[] data, boolean toLowerCase) { return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); } /** * Convert byte array to hexadecimal character array * * @param data byte[] * @param toDigits char[] for controlling output * @return hexadecimal char[] */ protected static char[] encodeHex(byte[] data, char[] toDigits) { int l = ; 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; } /** * Convert byte array to hexadecimal string * * @param data byte[] * @return Hex String */ public static String encodeHexString(byte[] data) { return encodeHexString(data, true); } /** * Convert byte array to hexadecimal string * * @param data byte[] * @param toLowerCase <code>true</code> Transfer to lowercase format, <code>false</code> Transfer to uppercase format * @return Hex String */ public static String encodeHexString(byte[] data, boolean toLowerCase) { return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); } /** * Convert byte array to hexadecimal string * * @param data byte[] * @param toDigits char[] for controlling output * @return Hex String */ protected static String encodeHexString(byte[] data, char[] toDigits) { return new String(encodeHex(data, toDigits)); } /** * Convert hexadecimal character array to byte array * * @param data Hexadecimal char[] * @return byte[] * @throws RuntimeException If the source hexadecimal character array is a strange length, a runtime exception will be thrown */ public static byte[] decodeHex(char[] data) { int len = ; 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; } /** * Convert hexadecimal characters to an integer * * @param ch hexadecimal char * @param index The position of hexadecimal characters in the character array * @return An integer * @throws RuntimeException throws runtime exception when ch is not a legal hexadecimal character */ protected static int toDigit(char ch, int index) { int digit = (ch, 16); if (digit == -1) { throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index); } return digit; } /** * Number string to ASCII string * * @param content string * @return ASCII string */ public static String StringToAsciiString(String content) { String result = ""; int max = (); for (int i = 0; i < max; i++) { char c = (i); String b = (c); result = result + b; } return result; } /** * Hexadecimal to string * * @param hexString hex string * @param encodeType Encoding type 4: Unicode, 2: Normal encoding * @return string */ public static String hexStringToString(String hexString, int encodeType) { String result = ""; int max = () / encodeType; for (int i = 0; i < max; i++) { char c = (char) hexStringToAlgorism(hexString .substring(i * encodeType, (i + 1) * encodeType)); result += c; } return result; } /** * Hexadecimal string loads decimal * * @param hex hex string * @return Decimal value */ public static int hexStringToAlgorism(String hex) { hex = (); int max = (); int result = 0; for (int i = max; i > 0; i--) { char c = (i - 1); int algorism = 0; if (c >= '0' && c <= '9') { algorism = c - '0'; } else { algorism = c - 55; } result += (16, max - i) * algorism; } return result; } /** * Sixteen to binary * * @param hex hex string * @return binary string */ public static String hexStringToBinary(String hex) { hex = (); String result = ""; int max = (); for (int i = 0; i < max; i++) { char c = (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 string to digital string * * @param content ASCII string * @return string */ public static String AsciiStringToString(String content) { String result = ""; int length = () / 2; for (int i = 0; i < length; i++) { String c = (i * 2, i * 2 + 2); int a = hexStringToAlgorism(c); char b = (char) a; String d = (b); result += d; } return result; } /** * Convert decimal to a hexadecimal string of specified length * * @param algorithm int decimal number * @param maxLength int Converted hexadecimal string length * @return String Converted hexadecimal string */ public static String algorismToHexString(int algorism, int maxLength) { String result = ""; result = (algorism); if (() % 2 == 1) { result = "0" + result; } return patchHexString((), maxLength); } /** * Convert byte array to normal string (character corresponding to ASCII) * * @param bytearray byte[] * @return String */ public static String byteToString(byte[] bytearray) { String result = ""; char temp; int length = ; for (int i = 0; i < length; i++) { temp = (char) bytearray[i]; result += temp; } return result; } /** * Binary string to decimal * * @param binary string * @return Decimal value */ public static int binaryToAlgorism(String binary) { int max = (); int result = 0; for (int i = max; i > 0; i--) { char c = (i - 1); int algorism = c - '0'; result += (2, max - i) * algorism; } return result; } /** * Convert decimal to hexadecimal string * * @param algorithm int Decimal number * @return String corresponding hexadecimal string */ public static String algorismToHEXString(int algorism) { String result = ""; result = (algorism); if (() % 2 == 1) { result = "0" + result; } result = (); return result; } /** * The HEX string is supplemented with 0, which is mainly used for insufficient number of length digits. * * @param str String Hexadecimal string that needs to be supplemented * @param maxLength int length of the supplemental hexadecimal string * @return Supplementary results */ static public String patchHexString(String str, int maxLength) { String temp = ""; for (int i = 0; i < maxLength - (); i++) { temp = "0" + temp; } str = (temp + str).substring(0, maxLength); return str; } /** * Convert a string to int * * @param s String String to convert * @param defaultInt int If an exception occurs, the number returned by default * @param radix int What is the binary string to convert, such as 16 8 10. * @return int converted number */ public static int parseToInt(String s, int defaultInt, int radix) { int i = 0; try { i = (s, radix); } catch (NumberFormatException ex) { i = defaultInt; } return i; } /** * Convert a decimal numeric string to int * * @param s String String to convert * @param defaultInt int If an exception occurs, the number returned by default * @return int converted number */ public static int parseToInt(String s, int defaultInt) { int i = 0; try { i = (s); } catch (NumberFormatException ex) { i = defaultInt; } return i; } /** * Hexadecimal string converted to byte array * * @return the array of byte */ public static byte[] hexToByte(String hex) throws IllegalArgumentException { if (() % 2 != 0) { throw new IllegalArgumentException(); } char[] arr = (); byte[] b = new byte[() / 2]; for (int i = 0, j = 0, l = (); i < l; i++, j++) { String swap = "" + arr[i++] + arr[i]; int byteint = (swap, 16) & 0xFF; b[j] = new Integer(byteint).byteValue(); } return b; } /** * Convert byte array to hexadecimal string * * @param b byte[] byte array to convert * @return String Hexadecimal String */ public static String byteToHex(byte b[]) { if (b == null) { throw new IllegalArgumentException( "Argument b ( byte array ) is null! "); } String hs = ""; String stmp = ""; for (int n = 0; n < ; n++) { stmp = (b[n] & 0xff); if (() == 1) { hs = hs + "0" + stmp; } else { hs = hs + stmp; } } return (); } 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; } /** * Convert binary strings to byte arrays, separated by "," for each byte **/ public static byte[] conver2HexToByte(String hex2Str) { // String [] temp = (","); byte[] b = new byte[() / 8]; for (int i = 0; i < ; i++) { // ((i*8, (i+1)*8)); b[i] = ((i * 8, (i + 1) * 8), 2).byteValue(); } return b; } public static void main(String[] args) { String a = "011001000011001101100100001100110100110001101110011010000111000001011001010101110011100100110110011000010101100001000110011100000101100101010111001101010110100101011001010101110011100001110101010110010011001000111001011101000000000000000000000000000000000000100010000110111001010000100000101100101100011001101011111111010000000100000010111010101000110101000110000000100100010101111000110000001111111101101001010110011000000010100011110010111111011101101011100100011011001100010111111101010111001110000111010010000110010000110011011001000011001101001100011011100110100001110000010110010101011100111001001101100110000101011000010001100111000001011001010101110011010101101001010110010101011100111000011101010101100100110010001110010111010000000000000000000000000000000000"; SecurityUtils.conver2HexToByte(a); } }
4. SM2 tool class
/** * @author weis * @version 1.0.0 * @ClassName . * @Description SM2 tool class * @createTime October 28, 2018 14:29:00 */ public class Sm2Tool { /** * Formal parameters * * @Version: 1.0.0 * @date: October 28, 2018 14:29:00 */ public static String[] ecc_param = { "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" }; public static Sm2Tool Instance() { return new Sm2Tool(); } public final BigInteger ecc_p; public final BigInteger ecc_a; public final BigInteger ecc_b; public final BigInteger ecc_n; public final BigInteger ecc_gx; 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_fieldsmen; public final ECFieldElement ecc_gy_fieldsmen; public Sm2Tool() { 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_fieldsmen = new Fp(this.ecc_p, this.ecc_gx); this.ecc_gy_fieldsmen = new Fp(this.ecc_p, this.ecc_gy); this.ecc_curve = new (this.ecc_p, this.ecc_a, this.ecc_b); this.ecc_point_g = new (this.ecc_curve, this.ecc_gx_fieldsmen, this.ecc_gy_fieldsmen); this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n); ECKeyGenerationParameters ecc_engender; ecc_engender = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom()); this.ecc_key_pair_generator = new ECKeyPairGenerator(); this.ecc_key_pair_generator.init(ecc_engender); } }
5. SM2 tool practical category
/** * @author weis * @version 1.0.0 * @ClassName . * @Description SM2 tool utility class * @createTime October 28, 2018 14:29:00 */ public class Sm2Utils { /** * Generate a random key pair * * @Version: 1.0.0 * @return: Map<String, String> * @date: October 28, 2018 14:29:00 */ public static Map<String, String> generateKeyPair() { Sm2Tool sm2Tool = (); AsymmetricCipherKeyPair key = sm2Tool.ecc_key_pair_generator.generateKeyPair(); ECPrivateKeyParameters empiric = (ECPrivateKeyParameters) (); ECPublicKeyParameters scrub = (ECPublicKeyParameters) (); //Decrypt the key BigInteger privateKey = (); //Encryption key ECPoint publicKey = (); Map<String, String> resultMap = new HashMap<String, String>(); ("privateKey", (())); ("publicKey", (())); return resultMap; } /** * Data encryption * * @param publicKey <p>Public Key</p> * @param data <p>Data that needs to be encrypted</p> * @Version: 1.0.0 * @return: String * @date: October 28, 2018 14:29:00 */ public static String encrypt(byte[] publicKey, byte[] data) throws IOException { if (publicKey == null || == 0) { return null; } if (data == null || == 0) { return null; } byte[] source = new byte[]; (data, 0, source, 0, ); Cipher cipher = new Cipher(); Sm2Tool sm2Tool = (); ECPoint userKey = sm2Tool.ecc_curve.decodePoint(publicKey); ECPoint c1 = (sm2Tool, userKey); (source); byte[] c3 = new byte[32]; (c3); //C1 C2 C3 assembled into encrypted string return (()) + (source) + (c3); } /** * Data decryption * * @param privateKey <p>Private Key</p> * @param encryptedData <p>Encrypted data</p> * @Version: 1.0.0 * @return: byte * @date: October 28, 2018 14:29:00 */ public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException { if (privateKey == null || == 0) { return null; } if (encryptedData == null || == 0) { return null; } //Convert the encrypted byte array into hexadecimal string length to * 2 String data = (encryptedData); /***Decompose the encrypted string * (C1 = C1 flag bit 2 bits + C1 entity part 128 bits = 130) * (C3 = C3 entity part 64 bits = 64) * (C2 = * 2 - C1 length - C2 length) */ byte[] c1Bytes = ((0, 130)); int c2Len = - 97; byte[] c2 = ((130, 130 + 2 * c2Len)); byte[] c3 = ((130 + 2 * c2Len, 194 + 2 * c2Len)); Sm2Tool sm2Tool = (); BigInteger userD = new BigInteger(1, privateKey); //Create ECPoint through C1 entity bytes ECPoint c1 = sm2Tool.ecc_curve.decodePoint(c1Bytes); Cipher cipher = new Cipher(); (userD, c1); (c2); (c3); //Return the decryption result return c2; } public static void main(String[] args) throws Exception { for (int i = 0; i < 200; i++) { //Generate a key pair Map<String, String> keyMap = generateKeyPair(); String plainText = "pass"; //Encryption key String publicKey = ("publicKey"); //Decrypt the key String privateKey = ("privateKey"); String encString = ((publicKey), ()); ("Crypto text:" + encString); byte[] plainString = ((privateKey), (encString)); (new String(plainString)); } } }
Summarize
This is the end of this article about Java National Encryption SM2 code. For more related Java National Encryption SM2 content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!