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