1 package org.bouncycastle.math.ec.custom.sec; 2 3 import java.math.BigInteger; 4 5 import org.bouncycastle.math.raw.Nat; 6 import org.bouncycastle.math.raw.Nat256; 7 8 public class SecP256K1Field 9 { 10 // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 11 static final int[] P = new int[]{ 0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 12 0xFFFFFFFF, 0xFFFFFFFF }; 13 static final int[] PExt = new int[]{ 0x000E90A1, 0x000007A2, 0x00000001, 0x00000000, 0x00000000, 14 0x00000000, 0x00000000, 0x00000000, 0xFFFFF85E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 15 0xFFFFFFFF, 0xFFFFFFFF }; 16 private static final int[] PExtInv = new int[]{ 0xFFF16F5F, 0xFFFFF85D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 17 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000007A1, 0x00000002 }; 18 private static final int P7 = 0xFFFFFFFF; 19 private static final int PExt15 = 0xFFFFFFFF; 20 private static final int PInv33 = 0x3D1; 21 add(int[] x, int[] y, int[] z)22 public static void add(int[] x, int[] y, int[] z) 23 { 24 int c = Nat256.add(x, y, z); 25 if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) 26 { 27 Nat.add33To(8, PInv33, z); 28 } 29 } 30 addExt(int[] xx, int[] yy, int[] zz)31 public static void addExt(int[] xx, int[] yy, int[] zz) 32 { 33 int c = Nat.add(16, xx, yy, zz); 34 if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt))) 35 { 36 if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) 37 { 38 Nat.incAt(16, zz, PExtInv.length); 39 } 40 } 41 } 42 addOne(int[] x, int[] z)43 public static void addOne(int[] x, int[] z) 44 { 45 int c = Nat.inc(8, x, z); 46 if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) 47 { 48 Nat.add33To(8, PInv33, z); 49 } 50 } 51 fromBigInteger(BigInteger x)52 public static int[] fromBigInteger(BigInteger x) 53 { 54 int[] z = Nat256.fromBigInteger(x); 55 if (z[7] == P7 && Nat256.gte(z, P)) 56 { 57 Nat256.subFrom(P, z); 58 } 59 return z; 60 } 61 half(int[] x, int[] z)62 public static void half(int[] x, int[] z) 63 { 64 if ((x[0] & 1) == 0) 65 { 66 Nat.shiftDownBit(8, x, 0, z); 67 } 68 else 69 { 70 int c = Nat256.add(x, P, z); 71 Nat.shiftDownBit(8, z, c); 72 } 73 } 74 multiply(int[] x, int[] y, int[] z)75 public static void multiply(int[] x, int[] y, int[] z) 76 { 77 int[] tt = Nat256.createExt(); 78 Nat256.mul(x, y, tt); 79 reduce(tt, z); 80 } 81 multiplyAddToExt(int[] x, int[] y, int[] zz)82 public static void multiplyAddToExt(int[] x, int[] y, int[] zz) 83 { 84 int c = Nat256.mulAddTo(x, y, zz); 85 if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt))) 86 { 87 if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) 88 { 89 Nat.incAt(16, zz, PExtInv.length); 90 } 91 } 92 } 93 negate(int[] x, int[] z)94 public static void negate(int[] x, int[] z) 95 { 96 if (Nat256.isZero(x)) 97 { 98 Nat256.zero(z); 99 } 100 else 101 { 102 Nat256.sub(P, x, z); 103 } 104 } 105 reduce(int[] xx, int[] z)106 public static void reduce(int[] xx, int[] z) 107 { 108 long cc = Nat256.mul33Add(PInv33, xx, 8, xx, 0, z, 0); 109 int c = Nat256.mul33DWordAdd(PInv33, cc, z, 0); 110 111 // assert c == 0L || c == 1L; 112 113 if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) 114 { 115 Nat.add33To(8, PInv33, z); 116 } 117 } 118 reduce32(int x, int[] z)119 public static void reduce32(int x, int[] z) 120 { 121 if ((x != 0 && Nat256.mul33WordAdd(PInv33, x, z, 0) != 0) 122 || (z[7] == P7 && Nat256.gte(z, P))) 123 { 124 Nat.add33To(8, PInv33, z); 125 } 126 } 127 square(int[] x, int[] z)128 public static void square(int[] x, int[] z) 129 { 130 int[] tt = Nat256.createExt(); 131 Nat256.square(x, tt); 132 reduce(tt, z); 133 } 134 squareN(int[] x, int n, int[] z)135 public static void squareN(int[] x, int n, int[] z) 136 { 137 // assert n > 0; 138 139 int[] tt = Nat256.createExt(); 140 Nat256.square(x, tt); 141 reduce(tt, z); 142 143 while (--n > 0) 144 { 145 Nat256.square(z, tt); 146 reduce(tt, z); 147 } 148 } 149 subtract(int[] x, int[] y, int[] z)150 public static void subtract(int[] x, int[] y, int[] z) 151 { 152 int c = Nat256.sub(x, y, z); 153 if (c != 0) 154 { 155 Nat.sub33From(8, PInv33, z); 156 } 157 } 158 subtractExt(int[] xx, int[] yy, int[] zz)159 public static void subtractExt(int[] xx, int[] yy, int[] zz) 160 { 161 int c = Nat.sub(16, xx, yy, zz); 162 if (c != 0) 163 { 164 if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) 165 { 166 Nat.decAt(16, zz, PExtInv.length); 167 } 168 } 169 } 170 twice(int[] x, int[] z)171 public static void twice(int[] x, int[] z) 172 { 173 int c = Nat.shiftUpBit(8, x, 0, z); 174 if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) 175 { 176 Nat.add33To(8, PInv33, z); 177 } 178 } 179 } 180