• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.math.ec.custom.sec;
2 
3 import java.math.BigInteger;
4 
5 import org.bouncycastle.math.ec.ECFieldElement;
6 import org.bouncycastle.math.raw.Mod;
7 import org.bouncycastle.math.raw.Nat192;
8 import org.bouncycastle.util.Arrays;
9 
10 public class SecP192K1FieldElement extends ECFieldElement
11 {
12     public static final BigInteger Q = SecP192K1Curve.q;
13 
14     protected int[] x;
15 
SecP192K1FieldElement(BigInteger x)16     public SecP192K1FieldElement(BigInteger x)
17     {
18         if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
19         {
20             throw new IllegalArgumentException("x value invalid for SecP192K1FieldElement");
21         }
22 
23         this.x = SecP192K1Field.fromBigInteger(x);
24     }
25 
SecP192K1FieldElement()26     public SecP192K1FieldElement()
27     {
28         this.x = Nat192.create();
29     }
30 
SecP192K1FieldElement(int[] x)31     protected SecP192K1FieldElement(int[] x)
32     {
33         this.x = x;
34     }
35 
isZero()36     public boolean isZero()
37     {
38         return Nat192.isZero(x);
39     }
40 
isOne()41     public boolean isOne()
42     {
43         return Nat192.isOne(x);
44     }
45 
testBitZero()46     public boolean testBitZero()
47     {
48         return Nat192.getBit(x, 0) == 1;
49     }
50 
toBigInteger()51     public BigInteger toBigInteger()
52     {
53         return Nat192.toBigInteger(x);
54     }
55 
getFieldName()56     public String getFieldName()
57     {
58         return "SecP192K1Field";
59     }
60 
getFieldSize()61     public int getFieldSize()
62     {
63         return Q.bitLength();
64     }
65 
add(ECFieldElement b)66     public ECFieldElement add(ECFieldElement b)
67     {
68         int[] z = Nat192.create();
69         SecP192K1Field.add(x, ((SecP192K1FieldElement)b).x, z);
70         return new SecP192K1FieldElement(z);
71     }
72 
addOne()73     public ECFieldElement addOne()
74     {
75         int[] z = Nat192.create();
76         SecP192K1Field.addOne(x, z);
77         return new SecP192K1FieldElement(z);
78     }
79 
subtract(ECFieldElement b)80     public ECFieldElement subtract(ECFieldElement b)
81     {
82         int[] z = Nat192.create();
83         SecP192K1Field.subtract(x, ((SecP192K1FieldElement)b).x, z);
84         return new SecP192K1FieldElement(z);
85     }
86 
multiply(ECFieldElement b)87     public ECFieldElement multiply(ECFieldElement b)
88     {
89         int[] z = Nat192.create();
90         SecP192K1Field.multiply(x, ((SecP192K1FieldElement)b).x, z);
91         return new SecP192K1FieldElement(z);
92     }
93 
divide(ECFieldElement b)94     public ECFieldElement divide(ECFieldElement b)
95     {
96 //        return multiply(b.invert());
97         int[] z = Nat192.create();
98         Mod.invert(SecP192K1Field.P, ((SecP192K1FieldElement)b).x, z);
99         SecP192K1Field.multiply(z, x, z);
100         return new SecP192K1FieldElement(z);
101     }
102 
negate()103     public ECFieldElement negate()
104     {
105         int[] z = Nat192.create();
106         SecP192K1Field.negate(x, z);
107         return new SecP192K1FieldElement(z);
108     }
109 
square()110     public ECFieldElement square()
111     {
112         int[] z = Nat192.create();
113         SecP192K1Field.square(x, z);
114         return new SecP192K1FieldElement(z);
115     }
116 
invert()117     public ECFieldElement invert()
118     {
119 //        return new SecP192K1FieldElement(toBigInteger().modInverse(Q));
120         int[] z = Nat192.create();
121         Mod.invert(SecP192K1Field.P, x, z);
122         return new SecP192K1FieldElement(z);
123     }
124 
125     /**
126      * return a sqrt root - the routine verifies that the calculation returns the right value - if
127      * none exists it returns null.
128      */
sqrt()129     public ECFieldElement sqrt()
130     {
131         /*
132          * Raise this element to the exponent 2^190 - 2^30 - 2^10 - 2^6 - 2^5 - 2^4 - 2^1
133          *
134          * Breaking up the exponent's binary representation into "repunits", we get:
135          * { 159 1s } { 1 0s } { 19 1s } { 1 0s } { 3 1s } { 3 0s} { 3 1s } { 1 0s }
136          *
137          * Therefore we need an addition chain containing 3, 19, 159 (the lengths of the repunits)
138          * We use: 1, 2, [3], 6, 8, 16, [19], 35, 70, 140, [159]
139          */
140 
141         int[] x1 = this.x;
142         if (Nat192.isZero(x1) || Nat192.isOne(x1))
143         {
144             return this;
145         }
146 
147         int[] x2 = Nat192.create();
148         SecP192K1Field.square(x1, x2);
149         SecP192K1Field.multiply(x2, x1, x2);
150         int[] x3 = Nat192.create();
151         SecP192K1Field.square(x2, x3);
152         SecP192K1Field.multiply(x3, x1, x3);
153         int[] x6 = Nat192.create();
154         SecP192K1Field.squareN(x3, 3, x6);
155         SecP192K1Field.multiply(x6, x3, x6);
156         int[] x8 = x6;
157         SecP192K1Field.squareN(x6, 2, x8);
158         SecP192K1Field.multiply(x8, x2, x8);
159         int[] x16 = x2;
160         SecP192K1Field.squareN(x8, 8, x16);
161         SecP192K1Field.multiply(x16, x8, x16);
162         int[] x19 = x8;
163         SecP192K1Field.squareN(x16, 3, x19);
164         SecP192K1Field.multiply(x19, x3, x19);
165         int[] x35 = Nat192.create();
166         SecP192K1Field.squareN(x19, 16, x35);
167         SecP192K1Field.multiply(x35, x16, x35);
168         int[] x70 = x16;
169         SecP192K1Field.squareN(x35, 35, x70);
170         SecP192K1Field.multiply(x70, x35, x70);
171         int[] x140 = x35;
172         SecP192K1Field.squareN(x70, 70, x140);
173         SecP192K1Field.multiply(x140, x70, x140);
174         int[] x159 = x70;
175         SecP192K1Field.squareN(x140, 19, x159);
176         SecP192K1Field.multiply(x159, x19, x159);
177 
178         int[] t1 = x159;
179         SecP192K1Field.squareN(t1, 20, t1);
180         SecP192K1Field.multiply(t1, x19, t1);
181         SecP192K1Field.squareN(t1, 4, t1);
182         SecP192K1Field.multiply(t1, x3, t1);
183         SecP192K1Field.squareN(t1, 6, t1);
184         SecP192K1Field.multiply(t1, x3, t1);
185         SecP192K1Field.square(t1, t1);
186 
187         int[] t2 = x3;
188         SecP192K1Field.square(t1, t2);
189 
190         return Nat192.eq(x1, t2) ? new SecP192K1FieldElement(t1) : null;
191     }
192 
equals(Object other)193     public boolean equals(Object other)
194     {
195         if (other == this)
196         {
197             return true;
198         }
199 
200         if (!(other instanceof SecP192K1FieldElement))
201         {
202             return false;
203         }
204 
205         SecP192K1FieldElement o = (SecP192K1FieldElement)other;
206         return Nat192.eq(x, o.x);
207     }
208 
hashCode()209     public int hashCode()
210     {
211         return Q.hashCode() ^ Arrays.hashCode(x, 0, 6);
212     }
213 }
214