1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Vladimir N. Molotkov
20* @version $Revision$
21*/
22
23package tests.security.spec;
24
25import junit.framework.TestCase;
26
27import java.math.BigInteger;
28import java.security.spec.ECFieldF2m;
29import java.util.Arrays;
30import java.util.Random;
31
32/**
33 * Tests for <code>ECFieldF2m</code> class fields and methods.
34 *
35 */
36public class ECFieldF2mTest extends TestCase {
37
38    /**
39     * Support class for this test.
40     * Encapsulates <code>ECFieldF2m</code> testing
41     * domain parameters.
42     *
43     */
44    private static final class ECFieldF2mDomainParams {
45
46        /**
47         * <code>NPE</code> reference object of class NullPointerException.
48         * NullPointerException must be thrown by <code>ECFieldF2m</code>
49         * ctors in some circumstances
50         */
51        static final NullPointerException NPE = new NullPointerException();
52        /**
53         * <code>IArgE</code> reference object of class IllegalArgumentException.
54         * IllegalArgumentException must be thrown by <code>ECFieldF2m</code>
55         * ctors in some circumstances
56         */
57        static final IllegalArgumentException IArgE = new IllegalArgumentException();
58
59        /**
60         * The <code>m</code> parameter for <code>ECFieldF2m</code>
61         * ctor for the current test.
62         */
63        final int m;
64        /**
65         * The <code>rp</code> parameter for <code>ECFieldF2m</code>
66         * ctor for the current test.
67         */
68        final BigInteger rp;
69        /**
70         * The <code>ks</code> parameter for <code>ECFieldF2m</code>
71         * ctor for the current test.
72         */
73        final int[] ks;
74
75
76        /**
77         * Exception expected with this parameters set or <code>null</code>
78         * if no exception expected.
79         */
80        final Exception x;
81
82        /**
83         * Constructs ECFieldF2mDomainParams
84         *
85         * @param m
86         * @param rp
87         * @param ks
88         * @param expectedException
89         */
90        ECFieldF2mDomainParams(final int m,
91                final BigInteger rp,
92                final int[] ks,
93                final Exception expectedException) {
94            this.m = m;
95            this.rp = rp;
96            this.ks = ks;
97            this.x = expectedException;
98        }
99    }
100
101    //
102    // Tests
103    //
104
105    /**
106     * Set of parameters used for <code>ECFieldF2m(int)</code>
107     * constructor tests.
108     */
109    private final ECFieldF2mDomainParams[] intCtorTestParameters =
110        new ECFieldF2mDomainParams[] {
111            // set 0: valid m
112            new ECFieldF2mDomainParams(1, null, null, null),
113            // set 1: valid m
114            new ECFieldF2mDomainParams(Integer.MAX_VALUE, null, null, null),
115            // set 2: invalid m
116            new ECFieldF2mDomainParams(0, null, null, ECFieldF2mDomainParams.IArgE),
117            // set 3: invalid m
118            new ECFieldF2mDomainParams(-1, null, null, ECFieldF2mDomainParams.IArgE)
119        };
120
121    /**
122     * Tests for constructor <code>ECFieldF2m(int)</code><br>
123     *
124     * Assertion: constructs new <code>ECFieldF2m</code> object
125     * using valid parameter m.
126     *
127     * Assertion: IllegalArgumentException if m is not positive.
128     */
129    public final void testECFieldF2mint() {
130        for(int i=0; i<intCtorTestParameters.length; i++) {
131            ECFieldF2mDomainParams tp = intCtorTestParameters[i];
132            try {
133                // perform test
134                new ECFieldF2m(tp.m);
135
136                if (tp.x != null) {
137                    // exception has been expected
138                    fail(getName() + ", set " + i +
139                            " FAILED: expected exception has not been thrown");
140                }
141            } catch (Exception e){
142                if (tp.x == null || !e.getClass().isInstance(tp.x)) {
143                    // exception: failure
144                    // if it has not been expected
145                    // or wrong one has been thrown
146                    fail(getName() + ", set " + i +
147                            " FAILED: unexpected " + e);
148                }
149            }
150        }
151    }
152
153    /**
154     * Set of parameters used for <code>ECFieldF2m(int, int[] ks)</code>
155     * constructor tests.
156     */
157    private final ECFieldF2mDomainParams[] constructorTestParameters =
158        new ECFieldF2mDomainParams[] {
159            // set 0: valid m and ks - trinomial basis params
160            new ECFieldF2mDomainParams(
161                    1999,
162                    new BigInteger("57406534763712726211641660058884099201115885104434760023882136841288313069618515692832974315825313495922298231949373138672355948043152766571296567808332659269564994572656140000344389574120022435714463495031743122390807731823194181973658513020233176985452498279081199404472314802811655824768082110985166340672084454492229252801189742403957029450467388250214501358353312915261004066118140645880633941658603299497698209063510889929202021079926591625770444716951045960277478891794836019580040978908928741972740865961716524153209532713803393514722581342474556943840519615081302148762454520131486413662191617"),
163                    new int[] {367},
164                    null),
165            // set 1: valid m and ks - pentanomial basis params
166            new ECFieldF2mDomainParams(
167                    2000,
168                    new BigInteger("114813069527425452423283320117768198402231770208869520047764273682576626139237031385665948631650626991844596463898746277344711896086305533142593135616665318539129989145312280000688779148240044871428926990063486244781615463646388363947317026040466353970904996558162398808944629605623311649536164221970332681364606313754094036473740741389411285817465477407288087941692709593079057904974473325399237449961796178150263073811552931156681807161003582337510008648338765664631815874608789366699668224806907571505750798647855797220056285479869767291137153732790597348308446887230584637235716444920907512810569735"),
169                    new int[] {981,2,1},
170                    null),
171            // set 2: valid m, invalid (null) pr, invalid (null) ks
172            new ECFieldF2mDomainParams(
173                    1963,
174                    null,
175                    null,
176                    ECFieldF2mDomainParams.NPE),
177            // set 3: valid m, invalid pr, invalid ks - wrong length
178            new ECFieldF2mDomainParams(
179                    1963,
180                    new BigInteger("114813069527425452423283320117768198402231770208869520047764273682576626139237031385665948631650626991844596463898746277344711896086305533142593135616665318539129989145312280000688779148240044871428926990063486244781615463646388363947317026040466353970904996558162398808944629605623311649536164221970332681364606313754094036473740741389411285817465477407288087941692709593079057904974473325399237449961796178150263073811552931156681807161003582337510008648338765664631815874608789366699668224806907571505750798647855797220056285479869767291137153732790597348308446887230584637235716444920907512810569734"),
181                    new int[] {981,2},
182                    ECFieldF2mDomainParams.IArgE),
183            // set 4: valid m, invalid ks - wrong length
184            new ECFieldF2mDomainParams(
185                    1963,
186                    new BigInteger("5"),
187                    new int[] {981,124,2,1},
188                    ECFieldF2mDomainParams.IArgE),
189            // set 5: valid m, invalid ks - wrong value
190            new ECFieldF2mDomainParams(
191                    1999,
192                    new BigInteger("5"),
193                    new int[] {1999},
194                    ECFieldF2mDomainParams.IArgE),
195            // set 6: valid m, invalid ks - wrong value
196            new ECFieldF2mDomainParams(
197                    1999,
198                    new BigInteger("5"),
199                    new int[] {0},
200                    ECFieldF2mDomainParams.IArgE),
201            // set 7: valid m, invalid ks - wrong values
202            new ECFieldF2mDomainParams(
203                    2000,
204                    new BigInteger("5"),
205                    new int[] {2000,2,1},
206                    ECFieldF2mDomainParams.IArgE),
207            // set 8: valid m, invalid ks - wrong values
208            new ECFieldF2mDomainParams(
209                    2000,
210                    new BigInteger("5"),
211                    new int[] {981,2,0},
212                    ECFieldF2mDomainParams.IArgE),
213            // set 9: invalid m
214            new ECFieldF2mDomainParams(
215                    -5,
216                    new BigInteger("114813069527425452423283320117768198402231770208869520047764273682576626139237031385665948631650626991844596463898746277344711896086305533142593135616665318539129989145312280000688779148240044871428926990063486244781615463646388363947317026040466353970904996558162398808944629605623311649536164221970332681364606313754094036473740741389411285817465477407288087941692709593079057904974473325399237449961796178150263073811552931156681807161003582337510008648338765664631815874608789366699668224806907571505750798647855797220056285479869767291137153732790597348308446887230584637235716444920907512810569735"),
217                    new int[] {981,2,1},
218                    ECFieldF2mDomainParams.IArgE),
219            // set 10: valid m, invalid ks - wrong order
220            new ECFieldF2mDomainParams(
221                    2000,
222                    new BigInteger("5"),
223                    new int[] {981,1,2},
224                    ECFieldF2mDomainParams.IArgE),
225            // set 11: valid m, invalid ks - no content
226            new ECFieldF2mDomainParams(
227                    2000,
228                    new BigInteger("5"),
229                    new int[3],
230                    ECFieldF2mDomainParams.IArgE),
231            // set 12: valid m, invalid ks - length is 0
232            new ECFieldF2mDomainParams(
233                    2000,
234                    new BigInteger("0"),
235                    new int[0],
236                    ECFieldF2mDomainParams.IArgE),
237        };
238
239    /**
240     * Tests for constructor <code>ECFieldF2m(int m, int[] ks)</code><br>
241     *
242     * Assertion: constructs new <code>ECFieldF2m</code> object
243     * using valid parameters m and rp. ks represents trinomial basis.
244     *
245     * Assertion: constructs new <code>ECFieldF2m</code> object
246     * using valid parameters m and ks. ks represents pentanomial basis.
247     *
248     * Assertion: IllegalArgumentException if m is not positive.
249     *
250     * Assertion: NullPointerException if ks is null.
251     *
252     * Assertion: IllegalArgumentException if ks is invalid.
253     */
254    public final void testECFieldF2mintintArray() {
255        for(int i=0; i<constructorTestParameters.length; i++) {
256            ECFieldF2mDomainParams tp = constructorTestParameters[i];
257            try {
258                // perform test
259                ECFieldF2m test = new ECFieldF2m(tp.m, tp.ks);
260
261                if (tp.x != null) {
262                    // exception has been expected
263                    fail(getName() + ", set " + i +
264                            " FAILED: expected exception has not been thrown");
265                }
266            } catch (Exception e){
267                if (tp.x == null || !e.getClass().isInstance(tp.x)) {
268                    // exception: failure
269                    // if it has not been expected
270                    // or wrong one has been thrown
271                    fail(getName() + ", set " + i +
272                            " FAILED: unexpected " + e);
273                }
274            }
275        }
276    }
277
278    /**
279     * Tests for constructor <code>ECFieldF2m(int m, BigInteger rp)</code><br>
280     *
281     * Assertion: constructs new <code>ECFieldF2m</code> object
282     * using valid parameters m and rp.
283     *
284     * Assertion: constructs new <code>ECFieldF2m</code> object
285     * using valid parameters m and rp.
286     *
287     * Assertion: IllegalArgumentException if m is not positive.
288     *
289     * Assertion: NullPointerException if rp is null.
290     *
291     * Assertion: IllegalArgumentException if rp is invalid.
292     */
293    public final void testECFieldF2mintBigInteger() {
294        for(int i=0; i<constructorTestParameters.length; i++) {
295            ECFieldF2mDomainParams tp = constructorTestParameters[i];
296            try {
297                // perform test
298                new ECFieldF2m(tp.m, tp.rp);
299
300                if (tp.x != null) {
301                    // exception has been expected
302                    fail(getName() + ", set " + i +
303                            " FAILED: expected exception has not been thrown");
304                }
305            } catch (Exception e){
306                if (tp.x == null || !e.getClass().isInstance(tp.x)) {
307                    // exception: failure
308                    // if it has not been expected
309                    // or wrong one has been thrown
310                    fail(getName() + ", set " + i +
311                            " FAILED: unexpected " + e);
312                }
313            }
314        }
315    }
316
317    /**
318     * Test #1 for <code>hashCode()</code> method.<br>
319     *
320     * Assertion: must return the same value if invoked
321     * repeatedly on the same object.
322     */
323    public final void testHashCode01() {
324        ECFieldF2m f = new ECFieldF2m(2000);
325        int hc = f.hashCode();
326        assertTrue(hc == f.hashCode() &&
327                   hc == f.hashCode() &&
328                   hc == f.hashCode() &&
329                   hc == f.hashCode() &&
330                   hc == f.hashCode() &&
331                   hc == f.hashCode() &&
332                   hc == f.hashCode() &&
333                   hc == f.hashCode());
334    }
335
336    /**
337     * Test #2 for <code>hashCode()</code> method.<br>
338     *
339     * Assertion: must return the same value if invoked
340     * repeatedly on the same object.
341     */
342    public final void testHashCode02() {
343        ECFieldF2m f = new ECFieldF2m(2000, new int[] {981, 2, 1});
344        int hc = f.hashCode();
345        assertTrue(hc == f.hashCode() &&
346                   hc == f.hashCode() &&
347                   hc == f.hashCode() &&
348                   hc == f.hashCode() &&
349                   hc == f.hashCode() &&
350                   hc == f.hashCode() &&
351                   hc == f.hashCode() &&
352                   hc == f.hashCode());
353    }
354
355    /**
356     * Test #3 for <code>hashCode()</code> method.<br>
357     *
358     * Assertion: must return the same value if invoked
359     * on equal (according to the <code>equals(Object)</code> method) objects.
360     */
361    public final void testHashCode03() {
362        assertTrue(new ECFieldF2m(111).hashCode() ==
363                   new ECFieldF2m(111).hashCode());
364    }
365
366    /**
367     * Test #4 for <code>hashCode()</code> method.<br>
368     *
369     * Assertion: must return the same value if invoked
370     * on equal (according to the <code>equals(Object)</code> method) objects.
371     */
372    public final void testHashCode04() {
373        assertTrue(new ECFieldF2m(2000, new int[] {981, 2, 1}).hashCode() ==
374                   new ECFieldF2m(2000, new int[] {981, 2, 1}).hashCode());
375    }
376
377    /**
378     * Test #5 for <code>hashCode()</code> method.<br>
379     *
380     * Assertion: must return the same value if invoked
381     * on equal (according to the <code>equals(Object)</code> method) objects.
382     */
383    public final void testHashCode05() {
384        assertTrue(new ECFieldF2m(2000, new int[] {981, 2, 1}).hashCode() ==
385                   new ECFieldF2m(2000, BigInteger.valueOf(0L).
386                                        setBit(0).setBit(1).setBit(2).
387                                        setBit(981).setBit(2000)).hashCode());
388    }
389
390    /**
391     * Test #1 for <code>equals()</code> method.<br>
392     *
393     * Assertion: object equals to itself.
394     */
395    public final void testEqualsObject01() {
396        ECFieldF2m obj = new ECFieldF2m(1999, new int[] {367});
397        assertTrue(obj.equals(obj));
398    }
399
400    /**
401     * Test #2 for <code>equals()</code> method.<br>
402     *
403     * Assertion: normal basis - objects equal if their m are equal.
404     */
405    public final void testEqualsObject02() {
406        assertTrue(new ECFieldF2m(43).equals(new ECFieldF2m(43)));
407    }
408
409    /**
410     * Test #3 for <code>equals()</code> method.<br>
411     *
412     * Assertion: trinomial basis - objects equal if their m, and rp
413     * are mutually equal.
414     */
415    public final void testEqualsObject03() {
416        assertTrue(new ECFieldF2m(1999, new int[] {367}).equals(
417                   new ECFieldF2m(1999, BigInteger.valueOf(0L).
418                                        setBit(0).setBit(367).setBit(1999))));
419    }
420
421    /**
422     * Test #4 for <code>equals()</code> method.<br>
423     *
424     * Assertion: pentanomial basis - objects equal if their m, and rp
425     * are mutually equal.
426     */
427    public final void testEqualsObject04() {
428        ECFieldF2m f1 = new ECFieldF2m(2000, new int[] {981, 2, 1});
429        ECFieldF2m f2 = new ECFieldF2m(2000, BigInteger.valueOf(0L).
430                setBit(0).setBit(1).setBit(2).
431                setBit(981).setBit(2000));
432        assertTrue(f1.equals(f2) && f2.equals(f1));
433    }
434
435    /**
436     * Test #5 for <code>equals()</code> method.<br>
437     *
438     * Assertion: objects equal if their m, and rp are mutually equal.
439     */
440    public final void testEqualsObject05() {
441        ECFieldF2m f1 = new ECFieldF2m(2000);
442        ECFieldF2m f2 = new ECFieldF2m(2000, BigInteger.valueOf(0L).
443                setBit(0).setBit(1).setBit(2).
444                setBit(981).setBit(2000));
445        assertFalse(f1.equals(f2) || f2.equals(f1));
446    }
447
448    /**
449     * Test #6 for <code>equals(Object obj)</code> method.<br>
450     *
451     * Assertion: returns false if obj is <code>null</code>
452     */
453    public final void testEqualsObject06() {
454        assertFalse(new ECFieldF2m(2000).equals(null));
455    }
456
457    /**
458     * Test #7 for <code>equals(Object obj)</code> method.<br>
459     *
460     * Assertion: returns false if obj is not instance of <code>ECFieldF2m</code>
461     */
462    public final void testEqualsObject07() {
463        assertFalse(new ECFieldF2m(2000).equals(new Object()));
464    }
465
466    /**
467     * Test for <code>getFieldSize()</code> method.<br>
468     *
469     * Assertion: returns m value for <code>ECFieldF2m</code>
470     */
471    public final void testGetFieldSize() {
472        assertEquals(2000, new ECFieldF2m(2000).getFieldSize());
473    }
474
475    /**
476     * Test for <code>getM()</code> method.<br>
477     *
478     * Assertion: returns m value for <code>ECFieldF2m</code>
479     */
480    public final void testGetM() {
481        assertEquals(2000, new ECFieldF2m(2000).getM());
482    }
483
484    /**
485     * Test #1 for <code>getMidTermsOfReductionPolynomial()</code> method.<br>
486     *
487     * Assertion: returns mid terms of reduction polynomial
488     */
489    public final void testGetMidTermsOfReductionPolynomial01() {
490        int[] a = new int[] {981,2,1};
491        int[] b = new ECFieldF2m(2000,
492                BigInteger.valueOf(0L).setBit(0).setBit(1).
493                setBit(2).setBit(981).setBit(2000)).
494                getMidTermsOfReductionPolynomial();
495        assertTrue(Arrays.equals(a, b));
496    }
497
498    /**
499     * Test #2 for <code>getMidTermsOfReductionPolynomial()</code> method.<br>
500     *
501     * Assertion: returns null for normal basis
502     */
503    public final void testGetMidTermsOfReductionPolynomial02() {
504        assertNull(new ECFieldF2m(2000).getMidTermsOfReductionPolynomial());
505    }
506
507    /**
508     * Test #3 for <code>getMidTermsOfReductionPolynomial()</code> method.<br>
509     *
510     * Assertion: returns mid terms of reduction polynomial
511     */
512    public final void testGetMidTermsOfReductionPolynomial03() {
513        int[] a = new int[] {367};
514        int[] b = new ECFieldF2m(1999, a).getMidTermsOfReductionPolynomial();
515        assertTrue(Arrays.equals(a, b));
516    }
517
518    /**
519     * Test #1 for <code>getReductionPolynomial()</code> method.<br>
520     *
521     * Assertion: returns reduction polynomial
522     */
523    public final void testGetReductionPolynomial01() {
524        BigInteger rp = BigInteger.valueOf(0L).setBit(0).setBit(1).setBit(2).
525        setBit(981).setBit(2000);
526        assertTrue(new ECFieldF2m(2000, rp).getReductionPolynomial().equals(rp));
527    }
528
529    /**
530     * Test #2 for <code>getReductionPolynomial()</code> method.<br>
531     *
532     * Assertion: returns null for normal basis
533     */
534    public final void testGetReductionPolynomial02() {
535        assertNull(new ECFieldF2m(2000).getReductionPolynomial());
536    }
537
538    /**
539     * Tests that object state is preserved against modifications
540     * through array reference passed to the constructor.
541     */
542    public final void testIsStatePreserved01() {
543        // reference array
544        int[] a = new int[] {367};
545        // reference array copy
546        int[] aCopy = a.clone();
547        // create obj using copy
548        ECFieldF2m f = new ECFieldF2m(1999, aCopy);
549        // modify copy
550        aCopy[0] = 5;
551        // compare reference with returned array
552        assertTrue(Arrays.equals(a, f.getMidTermsOfReductionPolynomial()));
553    }
554
555    /**
556     * Tests that object state is preserved against
557     * modifications through array reference returned by
558     * <code>getMidTermsOfReductionPolynomial()</code> method.
559     */
560    public final void testIsStatePreserved02() {
561        // reference array
562        int[] a = new int[] {981,2,1};
563        // reference array copy
564        int[] aCopy = a.clone();
565        // create obj using copy
566        ECFieldF2m f = new ECFieldF2m(2000, aCopy);
567        // get array reference and modify returned array
568        f.getMidTermsOfReductionPolynomial()[0] = 1532;
569        // compare reference with returned for the second time array
570        assertTrue(Arrays.equals(a, f.getMidTermsOfReductionPolynomial()));
571    }
572
573}
574