OSDN Git Service

perfect exception process
[bytom/bytom-java-sdk.git] / tx-signer / src / main / java / io / bytom / common / NonHardenedChild.java
1 package io.bytom.common;\r
2 \r
3 import org.bouncycastle.util.encoders.Hex;\r
4 \r
5 import javax.crypto.Mac;\r
6 import javax.crypto.spec.SecretKeySpec;\r
7 import java.io.ByteArrayOutputStream;\r
8 import java.security.InvalidKeyException;\r
9 import java.security.NoSuchAlgorithmException;\r
10 \r
11 public class NonHardenedChild {\r
12 \r
13     private static byte[] hmacSha512(byte[] data, byte[] key)\r
14             throws NoSuchAlgorithmException, InvalidKeyException {\r
15         SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA512");\r
16         Mac mac = Mac.getInstance("HmacSHA512");\r
17         mac.init(signingKey);\r
18         return mac.doFinal(data);\r
19     }\r
20 \r
21     public static byte[] nhChild(byte[] path, byte[] xprv, byte[] xpub) throws NoSuchAlgorithmException, InvalidKeyException {\r
22         // begin build data\r
23         ByteArrayOutputStream out = new ByteArrayOutputStream();\r
24         out.write('N');\r
25         out.write(xpub, 0, xpub.length / 2);\r
26         out.write(path, 0, path.length);\r
27         byte[] data = out.toByteArray();\r
28         // end build data\r
29 \r
30         // begin build key\r
31         byte[] key = new byte[xpub.length / 2];\r
32         System.arraycopy(xpub, xpub.length / 2, key, 0, xpub.length / 2);\r
33         // end build key\r
34 \r
35         // doFinal()\r
36         byte[] res = hmacSha512(data, key);\r
37 \r
38         //begin operate res[:32]\r
39         byte[] f = new byte[res.length / 2];\r
40         System.arraycopy(res, 0, f, 0, res.length / 2);\r
41         f = pruneIntermediateScalar(f);\r
42         System.arraycopy(f, 0, res, 0, res.length / 2);\r
43         //end operate res[:32]\r
44 \r
45         //begin operate res[:32] again\r
46         int carry = 0;\r
47         int sum = 0;\r
48         for (int i = 0; i < 32; i++) {\r
49             int xprvInt = xprv[i] & 0xFF;\r
50             int resInt = res[i] & 0xFF;\r
51             sum = xprvInt + resInt + carry;\r
52             res[i] = (byte) sum;\r
53             carry = sum >> 8;\r
54         }\r
55         if ((sum >> 8) != 0) {\r
56             System.err.println("sum does not fit in 256-bit int");\r
57         }\r
58         //end operate res[:32] again\r
59         return res;\r
60     }\r
61 \r
62     private static byte[] pruneIntermediateScalar(byte[] f) {\r
63         f[0] &= 248; // clear bottom 3 bits\r
64         f[29] &= 1; // clear 7 high bits\r
65         f[30] = 0;  // clear 8 bits\r
66         f[31] = 0;  // clear 8 bits\r
67         return f;\r
68     }\r
69 \r
70     public static byte[] child(byte[] xprv, String[] hpaths) throws NoSuchAlgorithmException, InvalidKeyException {\r
71         byte[][] paths = new byte[][]{\r
72                 Hex.decode(hpaths[0]),\r
73                 Hex.decode(hpaths[1])\r
74         };\r
75         byte[] res = xprv;\r
76         for (int i = 0; i < hpaths.length; i++) {\r
77             byte[] xpub = DeriveXpub.deriveXpub(res);\r
78             res = NonHardenedChild.nhChild(paths[i], res, xpub);\r
79         }\r
80         return res;\r
81     }\r
82 }\r
83 \r
84 \r