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