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