1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 import sun.security.util.math.*; 27 28 import java.math.BigInteger; 29 import java.nio.ByteBuffer; 30 import java.util.Arrays; 31 import java.util.Optional; 32 33 /** 34 * Arithmetic in the field of integers modulo a prime value implemented using 35 * BigInteger. This implementation is very versatile, but it is slow and none 36 * of the operations are value-independent. This class is intended for use in 37 * testing and prototyping, and production code should probably use a more 38 * specialized arithmetic implementation. 39 */ 40 41 public class BigIntegerModuloP implements IntegerFieldModuloP { 42 43 private final BigInteger p; 44 BigIntegerModuloP(BigInteger p)45 public BigIntegerModuloP(BigInteger p) { 46 this.p = p; 47 } 48 49 @Override getSize()50 public BigInteger getSize() { 51 return p; 52 } 53 54 @Override get0()55 public ImmutableElement get0() { 56 return new ImmutableElement(BigInteger.ZERO); 57 } 58 @Override get1()59 public ImmutableElement get1() { 60 return new ImmutableElement(BigInteger.ONE); 61 } 62 @Override getElement(BigInteger v)63 public ImmutableElement getElement(BigInteger v) { 64 return new ImmutableElement(v); 65 } 66 @Override getElement(byte[] v, int offset, int length, byte highByte)67 public ImmutableElement getElement(byte[] v, int offset, int length, 68 byte highByte) { 69 byte[] bigIntIn = new byte[length + 1]; 70 System.arraycopy(v, offset, bigIntIn, 0, length); 71 bigIntIn[length] = highByte; 72 reverse(bigIntIn); 73 return new ImmutableElement(new BigInteger(1, bigIntIn).mod(getSize())); 74 } 75 @Override getSmallValue(int i)76 public SmallValue getSmallValue(int i) { 77 return new SmallElement(i); 78 } 79 80 private abstract class Element implements IntegerModuloP { 81 82 protected BigInteger v; 83 Element(BigInteger v)84 protected Element(BigInteger v) { 85 this.v = v; 86 } 87 Element(boolean v)88 protected Element(boolean v) { 89 this.v = BigInteger.valueOf(v ? 1 : 0); 90 } 91 getModulus()92 private BigInteger getModulus() { 93 return getField().getSize(); 94 } 95 96 @Override getField()97 public IntegerFieldModuloP getField() { 98 return BigIntegerModuloP.this; 99 } 100 101 @Override asBigInteger()102 public BigInteger asBigInteger() { 103 return v; 104 } 105 106 @Override mutable()107 public MutableElement mutable() { 108 return new MutableElement(v); 109 } 110 111 @Override fixed()112 public ImmutableElement fixed() { 113 return new ImmutableElement(v); 114 } 115 116 @Override add(IntegerModuloP b)117 public ImmutableElement add(IntegerModuloP b) { 118 return new ImmutableElement( 119 v.add(b.asBigInteger()).mod(getModulus())); 120 } 121 122 @Override additiveInverse()123 public ImmutableElement additiveInverse() { 124 return new ImmutableElement(v.negate().mod(getModulus())); 125 } 126 127 @Override multiply(IntegerModuloP b)128 public ImmutableElement multiply(IntegerModuloP b) { 129 return new ImmutableElement( 130 v.multiply(b.asBigInteger()).mod(getModulus())); 131 } 132 133 @Override addModPowerTwo(IntegerModuloP arg, byte[] result)134 public void addModPowerTwo(IntegerModuloP arg, byte[] result) { 135 BigInteger biThis = asBigInteger(); 136 BigInteger biArg = arg.asBigInteger(); 137 bigIntAsByteArray(biThis.add(biArg), result); 138 } 139 bigIntAsByteArray(BigInteger arg, byte[] result)140 private void bigIntAsByteArray(BigInteger arg, byte[] result) { 141 byte[] bytes = arg.toByteArray(); 142 // bytes is backwards and possibly too big 143 // Copy the low-order bytes into result in reverse 144 int sourceIndex = bytes.length - 1; 145 for (int i = 0; i < result.length; i++) { 146 if (sourceIndex >= 0) { 147 result[i] = bytes[sourceIndex--]; 148 } else { 149 result[i] = 0; 150 } 151 } 152 } 153 154 @Override asByteArray(byte[] result)155 public void asByteArray(byte[] result) { 156 bigIntAsByteArray(v, result); 157 } 158 } 159 160 private class ImmutableElement extends Element 161 implements ImmutableIntegerModuloP { 162 ImmutableElement(BigInteger v)163 private ImmutableElement(BigInteger v) { 164 super(v); 165 } 166 } 167 168 private class MutableElement extends Element 169 implements MutableIntegerModuloP { 170 MutableElement(BigInteger v)171 private MutableElement(BigInteger v) { 172 super(v); 173 } 174 175 @Override conditionalSet(IntegerModuloP b, int set)176 public void conditionalSet(IntegerModuloP b, int set) { 177 if (set == 1) { 178 v = b.asBigInteger(); 179 } 180 } 181 182 @Override conditionalSwapWith(MutableIntegerModuloP b, int swap)183 public void conditionalSwapWith(MutableIntegerModuloP b, int swap) { 184 if (swap == 1) { 185 BigInteger temp = v; 186 v = b.asBigInteger(); 187 ((Element) b).v = temp; 188 } 189 } 190 191 @Override setValue(IntegerModuloP v)192 public MutableElement setValue(IntegerModuloP v) { 193 this.v = ((Element) v).v; 194 195 return this; 196 } 197 198 @Override setValue(byte[] arr, int offset, int length, byte highByte)199 public MutableElement setValue(byte[] arr, int offset, int length, 200 byte highByte) { 201 byte[] bigIntIn = new byte[length + 1]; 202 System.arraycopy(arr, offset, bigIntIn, 0, length); 203 bigIntIn[length] = highByte; 204 reverse(bigIntIn); 205 v = new BigInteger(bigIntIn).mod(getSize()); 206 207 return this; 208 } 209 210 @Override setValue(ByteBuffer buf, int length, byte highByte)211 public MutableElement setValue(ByteBuffer buf, int length, 212 byte highByte) { 213 byte[] bigIntIn = new byte[length + 1]; 214 buf.get(bigIntIn, 0, length); 215 bigIntIn[length] = highByte; 216 reverse(bigIntIn); 217 v = new BigInteger(bigIntIn).mod(getSize()); 218 219 return this; 220 } 221 222 @Override setSquare()223 public MutableElement setSquare() { 224 v = v.multiply(v).mod(getSize()); 225 return this; 226 } 227 228 @Override setProduct(IntegerModuloP b)229 public MutableElement setProduct(IntegerModuloP b) { 230 Element other = (Element) b; 231 v = v.multiply(other.v).mod(getSize()); 232 return this; 233 } 234 235 @Override setProduct(SmallValue value)236 public MutableElement setProduct(SmallValue value) { 237 BigInteger bigIntValue = ((SmallElement) value).asBigInteger(); 238 v = v.multiply(bigIntValue).mod(getSize()); 239 return this; 240 } 241 242 @Override setSum(IntegerModuloP b)243 public MutableElement setSum(IntegerModuloP b) { 244 Element other = (Element) b; 245 v = v.add(other.v).mod(getSize()); 246 return this; 247 } 248 249 @Override setDifference(IntegerModuloP b)250 public MutableElement setDifference(IntegerModuloP b) { 251 Element other = (Element) b; 252 v = v.subtract(other.v).mod(getSize()); 253 return this; 254 } 255 256 @Override setAdditiveInverse()257 public MutableElement setAdditiveInverse() { 258 v = BigInteger.ZERO.subtract(v); 259 return this; 260 } 261 262 @Override setReduced()263 public MutableElement setReduced() { 264 // do nothing 265 return this; 266 } 267 268 } 269 270 private class SmallElement extends ImmutableElement implements SmallValue { 271 SmallElement(int v)272 public SmallElement(int v) { 273 super(BigInteger.valueOf(v).mod(getSize())); 274 } 275 } 276 swap(byte[] arr, int i, int j)277 private static void swap(byte[] arr, int i, int j) { 278 byte tmp = arr[i]; 279 arr[i] = arr[j]; 280 arr[j] = tmp; 281 } 282 reverse(byte [] arr)283 private static void reverse(byte [] arr) { 284 int i = 0; 285 int j = arr.length - 1; 286 287 while (i < j) { 288 swap(arr, i, j); 289 i++; 290 j--; 291 } 292 } 293 294 } 295