1package org.bouncycastle.math.ec.custom.sec; 2 3import org.bouncycastle.math.ec.ECCurve; 4import org.bouncycastle.math.ec.ECFieldElement; 5import org.bouncycastle.math.ec.ECPoint; 6import org.bouncycastle.math.raw.Nat; 7import org.bouncycastle.math.raw.Nat192; 8 9public class SecP192R1Point extends ECPoint.AbstractFp 10{ 11 /** 12 * Create a point which encodes with point compression. 13 * 14 * @param curve 15 * the curve to use 16 * @param x 17 * affine x co-ordinate 18 * @param y 19 * affine y co-ordinate 20 * 21 * @deprecated Use ECCurve.createPoint to construct points 22 */ 23 public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) 24 { 25 this(curve, x, y, false); 26 } 27 28 /** 29 * Create a point that encodes with or without point compresion. 30 * 31 * @param curve 32 * the curve to use 33 * @param x 34 * affine x co-ordinate 35 * @param y 36 * affine y co-ordinate 37 * @param withCompression 38 * if true encode with point compression 39 * 40 * @deprecated per-point compression property will be removed, refer 41 * {@link #getEncoded(boolean)} 42 */ 43 public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) 44 { 45 super(curve, x, y); 46 47 if ((x == null) != (y == null)) 48 { 49 throw new IllegalArgumentException("Exactly one of the field elements is null"); 50 } 51 52 this.withCompression = withCompression; 53 } 54 55 SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) 56 { 57 super(curve, x, y, zs); 58 59 this.withCompression = withCompression; 60 } 61 62 protected ECPoint detach() 63 { 64 return new SecP192R1Point(null, getAffineXCoord(), getAffineYCoord()); 65 } 66 67 // B.3 pg 62 68 public ECPoint add(ECPoint b) 69 { 70 if (this.isInfinity()) 71 { 72 return b; 73 } 74 if (b.isInfinity()) 75 { 76 return this; 77 } 78 if (this == b) 79 { 80 return twice(); 81 } 82 83 ECCurve curve = this.getCurve(); 84 85 SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Y1 = (SecP192R1FieldElement)this.y; 86 SecP192R1FieldElement X2 = (SecP192R1FieldElement)b.getXCoord(), Y2 = (SecP192R1FieldElement)b.getYCoord(); 87 88 SecP192R1FieldElement Z1 = (SecP192R1FieldElement)this.zs[0]; 89 SecP192R1FieldElement Z2 = (SecP192R1FieldElement)b.getZCoord(0); 90 91 int c; 92 int[] tt1 = Nat192.createExt(); 93 int[] t2 = Nat192.create(); 94 int[] t3 = Nat192.create(); 95 int[] t4 = Nat192.create(); 96 97 boolean Z1IsOne = Z1.isOne(); 98 int[] U2, S2; 99 if (Z1IsOne) 100 { 101 U2 = X2.x; 102 S2 = Y2.x; 103 } 104 else 105 { 106 S2 = t3; 107 SecP192R1Field.square(Z1.x, S2); 108 109 U2 = t2; 110 SecP192R1Field.multiply(S2, X2.x, U2); 111 112 SecP192R1Field.multiply(S2, Z1.x, S2); 113 SecP192R1Field.multiply(S2, Y2.x, S2); 114 } 115 116 boolean Z2IsOne = Z2.isOne(); 117 int[] U1, S1; 118 if (Z2IsOne) 119 { 120 U1 = X1.x; 121 S1 = Y1.x; 122 } 123 else 124 { 125 S1 = t4; 126 SecP192R1Field.square(Z2.x, S1); 127 128 U1 = tt1; 129 SecP192R1Field.multiply(S1, X1.x, U1); 130 131 SecP192R1Field.multiply(S1, Z2.x, S1); 132 SecP192R1Field.multiply(S1, Y1.x, S1); 133 } 134 135 int[] H = Nat192.create(); 136 SecP192R1Field.subtract(U1, U2, H); 137 138 int[] R = t2; 139 SecP192R1Field.subtract(S1, S2, R); 140 141 // Check if b == this or b == -this 142 if (Nat192.isZero(H)) 143 { 144 if (Nat192.isZero(R)) 145 { 146 // this == b, i.e. this must be doubled 147 return this.twice(); 148 } 149 150 // this == -b, i.e. the result is the point at infinity 151 return curve.getInfinity(); 152 } 153 154 int[] HSquared = t3; 155 SecP192R1Field.square(H, HSquared); 156 157 int[] G = Nat192.create(); 158 SecP192R1Field.multiply(HSquared, H, G); 159 160 int[] V = t3; 161 SecP192R1Field.multiply(HSquared, U1, V); 162 163 SecP192R1Field.negate(G, G); 164 Nat192.mul(S1, G, tt1); 165 166 c = Nat192.addBothTo(V, V, G); 167 SecP192R1Field.reduce32(c, G); 168 169 SecP192R1FieldElement X3 = new SecP192R1FieldElement(t4); 170 SecP192R1Field.square(R, X3.x); 171 SecP192R1Field.subtract(X3.x, G, X3.x); 172 173 SecP192R1FieldElement Y3 = new SecP192R1FieldElement(G); 174 SecP192R1Field.subtract(V, X3.x, Y3.x); 175 SecP192R1Field.multiplyAddToExt(Y3.x, R, tt1); 176 SecP192R1Field.reduce(tt1, Y3.x); 177 178 SecP192R1FieldElement Z3 = new SecP192R1FieldElement(H); 179 if (!Z1IsOne) 180 { 181 SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x); 182 } 183 if (!Z2IsOne) 184 { 185 SecP192R1Field.multiply(Z3.x, Z2.x, Z3.x); 186 } 187 188 ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; 189 190 return new SecP192R1Point(curve, X3, Y3, zs, this.withCompression); 191 } 192 193 // B.3 pg 62 194 public ECPoint twice() 195 { 196 if (this.isInfinity()) 197 { 198 return this; 199 } 200 201 ECCurve curve = this.getCurve(); 202 203 SecP192R1FieldElement Y1 = (SecP192R1FieldElement)this.y; 204 if (Y1.isZero()) 205 { 206 return curve.getInfinity(); 207 } 208 209 SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Z1 = (SecP192R1FieldElement)this.zs[0]; 210 211 int c; 212 int[] t1 = Nat192.create(); 213 int[] t2 = Nat192.create(); 214 215 int[] Y1Squared = Nat192.create(); 216 SecP192R1Field.square(Y1.x, Y1Squared); 217 218 int[] T = Nat192.create(); 219 SecP192R1Field.square(Y1Squared, T); 220 221 boolean Z1IsOne = Z1.isOne(); 222 223 int[] Z1Squared = Z1.x; 224 if (!Z1IsOne) 225 { 226 Z1Squared = t2; 227 SecP192R1Field.square(Z1.x, Z1Squared); 228 } 229 230 SecP192R1Field.subtract(X1.x, Z1Squared, t1); 231 232 int[] M = t2; 233 SecP192R1Field.add(X1.x, Z1Squared, M); 234 SecP192R1Field.multiply(M, t1, M); 235 c = Nat192.addBothTo(M, M, M); 236 SecP192R1Field.reduce32(c, M); 237 238 int[] S = Y1Squared; 239 SecP192R1Field.multiply(Y1Squared, X1.x, S); 240 c = Nat.shiftUpBits(6, S, 2, 0); 241 SecP192R1Field.reduce32(c, S); 242 243 c = Nat.shiftUpBits(6, T, 3, 0, t1); 244 SecP192R1Field.reduce32(c, t1); 245 246 SecP192R1FieldElement X3 = new SecP192R1FieldElement(T); 247 SecP192R1Field.square(M, X3.x); 248 SecP192R1Field.subtract(X3.x, S, X3.x); 249 SecP192R1Field.subtract(X3.x, S, X3.x); 250 251 SecP192R1FieldElement Y3 = new SecP192R1FieldElement(S); 252 SecP192R1Field.subtract(S, X3.x, Y3.x); 253 SecP192R1Field.multiply(Y3.x, M, Y3.x); 254 SecP192R1Field.subtract(Y3.x, t1, Y3.x); 255 256 SecP192R1FieldElement Z3 = new SecP192R1FieldElement(M); 257 SecP192R1Field.twice(Y1.x, Z3.x); 258 if (!Z1IsOne) 259 { 260 SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x); 261 } 262 263 return new SecP192R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); 264 } 265 266 public ECPoint twicePlus(ECPoint b) 267 { 268 if (this == b) 269 { 270 return threeTimes(); 271 } 272 if (this.isInfinity()) 273 { 274 return b; 275 } 276 if (b.isInfinity()) 277 { 278 return twice(); 279 } 280 281 ECFieldElement Y1 = this.y; 282 if (Y1.isZero()) 283 { 284 return b; 285 } 286 287 return twice().add(b); 288 } 289 290 public ECPoint threeTimes() 291 { 292 if (this.isInfinity() || this.y.isZero()) 293 { 294 return this; 295 } 296 297 // NOTE: Be careful about recursions between twicePlus and threeTimes 298 return twice().add(this); 299 } 300 301 public ECPoint negate() 302 { 303 if (this.isInfinity()) 304 { 305 return this; 306 } 307 308 return new SecP192R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); 309 } 310} 311