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