//********************************************************* // // Copyright (c) Microsoft. All rights reserved. // This code is licensed under the Apache License Version 2.0. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. // //********************************************************* package com.microsoft.uprove; import java.io.IOException; import com.microsoft.uprove.FieldZq.ZqElement; class IssuerImpl implements Issuer { /** * Type-safe enum for the state machine. */ private static final class State { static final State INIT = new State("initial"); static final State COMPUTED = new State("precomputed"); static final State FIRST = new State("first message"); private final String name; private State(final String name) { super(); this.name = name; } public String toString() { return name; } } private int numberOfTokens; private IssuerCommonInput input; private ZqElement[] w; private GroupElement[] sigmaA; private GroupElement[] sigmaB; private PrimeOrderGroup Gq; private State state; public IssuerImpl(int numberOfTokens, IssuerCommonInput input) { if (numberOfTokens <= 0) { throw new IllegalArgumentException("numberOfTokens must be > 0"); } this.numberOfTokens = numberOfTokens; this.input = input; Gq = input.getGamma().getGroup(); // set the state this.state = State.INIT; } /** * Check to make sure we're in the proper state. * @param expected the expected state. * @throws IllegalStateException if the object is in the wrong state */ private void checkState(final State expected) { if (state != expected) { throw new IllegalStateException( "Invalid state. Expected \"" + expected + "\" was \"" + state + "\""); } } public void precomputation() throws IOException { precomputation(null); } public void precomputation(byte[][] preGenW) throws IOException { // check the state checkState(State.INIT); FieldZq Zq = Gq.getZq(); if (preGenW == null) { w = Zq.getRandomElements(numberOfTokens, false); } else { w = ProtocolHelper.getZqElementArray(Zq, preGenW); } sigmaA = new GroupElement[numberOfTokens]; sigmaB = new GroupElement[numberOfTokens]; for (int i=0; i<numberOfTokens; i++) { sigmaA[i] = Gq.getGenerator().exponentiate(w[i]); sigmaB[i] = input.getGamma().exponentiate(w[i]); } // advance the state state = State.COMPUTED; } public byte[][] generateFirstMessage() throws IOException { // check the state if (state == State.INIT) { precomputation(); } else { checkState(State.COMPUTED); } // advance the state state = State.FIRST; // return the sigmaA and sigmaB values byte[][] message1 = new byte[numberOfTokens*2][]; for (int i=0; i<numberOfTokens; i++) { message1[2*i] = sigmaA[i].toByteArray(); message1[2*i+1] = sigmaB[i].toByteArray(); } return message1; } public byte[][] generateThirdMessage(byte[][] message2) throws IOException { // check the state checkState(State.FIRST); // check message if (message2.length != numberOfTokens) { throw new IllegalArgumentException("wrong number of elements in message2"); } ZqElement[] sigmaC = ProtocolHelper.getZqElementArray(Gq.getZq(), message2); byte[][] sigmaR = new byte[numberOfTokens][]; for (int i=0; i<numberOfTokens; i++) { sigmaR[i] = sigmaC[i].multiply(input.getY0()).add(w[i]).toByteArray(); } return sigmaR; } }