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 SecP521R1FieldElement extends ECFieldElement 11{ 12 public static final BigInteger Q = SecP521R1Curve.q; 13 14 protected int[] x; 15 16 public SecP521R1FieldElement(BigInteger x) 17 { 18 if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) 19 { 20 throw new IllegalArgumentException("x value invalid for SecP521R1FieldElement"); 21 } 22 23 this.x = SecP521R1Field.fromBigInteger(x); 24 } 25 26 public SecP521R1FieldElement() 27 { 28 this.x = Nat.create(17); 29 } 30 31 protected SecP521R1FieldElement(int[] x) 32 { 33 this.x = x; 34 } 35 36 public boolean isZero() 37 { 38 return Nat.isZero(17, x); 39 } 40 41 public boolean isOne() 42 { 43 return Nat.isOne(17, 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(17, x); 54 } 55 56 public String getFieldName() 57 { 58 return "SecP521R1Field"; 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(17); 69 SecP521R1Field.add(x, ((SecP521R1FieldElement)b).x, z); 70 return new SecP521R1FieldElement(z); 71 } 72 73 public ECFieldElement addOne() 74 { 75 int[] z = Nat.create(17); 76 SecP521R1Field.addOne(x, z); 77 return new SecP521R1FieldElement(z); 78 } 79 80 public ECFieldElement subtract(ECFieldElement b) 81 { 82 int[] z = Nat.create(17); 83 SecP521R1Field.subtract(x, ((SecP521R1FieldElement)b).x, z); 84 return new SecP521R1FieldElement(z); 85 } 86 87 public ECFieldElement multiply(ECFieldElement b) 88 { 89 int[] z = Nat.create(17); 90 SecP521R1Field.multiply(x, ((SecP521R1FieldElement)b).x, z); 91 return new SecP521R1FieldElement(z); 92 } 93 94 public ECFieldElement divide(ECFieldElement b) 95 { 96// return multiply(b.invert()); 97 int[] z = Nat.create(17); 98 Mod.invert(SecP521R1Field.P, ((SecP521R1FieldElement)b).x, z); 99 SecP521R1Field.multiply(z, x, z); 100 return new SecP521R1FieldElement(z); 101 } 102 103 public ECFieldElement negate() 104 { 105 int[] z = Nat.create(17); 106 SecP521R1Field.negate(x, z); 107 return new SecP521R1FieldElement(z); 108 } 109 110 public ECFieldElement square() 111 { 112 int[] z = Nat.create(17); 113 SecP521R1Field.square(x, z); 114 return new SecP521R1FieldElement(z); 115 } 116 117 public ECFieldElement invert() 118 { 119// return new SecP521R1FieldElement(toBigInteger().modInverse(Q)); 120 int[] z = Nat.create(17); 121 Mod.invert(SecP521R1Field.P, x, z); 122 return new SecP521R1FieldElement(z); 123 } 124 125 // D.1.4 91 126 /** 127 * return a sqrt root - the routine verifies that the calculation returns the right value - if 128 * none exists it returns null. 129 */ 130 public ECFieldElement sqrt() 131 { 132 // Raise this element to the exponent 2^519 133 134 int[] x1 = this.x; 135 if (Nat.isZero(17, x1) || Nat.isOne(17, x1)) 136 { 137 return this; 138 } 139 140 int[] t1 = Nat.create(17); 141 int[] t2 = Nat.create(17); 142 143 SecP521R1Field.squareN(x1, 519, t1); 144 SecP521R1Field.square(t1, t2); 145 146 return Nat.eq(17, x1, t2) ? new SecP521R1FieldElement(t1) : null; 147 } 148 149 public boolean equals(Object other) 150 { 151 if (other == this) 152 { 153 return true; 154 } 155 156 if (!(other instanceof SecP521R1FieldElement)) 157 { 158 return false; 159 } 160 161 SecP521R1FieldElement o = (SecP521R1FieldElement)other; 162 return Nat.eq(17, x, o.x); 163 } 164 165 public int hashCode() 166 { 167 return Q.hashCode() ^ Arrays.hashCode(x, 0, 17); 168 } 169} 170