Path: blob/master/test/jdk/sun/security/util/math/BigIntegerModuloP.java
41152 views
/*1* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425import sun.security.util.math.*;2627import java.math.BigInteger;28import java.nio.ByteBuffer;29import java.util.Arrays;30import java.util.Optional;3132/**33* Arithmetic in the field of integers modulo a prime value implemented using34* BigInteger. This implementation is very versatile, but it is slow and none35* of the operations are value-independent. This class is intended for use in36* testing and prototyping, and production code should probably use a more37* specialized arithmetic implementation.38*/3940public class BigIntegerModuloP implements IntegerFieldModuloP {4142private final BigInteger p;4344public BigIntegerModuloP(BigInteger p) {45this.p = p;46}4748@Override49public BigInteger getSize() {50return p;51}5253@Override54public ImmutableElement get0() {55return new ImmutableElement(BigInteger.ZERO);56}57@Override58public ImmutableElement get1() {59return new ImmutableElement(BigInteger.ONE);60}61@Override62public ImmutableElement getElement(BigInteger v) {63return new ImmutableElement(v);64}65@Override66public ImmutableElement getElement(byte[] v, int offset, int length,67byte highByte) {68byte[] bigIntIn = new byte[length + 1];69System.arraycopy(v, offset, bigIntIn, 0, length);70bigIntIn[length] = highByte;71reverse(bigIntIn);72return new ImmutableElement(new BigInteger(1, bigIntIn).mod(getSize()));73}74@Override75public SmallValue getSmallValue(int i) {76return new SmallElement(i);77}7879private abstract class Element implements IntegerModuloP {8081protected BigInteger v;8283protected Element(BigInteger v) {84this.v = v;85}8687protected Element(boolean v) {88this.v = BigInteger.valueOf(v ? 1 : 0);89}9091private BigInteger getModulus() {92return getField().getSize();93}9495@Override96public IntegerFieldModuloP getField() {97return BigIntegerModuloP.this;98}99100@Override101public BigInteger asBigInteger() {102return v;103}104105@Override106public MutableElement mutable() {107return new MutableElement(v);108}109110@Override111public ImmutableElement fixed() {112return new ImmutableElement(v);113}114115@Override116public ImmutableElement add(IntegerModuloP b) {117return new ImmutableElement(118v.add(b.asBigInteger()).mod(getModulus()));119}120121@Override122public ImmutableElement additiveInverse() {123return new ImmutableElement(v.negate().mod(getModulus()));124}125126@Override127public ImmutableElement multiply(IntegerModuloP b) {128return new ImmutableElement(129v.multiply(b.asBigInteger()).mod(getModulus()));130}131132@Override133public void addModPowerTwo(IntegerModuloP arg, byte[] result) {134BigInteger biThis = asBigInteger();135BigInteger biArg = arg.asBigInteger();136bigIntAsByteArray(biThis.add(biArg), result);137}138139private void bigIntAsByteArray(BigInteger arg, byte[] result) {140byte[] bytes = arg.toByteArray();141// bytes is backwards and possibly too big142// Copy the low-order bytes into result in reverse143int sourceIndex = bytes.length - 1;144for (int i = 0; i < result.length; i++) {145if (sourceIndex >= 0) {146result[i] = bytes[sourceIndex--];147} else {148result[i] = 0;149}150}151}152153@Override154public void asByteArray(byte[] result) {155bigIntAsByteArray(v, result);156}157}158159private class ImmutableElement extends Element160implements ImmutableIntegerModuloP {161162private ImmutableElement(BigInteger v) {163super(v);164}165}166167private class MutableElement extends Element168implements MutableIntegerModuloP {169170private MutableElement(BigInteger v) {171super(v);172}173174@Override175public void conditionalSet(IntegerModuloP b, int set) {176if (set == 1) {177v = b.asBigInteger();178}179}180181@Override182public void conditionalSwapWith(MutableIntegerModuloP b, int swap) {183if (swap == 1) {184BigInteger temp = v;185v = b.asBigInteger();186((Element) b).v = temp;187}188}189190@Override191public MutableElement setValue(IntegerModuloP v) {192this.v = ((Element) v).v;193194return this;195}196197@Override198public MutableElement setValue(byte[] arr, int offset, int length,199byte highByte) {200byte[] bigIntIn = new byte[length + 1];201System.arraycopy(arr, offset, bigIntIn, 0, length);202bigIntIn[length] = highByte;203reverse(bigIntIn);204v = new BigInteger(bigIntIn).mod(getSize());205206return this;207}208209@Override210public MutableElement setValue(ByteBuffer buf, int length,211byte highByte) {212byte[] bigIntIn = new byte[length + 1];213buf.get(bigIntIn, 0, length);214bigIntIn[length] = highByte;215reverse(bigIntIn);216v = new BigInteger(bigIntIn).mod(getSize());217218return this;219}220221@Override222public MutableElement setSquare() {223v = v.multiply(v).mod(getSize());224return this;225}226227@Override228public MutableElement setProduct(IntegerModuloP b) {229Element other = (Element) b;230v = v.multiply(other.v).mod(getSize());231return this;232}233234@Override235public MutableElement setProduct(SmallValue value) {236BigInteger bigIntValue = ((SmallElement) value).asBigInteger();237v = v.multiply(bigIntValue).mod(getSize());238return this;239}240241@Override242public MutableElement setSum(IntegerModuloP b) {243Element other = (Element) b;244v = v.add(other.v).mod(getSize());245return this;246}247248@Override249public MutableElement setDifference(IntegerModuloP b) {250Element other = (Element) b;251v = v.subtract(other.v).mod(getSize());252return this;253}254255@Override256public MutableElement setAdditiveInverse() {257v = BigInteger.ZERO.subtract(v);258return this;259}260261@Override262public MutableElement setReduced() {263// do nothing264return this;265}266267}268269private class SmallElement extends ImmutableElement implements SmallValue {270271public SmallElement(int v) {272super(BigInteger.valueOf(v).mod(getSize()));273}274}275276private static void swap(byte[] arr, int i, int j) {277byte tmp = arr[i];278arr[i] = arr[j];279arr[j] = tmp;280}281282private static void reverse(byte [] arr) {283int i = 0;284int j = arr.length - 1;285286while (i < j) {287swap(arr, i, j);288i++;289j--;290}291}292293}294295296