18 | * Note that this is not the same base58 as used by Flickr, which you may find 19 | * referenced around the Internet. 20 | *
21 | * You may want to consider working with {@link VersionedChecksummedBytes} 22 | * instead, which adds support for testing the prefix and suffix bytes commonly 23 | * found in addresses. 24 | *
25 | * Satoshi explains: why base-58 instead of standard base-64 encoding? 26 | *
36 | * However, note that the encoding/decoding runs in O(n²) time, so it is 37 | * not useful for large data. 38 | *
39 | * The basic idea of the encoding is to treat the data bytes as a large number
40 | * represented using base-256 digits, convert the number to be represented using
41 | * base-58 digits, preserve the exact number of leading zeros (which are
42 | * otherwise lost during the mathematical operations on the numbers), and
43 | * finally represent the resulting base-58 digits as alphanumeric ASCII
44 | * characters.
45 | */
46 | public class Base58Algorithm {
47 | public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
48 | private static final char ENCODED_ZERO = ALPHABET[0];
49 | private static final int[] INDEXES = new int[128];
50 | static {
51 | Arrays.fill(INDEXES, -1);
52 | for (int i = 0; i < ALPHABET.length; i++) {
53 | INDEXES[ALPHABET[i]] = i;
54 | }
55 | }
56 |
57 | /**
58 | * Encodes the given bytes as a base58 string (no checksum is appended).
59 | *
60 | * @param input
61 | * the bytes to encode
62 | * @return the base58-encoded string
63 | */
64 | public static String encode(byte[] input) {
65 | if (input.length == 0) {
66 | return "";
67 | }
68 | // Count leading zeros.
69 | int zeros = 0;
70 | while (zeros < input.length && input[zeros] == 0) {
71 | ++zeros;
72 | }
73 | // Convert base-256 digits to base-58 digits (plus conversion to ASCII
74 | // characters)
75 | input = Arrays.copyOf(input, input.length); // since we modify it
76 | // in-place
77 | char[] encoded = new char[input.length * 2]; // upper bound
78 | int outputStart = encoded.length;
79 | for (int inputStart = zeros; inputStart < input.length;) {
80 | encoded[--outputStart] = ALPHABET[divmod(input, inputStart, 256, 58)];
81 | if (input[inputStart] == 0) {
82 | ++inputStart; // optimization - skip leading zeros
83 | }
84 | }
85 | // Preserve exactly as many leading encoded zeros in output as there
86 | // were leading zeros in input.
87 | while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) {
88 | ++outputStart;
89 | }
90 | while (--zeros >= 0) {
91 | encoded[--outputStart] = ENCODED_ZERO;
92 | }
93 | // Return encoded string (including encoded leading zeros).
94 | return new String(encoded, outputStart, encoded.length - outputStart);
95 | }
96 |
97 | /**
98 | * Decodes the given base58 string into the original data bytes.
99 | *
100 | * @param input
101 | * the base58-encoded string to decode
102 | * @return the decoded data bytes
103 | * @throws AddressFormatException
104 | * if the given string is not a valid base58 string
105 | */
106 | public static byte[] decode(String input) throws RuntimeException {
107 | if (input.length() == 0) {
108 | return new byte[0];
109 | }
110 | // Convert the base58-encoded ASCII chars to a base58 byte sequence
111 | // (base58 digits).
112 | byte[] input58 = new byte[input.length()];
113 | for (int i = 0; i < input.length(); ++i) {
114 | char c = input.charAt(i);
115 | int digit = c < 128 ? INDEXES[c] : -1;
116 | if (digit < 0) {
117 | throw new RuntimeException("Illegal character " + c + " at position " + i);
118 | }
119 | input58[i] = (byte) digit;
120 | }
121 | // Count leading zeros.
122 | int zeros = 0;
123 | while (zeros < input58.length && input58[zeros] == 0) {
124 | ++zeros;
125 | }
126 | // Convert base-58 digits to base-256 digits.
127 | byte[] decoded = new byte[input.length()];
128 | int outputStart = decoded.length;
129 | for (int inputStart = zeros; inputStart < input58.length;) {
130 | decoded[--outputStart] = divmod(input58, inputStart, 58, 256);
131 | if (input58[inputStart] == 0) {
132 | ++inputStart; // optimization - skip leading zeros
133 | }
134 | }
135 | // Ignore extra leading zeroes that were added during the calculation.
136 | while (outputStart < decoded.length && decoded[outputStart] == 0) {
137 | ++outputStart;
138 | }
139 | // Return decoded data (including original number of leading zeros).
140 | return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length);
141 | }
142 |
143 | public static BigInteger decodeToBigInteger(String input) throws RuntimeException {
144 | return new BigInteger(1, decode(input));
145 | }
146 |
147 | /**
148 | * Decodes the given base58 string into the original data bytes, using the
149 | * checksum in the last 4 bytes of the decoded data to verify that the rest
150 | * are correct. The checksum is removed from the returned data.
151 | *
152 | * @param input
153 | * the base58-encoded string to decode (which should include the
154 | * checksum)
155 | * @throws AddressFormatException
156 | * if the input is not base 58 or the checksum does not
157 | * validate.
158 | *
159 | * public static byte[] decodeChecked(String input) throws
160 | * AddressFormatException { byte[] decoded = decode(input); if
161 | * (decoded.length < 4) throw new
162 | * AddressFormatException("Input too short"); byte[] data =
163 | * Arrays.copyOfRange(decoded, 0, decoded.length - 4); byte[]
164 | * checksum = Arrays.copyOfRange(decoded, decoded.length - 4,
165 | * decoded.length); byte[] actualChecksum =
166 | * Arrays.copyOfRange(Sha256Hash.hashTwice(data), 0, 4); if
167 | * (!Arrays.equals(checksum, actualChecksum)) throw new
168 | * AddressFormatException("Checksum does not validate"); return
169 | * data; }
170 | */
171 |
172 | /**
173 | * Divides a number, represented as an array of bytes each containing a
174 | * single digit in the specified base, by the given divisor. The given
175 | * number is modified in-place to contain the quotient, and the return value
176 | * is the remainder.
177 | *
178 | * @param number
179 | * the number to divide
180 | * @param firstDigit
181 | * the index within the array of the first non-zero digit (this
182 | * is used for optimization by skipping the leading zeros)
183 | * @param base
184 | * the base in which the number's digits are represented (up to
185 | * 256)
186 | * @param divisor
187 | * the number to divide by (up to 256)
188 | * @return the remainder of the division operation
189 | */
190 | private static byte divmod(byte[] number, int firstDigit, int base, int divisor) {
191 | // this is just long division which accounts for the base of the input
192 | // digits
193 | int remainder = 0;
194 | for (int i = firstDigit; i < number.length; i++) {
195 | int digit = (int) number[i] & 0xFF;
196 | int temp = remainder * base + digit;
197 | number[i] = (byte) (temp / divisor);
198 | remainder = temp % divisor;
199 | }
200 | return (byte) remainder;
201 | }
202 |
203 | }
204 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/encrypt/algorithm/BaseAlgorithm.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Project Name:trustsql_sdk
3 | * File Name:BaseAlgoUtil.java
4 | * Package Name:com.tencent.trustsql.sdk.algo
5 | * Date:Jul 26, 20175:54:22 PM
6 | * Copyright (c) 2017, Tencent All Rights Reserved.
7 | *
8 | */
9 |
10 | package xyz.huanxicloud.blockchainj.core.common.encrypt.algorithm;
11 |
12 |
13 | import org.bouncycastle.jce.provider.BouncyCastleProvider;
14 |
15 | import java.security.MessageDigest;
16 | import java.security.Security;
17 |
18 | /**
19 | * ClassName:BaseAlgoUtil
20 | * Date: Jul 26, 2017 5:54:22 PM
21 | *
22 | * @author Rony
23 | * @since JDK 1.7
24 | */
25 | public class BaseAlgorithm {
26 |
27 | static {
28 | Security.addProvider(new BouncyCastleProvider());
29 | }
30 |
31 | /**
32 | * encode bytes
33 | *
34 | * @param algorithm algorithm
35 | * @param data data
36 | * @return byte[]
37 | */
38 | public static byte[] encode(String algorithm, byte[] data) {
39 | if (data == null) {
40 | return null;
41 | }
42 | try {
43 | MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
44 | messageDigest.update(data);
45 | return messageDigest.digest();
46 | } catch (Exception e) {
47 | throw new RuntimeException(e);
48 | }
49 | }
50 |
51 | /**
52 | * encodeTwice bytes
53 | *
54 | * @param algorithm algorithm
55 | * @param data data
56 | * @return byte[]
57 | */
58 | protected static byte[] encodeTwice(String algorithm, byte[] data) {
59 | if (data == null) {
60 | return null;
61 | }
62 | try {
63 | MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
64 | messageDigest.update(data);
65 | return messageDigest.digest(messageDigest.digest());
66 | } catch (Exception e) {
67 | throw new RuntimeException(e);
68 | }
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/encrypt/algorithm/DESAlgorithm.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Project Name:trustsql_sdk
3 | * File Name:DESAlgoUtil2.java
4 | * Package Name:com.tencent.trustsql.sdk.algo
5 | * Date:Jul 28, 201710:38:59 AM
6 | * Copyright (c) 2017, NUCC All Rights Reserved.
7 | *
8 | */
9 |
10 | package xyz.huanxicloud.blockchainj.core.common.encrypt.algorithm;
11 |
12 | import javax.crypto.Cipher;
13 | import javax.crypto.SecretKeyFactory;
14 | import javax.crypto.spec.DESedeKeySpec;
15 | import java.security.Key;
16 |
17 | /**
18 | * ClassName:DESAlgoUtil2
19 | * Function: TODO ADD FUNCTION.
20 | * Reason: TODO ADD REASON.
21 | * Date: Jul 28, 2017 10:38:59 AM
22 | * @author Rony
23 | * @since JDK 1.7
24 | */
25 | public class DESAlgorithm {
26 | /**
27 | * 密钥算法
28 | * */
29 | public static final String KEY_ALGORITHM = "DESede";
30 |
31 | /**
32 | * 加密/解密算法/工作模式/填充方式
33 | * */
34 | public static final String CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";
35 |
36 | /**
37 | * 转换密钥
38 | *
39 | * @param key
40 | * 二进制密钥
41 | * @return Key 密钥
42 | * */
43 | public static Key toKey(byte[] key) throws Exception {
44 | // 实例化Des密钥
45 | DESedeKeySpec dks = new DESedeKeySpec(key);
46 | // 实例化密钥工厂
47 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
48 | // 生成密钥
49 | return keyFactory.generateSecret(dks);
50 | }
51 |
52 | /**
53 | * 加密数据
54 | *
55 | * @param data
56 | * 待加密数据
57 | * @param key
58 | * 密钥
59 | * @return byte[] 加密后的数据
60 | * */
61 | public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
62 | // 还原密钥
63 | Key k = toKey(key);
64 | // 实例化
65 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
66 | // 初始化,设置为加密模式
67 | cipher.init(Cipher.ENCRYPT_MODE, k);
68 | // 执行操作
69 | return cipher.doFinal(data);
70 | }
71 |
72 | /**
73 | * 解密数据
74 | *
75 | * @param data
76 | * 待解密数据
77 | * @param key
78 | * 密钥
79 | * @return byte[] 解密后的数据
80 | * */
81 | public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
82 | // 欢迎密钥
83 | Key k = toKey(key);
84 | // 实例化
85 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
86 | // 初始化,设置为解密模式
87 | cipher.init(Cipher.DECRYPT_MODE, k);
88 | // 执行操作
89 | return cipher.doFinal(data);
90 | }
91 | }
92 |
93 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/encrypt/algorithm/ECDSAAlgorithm.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Project Name:trustsql_sdk
3 | * File Name:ECDSAAlgoUtil.java
4 | * Package Name:com.tencent.trustsql.sdk.algo
5 | * Date:Jul 26, 20175:17:04 PM
6 | * Copyright (c) 2017, Tencent All Rights Reserved.
7 | */
8 |
9 | package xyz.huanxicloud.blockchainj.core.common.encrypt.algorithm;
10 |
11 |
12 | import com.google.common.base.Objects;
13 | import org.apache.tomcat.util.codec.binary.Base64;
14 | import org.bouncycastle.jce.ECNamedCurveTable;
15 | import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
16 | import org.bouncycastle.math.ec.ECPoint;
17 | import org.spongycastle.asn1.ASN1InputStream;
18 | import org.spongycastle.asn1.ASN1Integer;
19 | import org.spongycastle.asn1.DERSequenceGenerator;
20 | import org.spongycastle.asn1.DLSequence;
21 | import org.spongycastle.asn1.x9.X9ECParameters;
22 | import org.spongycastle.crypto.digests.SHA256Digest;
23 | import org.spongycastle.crypto.ec.CustomNamedCurves;
24 | import org.spongycastle.crypto.params.ECDomainParameters;
25 | import org.spongycastle.crypto.params.ECPrivateKeyParameters;
26 | import org.spongycastle.crypto.params.ECPublicKeyParameters;
27 | import org.spongycastle.crypto.signers.ECDSASigner;
28 | import org.spongycastle.crypto.signers.HMacDSAKCalculator;
29 | import org.spongycastle.math.ec.FixedPointUtil;
30 | import xyz.huanxicloud.blockchainj.core.Constants;
31 |
32 | import java.io.ByteArrayOutputStream;
33 | import java.io.IOException;
34 | import java.io.UnsupportedEncodingException;
35 | import java.math.BigInteger;
36 | import java.security.MessageDigest;
37 | import java.security.SecureRandom;
38 |
39 | /**
40 | * ClassName:ECDSAAlgoUtil
41 | * Date: Jul 26, 2017 5:17:04 PM
42 | *
43 | * @author Rony
44 | * @since JDK 1.7
45 | */
46 | public class ECDSAAlgorithm {
47 | public static final ECDomainParameters CURVE;
48 | public static final BigInteger HALF_CURVE_ORDER;
49 |
50 | static {
51 | X9ECParameters CURVE_PARAMS = CustomNamedCurves.getByName("secp256k1");
52 | FixedPointUtil.precompute(CURVE_PARAMS.getG(), 12);
53 | CURVE = new ECDomainParameters(CURVE_PARAMS.getCurve(), CURVE_PARAMS.getG(), CURVE_PARAMS.getN(),
54 | CURVE_PARAMS.getH());
55 | HALF_CURVE_ORDER = CURVE_PARAMS.getN().shiftRight(1);
56 | }
57 |
58 | public static String generatePrivateKey() {
59 | SecureRandom secureRandom;
60 | try {
61 | secureRandom = SecureRandom.getInstance(Constants.RANDOM_NUMBER_ALGORITHM,
62 | Constants.RANDOM_NUMBER_ALGORITHM_PROVIDER);
63 | } catch (Exception e) {
64 | secureRandom = new SecureRandom();
65 | }
66 | // Generate the key, skipping as many as desired.
67 | byte[] privateKeyAttempt = new byte[32];
68 | secureRandom.nextBytes(privateKeyAttempt);
69 | BigInteger privateKeyCheck = new BigInteger(1, privateKeyAttempt);
70 | while (privateKeyCheck.compareTo(BigInteger.ZERO) == 0 || privateKeyCheck.compareTo(Constants.MAXPRIVATEKEY) > 0) {
71 | secureRandom.nextBytes(privateKeyAttempt);
72 | privateKeyCheck = new BigInteger(1, privateKeyAttempt);
73 | }
74 | String result = Base64.encodeBase64String(privateKeyAttempt);
75 | result = result.replaceAll("[\\s*\t\n\r]", "");
76 | return result;
77 | }
78 |
79 | /**
80 | * 生成公钥,encode为true时为短公钥
81 | *
82 | * @param privateKeyBase64String 私钥
83 | * @param encode 是否使用base64缩短
84 | * @return 公钥
85 | */
86 | public static String generatePublicKey(String privateKeyBase64String, boolean encode) {
87 | try {
88 | byte[] privateKeyBytes = Base64.decodeBase64(privateKeyBase64String);
89 | ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
90 | ECPoint pointQ = spec.getG().multiply(new BigInteger(1, privateKeyBytes));
91 | String result = Base64.encodeBase64String(pointQ.getEncoded(encode));
92 | result = result.replaceAll("[\\s*\t\n\r]", "");
93 | return result;
94 | } catch (Exception e) {
95 | throw new RuntimeException(e);
96 | }
97 | }
98 |
99 | /**
100 | * 生成长公钥
101 | *
102 | * @param privateKeyBase64String 私钥
103 | * @return 公钥
104 | */
105 | public static String generatePublicKey(String privateKeyBase64String) {
106 | return generatePublicKey(privateKeyBase64String, false);
107 | }
108 |
109 | public static String decodePublicKey(String encodePubKeyBase64String) {
110 | try {
111 | byte[] encodePubkeyBytes = Base64.decodeBase64(encodePubKeyBase64String);
112 | ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
113 | ECPoint pointQ = spec.getG().getCurve().decodePoint(encodePubkeyBytes);
114 | String result = Base64.encodeBase64String(pointQ.getEncoded(false));
115 | result = result.replaceAll("[\\s*\t\n\r]", "");
116 | return result;
117 | } catch (Exception e) {
118 | throw new RuntimeException(e);
119 | }
120 | }
121 |
122 | /**
123 | * 测试使用私钥签名,并使用公钥验证签名
124 | */
125 | public static void main(String[] args) throws Exception {
126 | String priKey = generatePrivateKey();
127 | System.out.println(priKey);
128 | String pubKey = generatePublicKey(priKey, true);
129 | String pubKey1 = generatePublicKey(priKey);
130 | System.out.println(pubKey);
131 | System.out.println(pubKey1);
132 | String sign = sign(priKey, "abc");
133 | System.out.println(sign);
134 | boolean verify = verify("abc", sign, pubKey);
135 | System.out.println(verify);
136 | }
137 |
138 | /**
139 | * 根据公钥生成address
140 | *
141 | * @param publicKey 公钥
142 | * @return Address
143 | * @throws Exception exception
144 | */
145 | public static String getAddress(String publicKey) throws Exception {
146 | return getAddress(publicKey.getBytes("UTF-8"), 0);
147 | }
148 |
149 | /**
150 | * 根据公钥生成地址
151 | *
152 | * @param keyBytes 公钥
153 | * @param version 版本,可以不用
154 | * @return address
155 | * @throws Exception exception
156 | */
157 | public static String getAddress(byte[] keyBytes, int... version) throws Exception {
158 | byte[] hashSha256 = BaseAlgorithm.encode("SHA-256", keyBytes);
159 | MessageDigest messageDigest = MessageDigest.getInstance("RipeMD160");
160 | messageDigest.update(hashSha256);
161 | // byte[] hashRipeMD160 = messageDigest.digest();
162 | // byte[] versionHashBytes = new byte[1 + hashRipeMD160.length];
163 | // if(version == null || version.length == 0) {
164 | // versionHashBytes[0] = 0;
165 | // } else {
166 | // versionHashBytes[0] = (byte) version[0];
167 | // }
168 | // System.arraycopy(hashRipeMD160, 0, versionHashBytes, 1, hashRipeMD160.length);
169 | // byte[] checkSumBytes = BaseAlgorithm.encodeTwice("SHA-256", versionHashBytes);
170 | // byte[] rawAddr = new byte[versionHashBytes.length + 4];
171 | // System.arraycopy(versionHashBytes, 0, rawAddr, 0, versionHashBytes.length);
172 | // System.arraycopy(checkSumBytes, 0, rawAddr, versionHashBytes.length, 4);
173 | byte[] hashRipeMD160 = messageDigest.digest();
174 | byte[] hashDoubleSha256 = BaseAlgorithm.encodeTwice("SHA-256", hashRipeMD160);
175 | byte[] rawAddr = new byte[1 + hashRipeMD160.length + 4];
176 | rawAddr[0] = 0;
177 | System.arraycopy(hashRipeMD160, 0, rawAddr, 1, hashRipeMD160.length);
178 | System.arraycopy(hashDoubleSha256, 0, rawAddr, hashRipeMD160.length + 1, 4);
179 | return Base58Algorithm.encode(rawAddr);
180 | }
181 |
182 | public static String sign(String privateKey, String data) throws UnsupportedEncodingException {
183 | return sign(privateKey, data.getBytes("UTF-8"));
184 | }
185 |
186 | public static String sign(String privateKey, byte[] data) {
187 | byte[] hash256 = BaseAlgorithm.encode("SHA-256", data);
188 | ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
189 | BigInteger pri = new BigInteger(1, Base64.decodeBase64(privateKey));
190 | ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(pri, CURVE);
191 | signer.init(true, privKey);
192 | BigInteger[] components = signer.generateSignature(hash256);
193 | byte[] content = new ECDSASignature(components[0], components[1]).toCanonicalised().encodeToDER();
194 | String result = Base64.encodeBase64String(content);
195 | result = result.replaceAll("[\\s*\t\n\r]", "");
196 | return result;
197 | }
198 |
199 | /**
200 | * 根据公钥验证签名是否合法
201 | *
202 | * @param srcStr 明文字符串
203 | * @param sign 用私钥签过名的sign
204 | * @param pubKey 公钥
205 | * @return 是否校验通过
206 | * @throws Exception Exception
207 | */
208 | public static boolean verify(String srcStr, String sign, String pubKey) throws Exception {
209 | byte[] hash256 = BaseAlgorithm.encode("SHA-256", srcStr.getBytes("UTF-8"));
210 | ECDSASignature eCDSASignature = ECDSASignature.decodeFromDER(Base64.decodeBase64(sign));
211 | ECDSASigner signer = new ECDSASigner();
212 | org.spongycastle.math.ec.ECPoint pub = CURVE.getCurve().decodePoint(Base64.decodeBase64(pubKey));
213 | @SuppressWarnings("all")
214 | ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub.getEncoded()), CURVE);
215 | signer.init(false, params);
216 | return signer.verifySignature(hash256, eCDSASignature.r, eCDSASignature.s);
217 | }
218 |
219 | public static class ECDSASignature {
220 | /**
221 | * The two components of the signature.
222 | */
223 | public final BigInteger r, s;
224 |
225 | /**
226 | * Constructs a signature with the given components. Does NOT
227 | * automatically canonicalise the signature.
228 | */
229 | public ECDSASignature(BigInteger r, BigInteger s) {
230 | this.r = r;
231 | this.s = s;
232 | }
233 |
234 | /**
235 | * Returns true if the S component is "low", that means it is below
236 | * See
238 | * BIP62.
239 | */
240 | public boolean isCanonical() {
241 | return s.compareTo(HALF_CURVE_ORDER) <= 0;
242 | }
243 |
244 | /**
245 | * Will automatically adjust the S component to be less than or equal to
246 | * half the curve order, if necessary. This is required because for
247 | * every signature (r,s) the signature (r, -s (mod N)) is a valid
248 | * signature of the same message. However, we dislike the ability to
249 | * modify the bits of a Bitcoin transaction after it's been signed, as
250 | * that violates various assumed invariants. Thus in future only one of
251 | * those forms will be considered legal and the other will be banned.
252 | */
253 | public ECDSASignature toCanonicalised() {
254 | if (!isCanonical()) {
255 | // The order of the curve is the number of valid points that
256 | // exist on that curve. If S is in the upper
257 | // half of the number of valid points, then bring it back to the
258 | // lower half. Otherwise, imagine that
259 | // N = 10
260 | // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are
261 | // valid solutions.
262 | // 10 - 8 == 2, giving us always the latter solution, which is
263 | // canonical.
264 | return new ECDSASignature(r, CURVE.getN().subtract(s));
265 | } else {
266 | return this;
267 | }
268 | }
269 |
270 | /**
271 | * DER is an international standard for serializing data structures
272 | * which is widely used in cryptography. It's somewhat like protocol
273 | * buffers but less convenient. This method returns a standard DER
274 | * encoding of the signature, as recognized by OpenSSL and other
275 | * libraries.
276 | */
277 | public byte[] encodeToDER() {
278 | try {
279 | return derByteStream().toByteArray();
280 | } catch (IOException e) {
281 | // Cannot happen.
282 | throw new RuntimeException(e);
283 | }
284 | }
285 |
286 | public static ECDSASignature decodeFromDER(byte[] bytes) {
287 | ASN1InputStream decoder = null;
288 | try {
289 | decoder = new ASN1InputStream(bytes);
290 | DLSequence seq = (DLSequence) decoder.readObject();
291 | if (seq == null) {
292 | throw new RuntimeException("Reached past end of ASN.1 stream.");
293 | }
294 | ASN1Integer r, s;
295 | try {
296 | r = (ASN1Integer) seq.getObjectAt(0);
297 | s = (ASN1Integer) seq.getObjectAt(1);
298 | } catch (ClassCastException e) {
299 | throw new IllegalArgumentException(e);
300 | }
301 | // OpenSSL deviates from the DER spec by interpreting these
302 | // values as unsigned, though they should not be
303 | // Thus, we always use the positive versions. See:
304 | // http://r6.ca/blog/20111119T211504Z.html
305 | return new ECDSASignature(r.getPositiveValue(), s.getPositiveValue());
306 | } catch (IOException e) {
307 | throw new RuntimeException(e);
308 | } finally {
309 | if (decoder != null) {
310 | try {
311 | decoder.close();
312 | } catch (IOException x) {
313 | }
314 | }
315 | }
316 | }
317 |
318 | protected ByteArrayOutputStream derByteStream() throws IOException {
319 | // Usually 70-72 bytes.
320 | ByteArrayOutputStream bos = new ByteArrayOutputStream(72);
321 | DERSequenceGenerator seq = new DERSequenceGenerator(bos);
322 | seq.addObject(new ASN1Integer(r));
323 | seq.addObject(new ASN1Integer(s));
324 | seq.close();
325 | return bos;
326 | }
327 |
328 | @Override
329 | public boolean equals(Object o) {
330 | if (this == o) {
331 | return true;
332 | }
333 | if (o == null || getClass() != o.getClass()) {
334 | return false;
335 | }
336 | ECDSASignature other = (ECDSASignature) o;
337 | return r.equals(other.r) && s.equals(other.s);
338 | }
339 |
340 | @Override
341 | public int hashCode() {
342 | return Objects.hashCode(r, s);
343 | }
344 | }
345 |
346 | }
347 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/encrypt/exception/ErrorNum.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Project Name:trustsql_sdk
3 | * File Name:ErrorNum.java
4 | * Package Name:com.tencent.trustsql.sdk
5 | * Date:Jul 26, 20172:59:02 PM
6 | * Copyright (c) 2017, Tencent All Rights Reserved.
7 | *
8 | */
9 |
10 | package xyz.huanxicloud.blockchainj.core.common.encrypt.exception;
11 | /**
12 | * ClassName:ErrorNum
13 | * Date: Jul 26, 2017 2:59:02 PM
14 | * @author Rony
15 | * @version
16 | * @since JDK 1.7
17 | * @see
18 | */
19 | public enum ErrorNum {
20 |
21 | INVALID_PARAM_ERROR("001", "参数错误"),
22 | DES3_ENCRYPT_ERROR("002", "DES3加解密错误"),
23 | AES_ENCRYPT_ERROR("003", "AES加解密错误"),
24 | ECDSA_ENCRYPT_ERROR("004", "ECDSA加解密错误"),
25 | SIGN_ERROR("005", "签名错误"),
26 | GENERATE_SIGN_ERROR("006", "生成签名错误"),
27 | GENERATE_SQL_ERROR("007", "生成SQL错误"),
28 | VERIFY_SIGN_ERROR("008", "验证签名错误");
29 |
30 | private String retCode;
31 | private String retMsg;
32 |
33 | ErrorNum(String retCode, String retMsg) {
34 | this.retCode = retCode;
35 | this.retMsg = retMsg;
36 | }
37 |
38 | public String getRetCode() {
39 | return retCode;
40 | }
41 |
42 | public void setRetCode(String retCode) {
43 | this.retCode = retCode;
44 | }
45 |
46 | public String getRetMsg() {
47 | return retMsg;
48 | }
49 |
50 | public void setRetMsg(String retMsg) {
51 | this.retMsg = retMsg;
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/encrypt/exception/TrustSDKException.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Project Name:trustsql_sdk
3 | * File Name:TrustSDKException.java
4 | * Package Name:com.tencent.trustsql.sdk.exception
5 | * Date:Jul 26, 201711:24:06 AM
6 | * Copyright (c) 2017, Tencent All Rights Reserved.
7 | *
8 | */
9 |
10 | package xyz.huanxicloud.blockchainj.core.common.encrypt.exception;
11 |
12 | import com.alibaba.fastjson.JSONObject;
13 |
14 | /**
15 | * ClassName:TrustSDKException
16 | * Date: Jul 26, 2017 11:24:06 AM
17 | * @author Rony
18 | * @version
19 | * @since JDK 1.7
20 | * @see
21 | */
22 | public class TrustSDKException extends Exception {
23 |
24 | private static final long serialVersionUID = -4214831807802264420L;
25 |
26 | protected String rtnCd;
27 | protected String rtnMsg;
28 |
29 | public TrustSDKException(String rtnCd, String rtnMsg) {
30 | super(rtnMsg);
31 | this.rtnCd = rtnCd;
32 | this.rtnMsg = rtnMsg;
33 | }
34 |
35 | public TrustSDKException(String rtnCd, String rtnMsg, Throwable t) {
36 | super(rtnMsg, t);
37 | this.rtnCd = rtnCd;
38 | this.rtnMsg = rtnMsg;
39 | }
40 |
41 | public String getRtnCd() {
42 | return rtnCd;
43 | }
44 |
45 | public void setRtnCd(String rtnCd) {
46 | this.rtnCd = rtnCd;
47 | }
48 |
49 | public String getRtnMsg() {
50 | return rtnMsg;
51 | }
52 |
53 | public void setRtnMsg(String rtnMsg) {
54 | this.rtnMsg = rtnMsg;
55 | }
56 |
57 | @Override
58 | public String toString() {
59 | return JSONObject.toJSONString(this);
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/returnmsg/ResultCode.java:
--------------------------------------------------------------------------------
1 | package xyz.huanxicloud.blockchainj.core.common.returnmsg;
2 |
3 | /**
4 | * @author wuweifeng wrote on 2017/10/23.
5 | */
6 | public enum ResultCode {
7 | //成功
8 | SUCCESS(200),
9 | //失败
10 | FAIL(400),
11 | //未认证(签名错误)
12 | UNAUTHORIZED(401),
13 | //没有登录
14 | NO_LOGIN(402),
15 | //没有权限
16 | NO_PERMISSION(403),
17 | //接口不存在
18 | NOT_FOUND(404),
19 | //用户状态异常、公司状态异常、产品状态异常
20 | STATE_ERROR(406),
21 | //服务器内部错误
22 | INTERNAL_SERVER_ERROR(500),
23 | //参数错误
24 | PARAMETER_ERROR(10001),
25 | //账号错误
26 | ACCOUNT_ERROR(20001),
27 | //登录失败
28 | LOGIN_FAIL_ERROR(20002);
29 |
30 |
31 | public int code;
32 |
33 | ResultCode(int code) {
34 | this.code = code;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/returnmsg/ReturnMessage.java:
--------------------------------------------------------------------------------
1 | package xyz.huanxicloud.blockchainj.core.common.returnmsg;
2 |
3 | /**
4 | * @author wuweifeng wrote on 2017/10/23.
5 | */
6 | public class ReturnMessage {
7 | private int code;
8 | private Object msg;
9 |
10 | @Override
11 | public String toString() {
12 | return "ReturnMessage{" +
13 | "code=" + code +
14 | ", data=" + msg +
15 | '}';
16 | }
17 |
18 | public ReturnMessage(int code, Object msg) {
19 | this.code = code;
20 | this.msg = msg;
21 | }
22 |
23 | public ReturnMessage setCode(ResultCode resultCode) {
24 | this.code = resultCode.code;
25 | return this;
26 | }
27 |
28 | public int getCode() {
29 | return code;
30 | }
31 |
32 | public ReturnMessage setCode(int code) {
33 | this.code = code;
34 | return this;
35 | }
36 |
37 | public Object getMsg() {
38 | return msg;
39 | }
40 |
41 | public void setMsg(Object msg) {
42 | this.msg = msg;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/start/AppStart.java:
--------------------------------------------------------------------------------
1 | package xyz.huanxicloud.blockchainj.core.common.start;
2 |
3 | import org.springframework.stereotype.Component;
4 | import xyz.huanxicloud.blockchainj.core.blockchain.BlockChain;
5 | import xyz.huanxicloud.blockchainj.core.network.client.SocketClientManager;
6 |
7 | import javax.annotation.PostConstruct;
8 | import javax.annotation.Resource;
9 |
10 | /**
11 | * @author: huanxi
12 | * @date: 2019/1/4 18:09
13 | */
14 | @Component
15 | public class AppStart {
16 | @Resource
17 | BlockChain blockChain;
18 | @Resource
19 | SocketClientManager socketClientManager;
20 | @PostConstruct
21 | public void initApp() {
22 | //获取所有节点
23 | //连接各节点
24 | socketClientManager.start();
25 | initDB();
26 | }
27 |
28 | public void initDB() {
29 | //创建本地数据库
30 |
31 | //初始化表
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/util/CommonUtils.java:
--------------------------------------------------------------------------------
1 | package xyz.huanxicloud.blockchainj.core.common.util;
2 |
3 | /**
4 | * @author: huanxi
5 | * @date: 2019/1/1 20:40
6 | */
7 | public class CommonUtils {
8 | public static Long getTimestamp() {
9 | return System.currentTimeMillis();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/xyz/huanxicloud/blockchainj/core/common/util/FastJsonUtil.java:
--------------------------------------------------------------------------------
1 | package xyz.huanxicloud.blockchainj.core.common.util;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.alibaba.fastjson.serializer.JSONLibDataFormatSerializer;
6 | import com.alibaba.fastjson.serializer.SerializeConfig;
7 | import com.alibaba.fastjson.serializer.SerializerFeature;
8 |
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | /**
13 | * @author wuweifeng wrote on 2018/3/2.
14 | */
15 | public class FastJsonUtil {
16 | private static final SerializeConfig CONFIG;
17 |
18 | static {
19 | CONFIG = new SerializeConfig();
20 | CONFIG.put(java.util.Date.class, new JSONLibDataFormatSerializer()); // 使用和json-lib兼容的日期输出格式
21 | CONFIG.put(java.sql.Date.class, new JSONLibDataFormatSerializer()); // 使用和json-lib兼容的日期输出格式
22 | }
23 |
24 | private static final SerializerFeature[] FEATURES = {SerializerFeature.WriteMapNullValue, // 输出空置字段
25 | SerializerFeature.WriteNullListAsEmpty, // list字段如果为null,输出为[],而不是null
26 | SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而不是null
27 | SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null,输出为false,而不是null
28 | SerializerFeature.WriteNullStringAsEmpty // 字符类型字段如果为null,输出为"",而不是null
29 | };
30 |
31 |
32 | public static String toJSONString(Object object) {
33 | return JSON.toJSONString(object, CONFIG, FEATURES);
34 | }
35 |
36 | public static String toJSONNoFeatures(Object object) {
37 | return JSON.toJSONString(object, CONFIG);
38 | }
39 |
40 |
41 | public static Object toBean(String text) {
42 | return JSON.parse(text);
43 | }
44 |
45 | public static