Mercurial > 510Connectbot
comparison src/org/keyczar/jce/EcCore.java @ 0:0ce5cc452d02
initial version
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 22 May 2014 10:41:19 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0ce5cc452d02 |
---|---|
1 /* | |
2 * Copyright 2008 Google Inc. | |
3 * | |
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not | |
5 * use this file except in compliance with the License. You may obtain a copy of | |
6 * the License at | |
7 * | |
8 * http://www.apache.org/licenses/LICENSE-2.0 | |
9 * | |
10 * Unless required by applicable law or agreed to in writing, software | |
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
13 * License for the specific language governing permissions and limitations under | |
14 * the License. | |
15 */ | |
16 | |
17 package org.keyczar.jce; | |
18 | |
19 import java.math.BigInteger; | |
20 import java.security.spec.ECFieldFp; | |
21 import java.security.spec.ECParameterSpec; | |
22 | |
23 /** | |
24 * This class implements the basic EC operations such as point addition and | |
25 * doubling and point multiplication. Only NSA Suite B / NIST curves are | |
26 * supported. | |
27 * | |
28 * Todo: | |
29 * - Add (more) comments - Performance optimizations - Cleanup ASN.1 code, | |
30 * possibly replace with own impl - ... | |
31 * | |
32 * References: | |
33 * | |
34 * [1] Software Implementation of the NIST Elliptic Curves Over Prime Fields, M. | |
35 * Brown et al. [2] Efficient elliptic curve exponentiation using mixed | |
36 * coordinates, H. Cohen et al. [3] SEC 1: Elliptic Curve Cryptography. [4] | |
37 * Guide to Elliptic Curve Cryptography, D. Hankerson et al., Springer. | |
38 * | |
39 * @author martclau@gmail.com | |
40 * | |
41 */ | |
42 // BEGIN connectbot-changed | |
43 public final class EcCore { | |
44 // END connectbot-changed | |
45 // BEGIN connectbot-removed | |
46 // private static final long serialVersionUID = -1376116429660095993L; | |
47 // | |
48 // private static final String INFO = "Google Keyczar (EC key/parameter generation; EC signing)"; | |
49 // | |
50 // public static final String NAME = "GooKey"; | |
51 // | |
52 // @SuppressWarnings("unchecked") | |
53 // public EcCore() { | |
54 // super(NAME, 0.1, INFO); | |
55 // AccessController.doPrivileged(new PrivilegedAction<Object>() { | |
56 // @Override | |
57 // public Object run() { | |
58 // put("Signature.SHA1withECDSA", "org.keyczar.jce.EcSignatureImpl$SHA1"); | |
59 // put("Alg.Alias.Signature.ECDSA", "SHA1withDSA"); | |
60 // put("Signature.SHA256withECDSA", | |
61 // "org.keyczar.jce.EcSignatureImpl$SHA256"); | |
62 // put("Signature.SHA384withECDSA", | |
63 // "org.keyczar.jce.EcSignatureImpl$SHA384"); | |
64 // put("Signature.SHA512withECDSA", | |
65 // "org.keyczar.jce.EcSignatureImpl$SHA512"); | |
66 // put("KeyPairGenerator.EC", "org.keyczar.jce.EcKeyPairGeneratorImpl"); | |
67 // put("KeyFactory.EC", "org.keyczar.jce.EcKeyFactoryImpl"); | |
68 // put("Signature.SHA1withECDSA KeySize", "521"); | |
69 // put("Signature.SHA1withECDSA ImplementedIn", "Software"); | |
70 // put("Signature.SHA256withECDSA KeySize", "521"); | |
71 // put("Signature.SHA256withECDSA ImplementedIn", "Software"); | |
72 // put("Signature.SHA384withECDSA KeySize", "521"); | |
73 // put("Signature.SHA384withECDSA ImplementedIn", "Software"); | |
74 // put("Signature.SHA512withECDSA KeySize", "521"); | |
75 // put("Signature.SHA512withECDSA ImplementedIn", "Software"); | |
76 // put("KeyPairGenerator.EC ImplementedIn", "Software"); | |
77 // put("KeyFactory.EC ImplementedIn", "Software"); | |
78 // return null; | |
79 // } | |
80 // }); | |
81 // } | |
82 // | |
83 // private static final ECParameterSpec P192 = new ECParameterSpec( | |
84 // new EllipticCurve( | |
85 // new ECFieldFp(new BigInteger( | |
86 // "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16)), | |
87 // new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", 16), | |
88 // new BigInteger("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 16)), | |
89 // new ECPoint( | |
90 // new BigInteger("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", 16), | |
91 // new BigInteger("07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", 16)), | |
92 // new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 16), 1); | |
93 // | |
94 // private static final ECParameterSpec P224 = new ECParameterSpec( | |
95 // new EllipticCurve(new ECFieldFp(new BigInteger( | |
96 // "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", 16)), | |
97 // new BigInteger( | |
98 // "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", 16), | |
99 // new BigInteger( | |
100 // "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", 16)), | |
101 // new ECPoint(new BigInteger( | |
102 // "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", 16), | |
103 // new BigInteger( | |
104 // "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", 16)), | |
105 // new BigInteger( | |
106 // "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 16), 1); | |
107 // | |
108 // private static final ECParameterSpec P256 = new ECParameterSpec( | |
109 // new EllipticCurve(new ECFieldFp(new BigInteger( | |
110 // "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", | |
111 // 16)), new BigInteger( | |
112 // "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", | |
113 // 16), new BigInteger( | |
114 // "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", | |
115 // 16)), new ECPoint(new BigInteger( | |
116 // "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", | |
117 // 16), new BigInteger( | |
118 // "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", | |
119 // 16)), new BigInteger( | |
120 // "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", | |
121 // 16), 1); | |
122 // | |
123 // private static final ECParameterSpec P384 = new ECParameterSpec( | |
124 // new EllipticCurve( | |
125 // new ECFieldFp( | |
126 // new BigInteger( | |
127 // "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", | |
128 // 16)), | |
129 // new BigInteger( | |
130 // "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", | |
131 // 16), | |
132 // new BigInteger( | |
133 // "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", | |
134 // 16)), | |
135 // new ECPoint( | |
136 // new BigInteger( | |
137 // "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", | |
138 // 16), | |
139 // new BigInteger( | |
140 // "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", | |
141 // 16)), | |
142 // new BigInteger( | |
143 // "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", | |
144 // 16), 1); | |
145 // | |
146 // private static final ECParameterSpec P521 = new ECParameterSpec( | |
147 // new EllipticCurve( | |
148 // new ECFieldFp( | |
149 // new BigInteger( | |
150 // "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", | |
151 // 16)), | |
152 // new BigInteger( | |
153 // "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", | |
154 // 16), | |
155 // new BigInteger( | |
156 // "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", | |
157 // 16)), | |
158 // new ECPoint( | |
159 // new BigInteger( | |
160 // "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", | |
161 // 16), | |
162 // new BigInteger( | |
163 // "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", | |
164 // 16)), | |
165 // new BigInteger( | |
166 // "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", | |
167 // 16), 1); | |
168 // | |
169 // public static final String EC_PARAMS_P192_OID = "1.2.840.10045.3.1.1"; | |
170 // public static final String EC_PARAMS_P224_OID = "1.3.132.0.33"; | |
171 // public static final String EC_PARAMS_P256_OID = "1.2.840.10045.3.1.7"; | |
172 // public static final String EC_PARAMS_P384_OID = "1.3.132.0.34"; | |
173 // public static final String EC_PARAMS_P521_OID = "1.3.132.0.35"; | |
174 // | |
175 // private static Map<String, ECParameterSpec> oidMap = new HashMap<String, ECParameterSpec>(); | |
176 // private static Map<ECParameterSpec, String> paramsMap = new HashMap<ECParameterSpec, String>(); | |
177 // private static Map<ECParameterSpec, String> friendlyNameMap = new HashMap<ECParameterSpec, String>(); | |
178 // | |
179 // static { | |
180 // oidMap.put(EC_PARAMS_P192_OID, P192); | |
181 // oidMap.put(EC_PARAMS_P224_OID, P224); | |
182 // oidMap.put(EC_PARAMS_P256_OID, P256); | |
183 // oidMap.put(EC_PARAMS_P384_OID, P384); | |
184 // oidMap.put(EC_PARAMS_P521_OID, P521); | |
185 // paramsMap.put(P192, EC_PARAMS_P192_OID); | |
186 // paramsMap.put(P224, EC_PARAMS_P224_OID); | |
187 // paramsMap.put(P256, EC_PARAMS_P256_OID); | |
188 // paramsMap.put(P384, EC_PARAMS_P384_OID); | |
189 // paramsMap.put(P521, EC_PARAMS_P521_OID); | |
190 // friendlyNameMap.put(P192, "P-192"); | |
191 // friendlyNameMap.put(P224, "P-224"); | |
192 // friendlyNameMap.put(P256, "P-256"); | |
193 // friendlyNameMap.put(P384, "P-384"); | |
194 // friendlyNameMap.put(P521, "P-521"); | |
195 // } | |
196 // | |
197 // public static ECParameterSpec getParams(String oid) { | |
198 // ECParameterSpec params; | |
199 // if ((params = oidMap.get(oid)) != null) return params; | |
200 // throw new IllegalArgumentException("Unsupported EC parameters: " + oid); | |
201 // } | |
202 // | |
203 // public static String getOID(ECParameterSpec params) { | |
204 // String oid; | |
205 // if ((oid = paramsMap.get(params)) != null) return oid; | |
206 // throw new IllegalArgumentException("Unsupport EC parameters"); | |
207 // } | |
208 // | |
209 // public static String getFriendlyName(ECParameterSpec params) { | |
210 // String name; | |
211 // if ((name = friendlyNameMap.get(params)) != null) return name; | |
212 // throw new IllegalArgumentException("Unsupport EC parameters"); | |
213 // } | |
214 // | |
215 // private static final BigInteger ZERO = BigInteger.ZERO; | |
216 // private static final BigInteger ONE = BigInteger.ONE; | |
217 // private static final BigInteger TWO = BigInteger.valueOf(2); | |
218 // END connectbot-removed | |
219 private static final BigInteger THREE = BigInteger.valueOf(3); | |
220 // BEGIN connectbot-removed | |
221 // private static final BigInteger FOUR = BigInteger.valueOf(4); | |
222 // private static final BigInteger EIGHT = BigInteger.valueOf(8); | |
223 // END connectbot-removed | |
224 | |
225 private static BigInteger[] doublePointA(BigInteger[] P, | |
226 ECParameterSpec params) { | |
227 final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); | |
228 final BigInteger a = params.getCurve().getA(); | |
229 | |
230 if (P[0] == null || P[1] == null) return P; | |
231 | |
232 BigInteger d = (P[0].pow(2).multiply(THREE).add(a)).multiply(P[1] | |
233 .shiftLeft(1).modInverse(p)); | |
234 BigInteger[] R = new BigInteger[2]; | |
235 R[0] = d.pow(2).subtract(P[0].shiftLeft(1)).mod(p); | |
236 R[1] = d.multiply(P[0].subtract(R[0])).subtract(P[1]).mod(p); | |
237 return R; | |
238 } | |
239 | |
240 private static BigInteger[] addPointsA(BigInteger[] P1, BigInteger[] P2, | |
241 ECParameterSpec params) { | |
242 final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); | |
243 | |
244 if (P2[0] == null || P2[1] == null) return P1; | |
245 | |
246 if (P1[0] == null || P1[1] == null) return P2; | |
247 | |
248 BigInteger d = (P2[1].subtract(P1[1])).multiply((P2[0].subtract(P1[0])) | |
249 .modInverse(p)); | |
250 BigInteger[] R = new BigInteger[2]; | |
251 R[0] = d.pow(2).subtract(P1[0]).subtract(P2[0]).mod(p); | |
252 R[1] = d.multiply(P1[0].subtract(R[0])).subtract(P1[1]).mod(p); | |
253 return R; | |
254 } | |
255 | |
256 public static BigInteger[] multiplyPointA(BigInteger[] P, BigInteger k, | |
257 ECParameterSpec params) { | |
258 BigInteger[] Q = new BigInteger[] {null, null}; | |
259 | |
260 for (int i = k.bitLength() - 1; i >= 0; i--) { | |
261 Q = doublePointA(Q, params); | |
262 | |
263 if (k.testBit(i)) Q = addPointsA(Q, P, params); | |
264 } | |
265 | |
266 return Q; | |
267 } | |
268 | |
269 // BEGIN connectbot-removed | |
270 // private static BigInteger[] doublePointJ(BigInteger[] P, | |
271 // ECParameterSpec params) { | |
272 // final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); | |
273 // BigInteger A, B, C, D; | |
274 // | |
275 // if (P[2].signum() == 0) // point at inf | |
276 // return P; | |
277 // | |
278 // A = FOUR.multiply(P[0]).multiply(P[1].pow(2)).mod(p); | |
279 // B = EIGHT.multiply(P[1].pow(4)).mod(p); | |
280 // C = THREE.multiply(P[0].subtract(P[2].pow(2))).multiply( | |
281 // P[0].add(P[2].pow(2))).mod(p); | |
282 // D = C.pow(2).subtract(A.add(A)).mod(p); | |
283 // | |
284 // return new BigInteger[] { | |
285 // D, C.multiply(A.subtract(D)).subtract(B).mod(p), | |
286 // TWO.multiply(P[1]).multiply(P[2]).mod(p)}; | |
287 // } | |
288 // | |
289 // private static BigInteger[] addPointsJA(BigInteger[] P1, BigInteger[] P2, | |
290 // ECParameterSpec params) { | |
291 // final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); | |
292 // BigInteger A, B, C, D; | |
293 // BigInteger X3; | |
294 // | |
295 // if (P1[2].signum() == 0) // point at inf | |
296 // return new BigInteger[] {P2[0], P2[1], ONE}; | |
297 // | |
298 // A = P2[0].multiply(P1[2].pow(2)).mod(p); | |
299 // B = P2[1].multiply(P1[2].pow(3)).mod(p); | |
300 // C = A.subtract(P1[0]).mod(p); | |
301 // D = B.subtract(P1[1]).mod(p); | |
302 // | |
303 // X3 = D.pow(2) | |
304 // .subtract(C.pow(3).add(TWO.multiply(P1[0]).multiply(C.pow(2)))).mod(p); | |
305 // return new BigInteger[] { | |
306 // X3, | |
307 // D.multiply(P1[0].multiply(C.pow(2)).subtract(X3)).subtract( | |
308 // P1[1].multiply(C.pow(3))).mod(p), P1[2].multiply(C).mod(p)}; | |
309 // } | |
310 // | |
311 // // Binary NAF method for point multiplication | |
312 // public static BigInteger[] multiplyPoint(BigInteger[] P, BigInteger k, | |
313 // ECParameterSpec params) { | |
314 // BigInteger h = THREE.multiply(k); | |
315 // | |
316 // BigInteger[] Pneg = new BigInteger[] {P[0], P[1].negate()}; | |
317 // BigInteger[] R = new BigInteger[] {P[0], P[1], ONE}; | |
318 // | |
319 // int bitLen = h.bitLength(); | |
320 // for (int i = bitLen - 2; i > 0; --i) { | |
321 // R = doublePointJ(R, params); | |
322 // if (h.testBit(i)) R = addPointsJA(R, P, params); | |
323 // if (k.testBit(i)) R = addPointsJA(R, Pneg, params); | |
324 // } | |
325 // | |
326 // // // <DEBUG> | |
327 // // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; | |
328 // // toAffine(SS, params); | |
329 // // BigInteger[] RR = multiplyPointA(P, k, params); | |
330 // // if (!SS[0].equals(RR[0]) || !SS[1].equals(RR[1])) | |
331 // // throw new RuntimeException("Internal mult error"); | |
332 // // // </DEBUG> | |
333 // | |
334 // return R; | |
335 // } | |
336 | |
337 // // Simultaneous multiple point multiplication, also known as Shamir's trick | |
338 // static BigInteger[] multiplyPoints(BigInteger[] P, BigInteger k, | |
339 // BigInteger[] Q, BigInteger l, ECParameterSpec params) { | |
340 // BigInteger[] PQ = addPointsA(P, Q, params); | |
341 // BigInteger[] R = new BigInteger[] {null, null, ZERO}; | |
342 // | |
343 // int max = Math.max(k.bitLength(), l.bitLength()); | |
344 // for (int i = max - 1; i >= 0; --i) { | |
345 // R = doublePointJ(R, params); | |
346 // if (k.testBit(i)) { | |
347 // if (l.testBit(i)) | |
348 // R = addPointsJA(R, PQ, params); | |
349 // else | |
350 // R = addPointsJA(R, P, params); | |
351 // } else if (l.testBit(i)) R = addPointsJA(R, Q, params); | |
352 // } | |
353 // | |
354 // // // <DEBUG> | |
355 // // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; | |
356 // // toAffine(SS, params); | |
357 // // BigInteger[] AA = multiplyPointA(P, k, params); | |
358 // // BigInteger[] BB = multiplyPointA(Q, l, params); | |
359 // // BigInteger[] AB = addPointsA(AA, BB, params); | |
360 // // if (!SS[0].equals(AB[0]) || !SS[1].equals(AB[1])) | |
361 // // throw new RuntimeException("Internal mult error"); | |
362 // // // </DEBUG> | |
363 // | |
364 // return R; | |
365 // } | |
366 // | |
367 // // SEC 1, 2.3.5 | |
368 // static byte[] fieldElemToBytes(BigInteger a, ECParameterSpec params) { | |
369 // int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; | |
370 // byte[] bytes = a.toByteArray(); | |
371 // if (len < bytes.length) { | |
372 // byte[] tmp = new byte[len]; | |
373 // System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); | |
374 // return tmp; | |
375 // } else if (len > bytes.length) { | |
376 // byte[] tmp = new byte[len]; | |
377 // System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); | |
378 // return tmp; | |
379 // } | |
380 // return bytes; | |
381 // } | |
382 // | |
383 // static int fieldElemToBytes(BigInteger a, ECParameterSpec params, | |
384 // byte[] data, int off) { | |
385 // int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; | |
386 // byte[] bytes = a.toByteArray(); | |
387 // if (len < bytes.length) { | |
388 // System.arraycopy(bytes, bytes.length - len, data, off, len); | |
389 // return len; | |
390 // } else if (len > bytes.length) { | |
391 // System.arraycopy(bytes, 0, data, len - bytes.length + off, bytes.length); | |
392 // return len; | |
393 // } | |
394 // System.arraycopy(bytes, 0, data, off, bytes.length); | |
395 // return bytes.length; | |
396 // } | |
397 // | |
398 // // SEC 1, 2.3.3 | |
399 // static byte[] ecPointToBytes(ECPoint a, ECParameterSpec params) { | |
400 // byte[] fe1 = fieldElemToBytes(a.getAffineX(), params); | |
401 // byte[] fe2 = fieldElemToBytes(a.getAffineY(), params); | |
402 // byte[] bytes = new byte[1 + fe1.length + fe2.length]; | |
403 // bytes[0] = 0x04; | |
404 // System.arraycopy(fe1, 0, bytes, 1, fe1.length); | |
405 // System.arraycopy(fe2, 0, bytes, 1 + fe1.length, fe2.length); | |
406 // return bytes; | |
407 // } | |
408 // | |
409 // // SEC 1, 2.3.4 | |
410 // static ECPoint bytesToECPoint(byte[] bytes, ECParameterSpec params) { | |
411 // switch (bytes[0]) { | |
412 // case 0x00: // point at inf | |
413 // throw new IllegalArgumentException( | |
414 // "Point at infinity is not a valid argument"); | |
415 // case 0x02: // point compression | |
416 // case 0x03: | |
417 // throw new UnsupportedOperationException( | |
418 // "Point compression is not supported"); | |
419 // case 0x04: | |
420 // final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); | |
421 // byte[] fe = new byte[(p.bitLength() + 7) / 8]; | |
422 // System.arraycopy(bytes, 1, fe, 0, fe.length); | |
423 // BigInteger x = new BigInteger(1, fe); | |
424 // System.arraycopy(bytes, 1 + fe.length, fe, 0, fe.length); | |
425 // return new ECPoint(x, new BigInteger(1, fe)); | |
426 // default: | |
427 // throw new IllegalArgumentException("Invalid point encoding"); | |
428 // } | |
429 // } | |
430 // | |
431 // // Convert Jacobian point to affine | |
432 // static void toAffine(BigInteger[] P, ECParameterSpec params) { | |
433 // final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); | |
434 // P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); | |
435 // P[1] = P[1].multiply(P[2].pow(3).modInverse(p)).mod(p); | |
436 // } | |
437 // | |
438 // static void toAffineX(BigInteger[] P, ECParameterSpec params) { | |
439 // final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); | |
440 // P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); | |
441 // } | |
442 // | |
443 // static BigInteger[] internalPoint(ECPoint P) { | |
444 // return new BigInteger[] {P.getAffineX(), P.getAffineY()}; | |
445 // } | |
446 // | |
447 // // private static void printPerf(String msg, long start, long stop) { | |
448 // // String unit = "ms"; | |
449 // // long diff = stop - start; | |
450 // // if (diff > 1000) { | |
451 // // diff /= 1000; | |
452 // // unit = "s"; | |
453 // // } | |
454 // // System.out.printf("%s: %d %s\n", msg, diff, unit); | |
455 // // } | |
456 // | |
457 // public static void main(String[] args) throws Exception { | |
458 // | |
459 // Security.insertProviderAt(new EcCore(), 0); | |
460 // | |
461 // // ---- | |
462 // // Test primitives | |
463 // // ---- | |
464 // | |
465 // // GooKey EC private key, 256 bit | |
466 // // Private value: | |
467 // // a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2 | |
468 // // Parameters: P-256 (1.2.840.10045.3.1.7) | |
469 // // GooKey EC public key, 256 bit | |
470 // // Public value (x coordinate): | |
471 // // 86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c | |
472 // // Public value (y coordinate): | |
473 // // ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6 | |
474 // // Parameters: P-256 (1.2.840.10045.3.1.7) | |
475 // // GooKey EC private key, 256 bit | |
476 // // Private value: | |
477 // // b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022 | |
478 // // Parameters: P-256 (1.2.840.10045.3.1.7) | |
479 // // GooKey EC public key, 256 bit | |
480 // // Public value (x coordinate): | |
481 // // 61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1 | |
482 // // Public value (y coordinate): | |
483 // // 3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705 | |
484 // // Parameters: P-256 (1.2.840.10045.3.1.7) | |
485 // | |
486 // // P = kG | |
487 // BigInteger k = new BigInteger( | |
488 // "a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2", 16); | |
489 // BigInteger[] P = new BigInteger[] { | |
490 // new BigInteger( | |
491 // "86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c", | |
492 // 16), | |
493 // new BigInteger( | |
494 // "ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6", | |
495 // 16), ONE}; | |
496 // | |
497 // // Q = lG | |
498 // BigInteger l = new BigInteger( | |
499 // "b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022", 16); | |
500 // BigInteger[] Q = new BigInteger[] { | |
501 // new BigInteger( | |
502 // "61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1", | |
503 // 16), | |
504 // new BigInteger( | |
505 // "3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705", | |
506 // 16), ONE}; | |
507 // | |
508 // // Known answer for P+Q | |
509 // BigInteger[] kat1 = new BigInteger[] { | |
510 // new BigInteger( | |
511 // "bc7adb05bca2460bbfeb4e0f88b61c384ea88ed3fd56017938ac2582513d4220", | |
512 // 16), | |
513 // new BigInteger( | |
514 // "a640a43df2e9df39eec11445b7e3f7835b743ef1ac4a83cecb570a060b3f1c6c", | |
515 // 16)}; | |
516 // | |
517 // BigInteger[] R = addPointsA(P, Q, P256); | |
518 // if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) | |
519 // throw new RuntimeException("kat1 failed"); | |
520 // | |
521 // R = addPointsJA(P, Q, P256); | |
522 // toAffine(R, P256); | |
523 // if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) | |
524 // throw new RuntimeException("kat1 failed"); | |
525 // | |
526 // | |
527 // // Known answer for Q+Q | |
528 // BigInteger[] kat2 = new BigInteger[] { | |
529 // new BigInteger( | |
530 // "c79d7f9100c14a70f0bb9bdce59654abf99e10d1ac5afc1a0f1b6bc650d6429b", | |
531 // 16), | |
532 // new BigInteger( | |
533 // "6856814e47adce42bc0d7c3bef308c6c737c418ed093effb31e21f53c7735c97", | |
534 // 16)}; | |
535 // | |
536 // R = doublePointA(P, P256); | |
537 // if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) | |
538 // throw new RuntimeException("kat2 failed"); | |
539 // | |
540 // R = doublePointJ(P, P256); | |
541 // toAffine(R, P256); | |
542 // if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) | |
543 // throw new RuntimeException("kat2 failed"); | |
544 // | |
545 // // Known answer for kP | |
546 // BigInteger[] kat3 = new BigInteger[] { | |
547 // new BigInteger( | |
548 // "97a82a834b9e6b50660ae30d43dac9b200276e8bcd2ed6a6593048de09276d1a", | |
549 // 16), | |
550 // new BigInteger( | |
551 // "30a9590a01066d8ef54a910afcc8648dbc7400c01750af423ce95547f2154d56", | |
552 // 16)}; | |
553 // | |
554 // R = multiplyPointA(P, k, P256); | |
555 // if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) | |
556 // throw new RuntimeException("kat3 failed"); | |
557 // | |
558 // R = multiplyPoint(P, k, P256); | |
559 // toAffine(R, P256); | |
560 // if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) | |
561 // throw new RuntimeException("kat3 failed"); | |
562 // | |
563 // // Known answer for kP+lQ | |
564 // BigInteger[] kat4 = new BigInteger[] { | |
565 // new BigInteger( | |
566 // "6fd51be5cf3d6a6bcb62594bbe41ccf549b37d8fefff6e293a5bea0836efcfc6", | |
567 // 16), | |
568 // new BigInteger( | |
569 // "9bc21a930137aa3814908974c431e4545a05dce61321253c337f3883129c42ca", | |
570 // 16)}; | |
571 // | |
572 // BigInteger[] RR = multiplyPointA(Q, l, P256); | |
573 // R = addPointsA(R, RR, P256); | |
574 // if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) | |
575 // throw new RuntimeException("kat4 failed"); | |
576 // | |
577 // R = multiplyPoints(P, k, Q, l, P256); | |
578 // toAffine(R, P256); | |
579 // if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) | |
580 // throw new RuntimeException("kat4 failed"); | |
581 // | |
582 // // ---- | |
583 // // Test ECDSA in various combinations | |
584 // // ---- | |
585 // | |
586 // Provider gooProv = Security.getProvider("GooKey"); | |
587 // Provider nssProv = Security.getProvider("SunPKCS11-NSS"); | |
588 // | |
589 // // Number of iterations: trust me, this is a (stress) good test | |
590 // // and does provoke bugs in a fuzzing way. | |
591 // int iter = 50; | |
592 // | |
593 // // Iterate over all key lengths and signature schemes. | |
594 // int[] keyLengths = {192, 224, 256, 384, 521}; | |
595 // String[] ecdsas = { | |
596 // "SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", | |
597 // "SHA512withECDSA"}; | |
598 // for (int s = 0; s < ecdsas.length; s++) { | |
599 // System.out.println("Signature scheme " + ecdsas[s]); | |
600 // for (int i = 0; i < keyLengths.length; i++) { | |
601 // System.out.print("Testing P-" + keyLengths[i] + ": "); | |
602 // for (int n = 0; n < iter; n++) { | |
603 // System.out.print("."); | |
604 // | |
605 // KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", gooProv); | |
606 // kpGen.initialize(keyLengths[i]); | |
607 // KeyPair ecKeyPair = kpGen.generateKeyPair(); | |
608 // | |
609 // ECPrivateKey ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); | |
610 // byte[] tmp = ecPrivKey.getEncoded(); | |
611 // KeyFactory keyFab = KeyFactory.getInstance("EC", gooProv); | |
612 // keyFab.generatePrivate(new PKCS8EncodedKeySpec(tmp)); | |
613 // ECPrivateKeySpec ecPrivSpec = new ECPrivateKeySpec(ecPrivKey.getS(), | |
614 // ecPrivKey.getParams()); | |
615 // keyFab.generatePrivate(ecPrivSpec); | |
616 // | |
617 // ECPublicKey ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); | |
618 // tmp = ecPubKey.getEncoded(); // dont modify tmp now - is used below | |
619 // keyFab.generatePublic(new X509EncodedKeySpec(tmp)); | |
620 // ECPublicKeySpec ecPubSpec = new ECPublicKeySpec(ecPubKey.getW(), | |
621 // ecPubKey.getParams()); | |
622 // keyFab.generatePublic(ecPubSpec); | |
623 // | |
624 // Signature ecdsa = Signature.getInstance(ecdsas[s], gooProv); | |
625 // ecdsa.initSign(ecPrivKey); | |
626 // ecdsa.update(tmp); | |
627 // byte[] sig = ecdsa.sign(); | |
628 // ecdsa.initVerify(ecPubKey); | |
629 // ecdsa.update(tmp); | |
630 // if (!ecdsa.verify(sig)) | |
631 // throw new RuntimeException("Signature not verified: " | |
632 // + keyLengths[i]); | |
633 // | |
634 // // Cross verify using NSS if present | |
635 // if (nssProv != null) { | |
636 // keyFab = KeyFactory.getInstance("EC", nssProv); | |
637 // | |
638 // // For some reason NSS doesnt seem to work for P-192 and P-224?! | |
639 // if (keyLengths[i] == 192 || keyLengths[i] == 224) continue; | |
640 // | |
641 // ECPrivateKey nssPrivKey = (ECPrivateKey) keyFab | |
642 // .generatePrivate(new PKCS8EncodedKeySpec(ecPrivKey.getEncoded())); | |
643 // ECPublicKey nssPubKey = (ECPublicKey) keyFab | |
644 // .generatePublic(new X509EncodedKeySpec(ecPubKey.getEncoded())); | |
645 // | |
646 // ecdsa = Signature.getInstance(ecdsas[s], nssProv); | |
647 // ecdsa.initVerify(nssPubKey); | |
648 // ecdsa.update(tmp); | |
649 // if (!ecdsa.verify(sig)) | |
650 // throw new RuntimeException("Signature not verified 2: " | |
651 // + keyLengths[i]); | |
652 // | |
653 // ecdsa.initSign(nssPrivKey); | |
654 // ecdsa.update(tmp); | |
655 // sig = ecdsa.sign(); | |
656 // ecdsa = Signature.getInstance(ecdsas[s], gooProv); | |
657 // ecdsa.initVerify(ecPubKey); | |
658 // ecdsa.update(tmp); | |
659 // if (!ecdsa.verify(sig)) | |
660 // throw new RuntimeException("Signature not verified 3: " | |
661 // + keyLengths[i]); | |
662 // } | |
663 // } | |
664 // System.out.println(" done"); | |
665 // } | |
666 // } | |
667 // | |
668 // // Test Keyczar integration | |
669 // // Signer ecdsaSigner = new Signer("c:\\temp\\eckeyset"); | |
670 // // String tbs = "Sign this"; | |
671 // // String sig = ecdsaSigner.sign(tbs); | |
672 // // if (ecdsaSigner.verify(sig, tbs)) | |
673 // // System.out.println("Keyczar EC OK"); | |
674 // // else | |
675 // // System.out.println("Keyczar EC not OK"); | |
676 // } | |
677 //END connectbot-removed | |
678 } |