forked from TaisysTeam/slimduet_wallet_applet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSECP256k1.java
148 lines (131 loc) · 6.59 KB
/
SECP256k1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
GPL3.0 License
Copyright (c) [2022] [TAISYS TECHNOLOGIES CO., LTD.]
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.taisys.Slimduet.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.security.CryptoException;
import javacard.security.ECKey;
import javacard.security.ECPrivateKey;
import javacard.security.KeyAgreement;
import javacard.security.*;
/**
* Utility methods to work with the SECP256k1 curve. This class is not meant to be instantiated, but its init method
* must be called during applet installation.
*/
public class SECP256k1 {
static final byte SECP256K1_FP[] = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFE,(byte)0xFF,(byte)0xFF,(byte)0xFC,(byte)0x2F
};
static final byte SECP256K1_A[] = {
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00
};
static final byte SECP256K1_B[] = {
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x07
};
static final byte SECP256K1_G[] = {
(byte)0x04,
(byte)0x79,(byte)0xBE,(byte)0x66,(byte)0x7E,(byte)0xF9,(byte)0xDC,(byte)0xBB,(byte)0xAC,
(byte)0x55,(byte)0xA0,(byte)0x62,(byte)0x95,(byte)0xCE,(byte)0x87,(byte)0x0B,(byte)0x07,
(byte)0x02,(byte)0x9B,(byte)0xFC,(byte)0xDB,(byte)0x2D,(byte)0xCE,(byte)0x28,(byte)0xD9,
(byte)0x59,(byte)0xF2,(byte)0x81,(byte)0x5B,(byte)0x16,(byte)0xF8,(byte)0x17,(byte)0x98,
(byte)0x48,(byte)0x3A,(byte)0xDA,(byte)0x77,(byte)0x26,(byte)0xA3,(byte)0xC4,(byte)0x65,
(byte)0x5D,(byte)0xA4,(byte)0xFB,(byte)0xFC,(byte)0x0E,(byte)0x11,(byte)0x08,(byte)0xA8,
(byte)0xFD,(byte)0x17,(byte)0xB4,(byte)0x48,(byte)0xA6,(byte)0x85,(byte)0x54,(byte)0x19,
(byte)0x9C,(byte)0x47,(byte)0xD0,(byte)0x8F,(byte)0xFB,(byte)0x10,(byte)0xD4,(byte)0xB8
};
static final byte SECP256K1_R[] = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFE,
(byte)0xBA,(byte)0xAE,(byte)0xDC,(byte)0xE6,(byte)0xAF,(byte)0x48,(byte)0xA0,(byte)0x3B,
(byte)0xBF,(byte)0xD2,(byte)0x5E,(byte)0x8C,(byte)0xD0,(byte)0x36,(byte)0x41,(byte)0x41
};
static final byte SECP256K1_K = (byte)0x01;
private static KeyAgreement ecPointMultiplier;
/**
* Allocates objects needed by this class. Must be invoked during the applet installation exactly 1 time.
*/
static void init() {
try {
ecPointMultiplier = KeyAgreement.getInstance((byte)0x41, false);
} catch(CryptoException e) {
ecPointMultiplier = null;
}
}
/**
* Sets the SECP256k1 curve parameters to the given ECKey (public or private).
*
* @param key the key where the curve parameters must be set
*/
static void setCurveParameters(ECKey key) {
key.setA(SECP256K1_A, (short) 0x00, (short) SECP256K1_A.length);
key.setB(SECP256K1_B, (short) 0x00, (short) SECP256K1_B.length);
key.setFieldFP(SECP256K1_FP, (short) 0x00, (short) SECP256K1_FP.length);
key.setG(SECP256K1_G, (short) 0x00, (short) SECP256K1_G.length);
key.setR(SECP256K1_R, (short) 0x00, (short) SECP256K1_R.length);
key.setK(SECP256K1_K);
}
/**
* Derives the public key from the given private key and outputs it in the pubOut buffer. This is done by multiplying
* the private key by the G point of the curve.
*
* @param privateKey the private key
* @param pubOut the output buffer for the public key
* @param pubOff the offset in pubOut
* @return the length of the public key
*/
static short derivePublicKey(ECPrivateKey privateKey, byte[] pubOut, short pubOff) {
return multiplyPoint(privateKey, SECP256K1_G, (short) 0, (short) SECP256K1_G.length, pubOut, pubOff);
}
/**
* Multiplies a scalar in the form of a private key by the given point. Uses a special version of EC-DH
* supported since JavaCard 3.0.5 which outputs both X and Y in their uncompressed form.
*
* @param privateKey the scalar in a private key object
* @param point the point to multiply
* @param pointOff the offset of the point
* @param pointLen the length of the point
* @param out the output buffer
* @param outOff the offset in the output buffer
* @return the length of the data written in the out buffer
*/
static short multiplyPoint(ECPrivateKey privateKey, byte[] point, short pointOff, short pointLen, byte[] out, short outOff) {
assertECPointMultiplicationSupport();
ecPointMultiplier.init(privateKey);
return ecPointMultiplier.generateSecret(point, pointOff, pointLen, out, outOff);
}
/**
* Returns whether the card supports EC point multiplication or not.
*
* @return whether the card supports EC point multiplication or not
*/
static boolean hasECPointMultiplication() {
return ecPointMultiplier != null;
}
/**
* Asserts that EC point multiplication is supported. If not, the 0x6A81 status word is returned by throwing an
* ISOException.
*/
static void assertECPointMultiplicationSupport() {
if(!hasECPointMultiplication()) {
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
}
}
//====Clean Buffer
public static void cleanAllField(){
ecPointMultiplier = null;
}
}