// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.crypto.agreement.ecjpake;

import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Strings;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.util.BigIntegers;
import java.security.SecureRandom;
import java.math.BigInteger;

public class ECJPAKEUtil
{
    static final BigInteger ZERO;
    static final BigInteger ONE;
    
    public static BigInteger generateX1(final BigInteger bigInteger, final SecureRandom secureRandom) {
        return BigIntegers.createRandomInRange(ECJPAKEUtil.ONE, bigInteger.subtract(ECJPAKEUtil.ONE), secureRandom);
    }
    
    public static BigInteger calculateS(final BigInteger m, final byte[] magnitude) throws CryptoException {
        final BigInteger mod = new BigInteger(1, magnitude).mod(m);
        if (mod.signum() == 0) {
            throw new CryptoException("MUST ensure s is not equal to 0 modulo n");
        }
        return mod;
    }
    
    public static BigInteger calculateS(final BigInteger bigInteger, final char[] array) throws CryptoException {
        return calculateS(bigInteger, Strings.toUTF8ByteArray(array));
    }
    
    public static ECPoint calculateGx(final ECPoint ecPoint, final BigInteger bigInteger) {
        return ecPoint.multiply(bigInteger);
    }
    
    public static ECPoint calculateGA(final ECPoint ecPoint, final ECPoint ecPoint2, final ECPoint ecPoint3) {
        return ecPoint.add(ecPoint2).add(ecPoint3);
    }
    
    public static BigInteger calculateX2s(final BigInteger m, final BigInteger bigInteger, final BigInteger val) {
        return bigInteger.multiply(val).mod(m);
    }
    
    public static ECPoint calculateA(final ECPoint ecPoint, final BigInteger bigInteger) {
        return ecPoint.multiply(bigInteger);
    }
    
    public static ECSchnorrZKP calculateZeroKnowledgeProof(final ECPoint ecPoint, final BigInteger m, final BigInteger bigInteger, final ECPoint ecPoint2, final Digest digest, final String s, final SecureRandom secureRandom) {
        final BigInteger randomInRange = BigIntegers.createRandomInRange(BigInteger.ONE, m.subtract(BigInteger.ONE), secureRandom);
        final ECPoint multiply = ecPoint.multiply(randomInRange);
        return new ECSchnorrZKP(multiply, randomInRange.subtract(bigInteger.multiply(calculateHashForZeroKnowledgeProof(ecPoint, multiply, ecPoint2, s, digest))).mod(m));
    }
    
    private static BigInteger calculateHashForZeroKnowledgeProof(final ECPoint ecPoint, final ECPoint ecPoint2, final ECPoint ecPoint3, final String s, final Digest digest) {
        digest.reset();
        updateDigestIncludingSize(digest, ecPoint);
        updateDigestIncludingSize(digest, ecPoint2);
        updateDigestIncludingSize(digest, ecPoint3);
        updateDigestIncludingSize(digest, s);
        final byte[] val = new byte[digest.getDigestSize()];
        digest.doFinal(val, 0);
        return new BigInteger(val);
    }
    
    private static void updateDigestIncludingSize(final Digest digest, final ECPoint ecPoint) {
        final byte[] encoded = ecPoint.getEncoded(true);
        digest.update(intToByteArray(encoded.length), 0, 4);
        digest.update(encoded, 0, encoded.length);
        Arrays.fill(encoded, (byte)0);
    }
    
    private static void updateDigestIncludingSize(final Digest digest, final String s) {
        final byte[] utf8ByteArray = Strings.toUTF8ByteArray(s);
        digest.update(intToByteArray(utf8ByteArray.length), 0, 4);
        digest.update(utf8ByteArray, 0, utf8ByteArray.length);
        Arrays.fill(utf8ByteArray, (byte)0);
    }
    
    public static void validateZeroKnowledgeProof(final ECPoint ecPoint, final ECPoint ecPoint2, final ECSchnorrZKP ecSchnorrZKP, final BigInteger bigInteger, final BigInteger m, final ECCurve ecCurve, final BigInteger bigInteger2, final String s, final Digest digest) throws CryptoException {
        final ECPoint v = ecSchnorrZKP.getV();
        final BigInteger getr = ecSchnorrZKP.getr();
        final BigInteger calculateHashForZeroKnowledgeProof = calculateHashForZeroKnowledgeProof(ecPoint, v, ecPoint2, s, digest);
        if (ecPoint2.isInfinity()) {
            throw new CryptoException("Zero-knowledge proof validation failed: X cannot equal infinity");
        }
        final ECPoint normalize = ecPoint2.normalize();
        if (normalize.getAffineXCoord().toBigInteger().signum() < 0 || normalize.getAffineXCoord().toBigInteger().compareTo(bigInteger) >= 0 || normalize.getAffineYCoord().toBigInteger().signum() < 0 || normalize.getAffineYCoord().toBigInteger().compareTo(bigInteger) >= 0) {
            throw new CryptoException("Zero-knowledge proof validation failed: x and y are not in the field");
        }
        try {
            ecCurve.decodePoint(ecPoint2.getEncoded(true));
        }
        catch (final Exception ex) {
            throw new CryptoException("Zero-knowledge proof validation failed: x does not lie on the curve", ex);
        }
        if (ecPoint2.multiply(bigInteger2).isInfinity()) {
            throw new CryptoException("Zero-knowledge proof validation failed: Nx cannot be infinity");
        }
        if (!v.equals(ecPoint.multiply(getr).add(ecPoint2.multiply(calculateHashForZeroKnowledgeProof.mod(m))))) {
            throw new CryptoException("Zero-knowledge proof validation failed: V must be a point on the curve");
        }
    }
    
    public static void validateParticipantIdsDiffer(final String str, final String anObject) throws CryptoException {
        if (str.equals(anObject)) {
            throw new CryptoException("Both participants are using the same participantId (" + str + "). This is not allowed. Each participant must use a unique participantId.");
        }
    }
    
    public static void validateParticipantIdsEqual(final String str, final String s) throws CryptoException {
        if (!str.equals(s)) {
            throw new CryptoException("Received payload from incorrect partner (" + s + "). Expected to receive payload from " + str + ".");
        }
    }
    
    public static void validateNotNull(final Object o, final String str) {
        if (o == null) {
            throw new NullPointerException(str + " must not be null");
        }
    }
    
    public static BigInteger calculateKeyingMaterial(final BigInteger m, final ECPoint ecPoint, final BigInteger bigInteger, final BigInteger val, final ECPoint ecPoint2) {
        return ecPoint2.subtract(ecPoint.multiply(bigInteger.multiply(val).mod(m))).multiply(bigInteger).normalize().getAffineXCoord().toBigInteger();
    }
    
    public static BigInteger calculateMacTag(final String s, final String s2, final ECPoint ecPoint, final ECPoint ecPoint2, final ECPoint ecPoint3, final ECPoint ecPoint4, final BigInteger bigInteger, final Digest digest) {
        final byte[] calculateMacKey = calculateMacKey(bigInteger, digest);
        final HMac hMac = new HMac(digest);
        final byte[] val = new byte[hMac.getMacSize()];
        hMac.init(new KeyParameter(calculateMacKey));
        updateMac(hMac, "KC_1_U");
        updateMac(hMac, s);
        updateMac(hMac, s2);
        updateMac(hMac, ecPoint);
        updateMac(hMac, ecPoint2);
        updateMac(hMac, ecPoint3);
        updateMac(hMac, ecPoint4);
        hMac.doFinal(val, 0);
        Arrays.fill(calculateMacKey, (byte)0);
        return new BigInteger(val);
    }
    
    private static byte[] calculateMacKey(final BigInteger bigInteger, final Digest digest) {
        digest.reset();
        updateDigest(digest, bigInteger);
        updateDigest(digest, "ECJPAKE_KC");
        final byte[] array = new byte[digest.getDigestSize()];
        digest.doFinal(array, 0);
        return array;
    }
    
    public static void validateMacTag(final String s, final String s2, final ECPoint ecPoint, final ECPoint ecPoint2, final ECPoint ecPoint3, final ECPoint ecPoint4, final BigInteger bigInteger, final Digest digest, final BigInteger x) throws CryptoException {
        if (!calculateMacTag(s2, s, ecPoint3, ecPoint4, ecPoint, ecPoint2, bigInteger, digest).equals(x)) {
            throw new CryptoException("Partner MacTag validation failed. Therefore, the password, MAC, or digest algorithm of each participant does not match.");
        }
    }
    
    private static void updateMac(final Mac mac, final ECPoint ecPoint) {
        final byte[] encoded = ecPoint.getEncoded(true);
        mac.update(encoded, 0, encoded.length);
        Arrays.fill(encoded, (byte)0);
    }
    
    private static void updateMac(final Mac mac, final String s) {
        final byte[] utf8ByteArray = Strings.toUTF8ByteArray(s);
        mac.update(utf8ByteArray, 0, utf8ByteArray.length);
        Arrays.fill(utf8ByteArray, (byte)0);
    }
    
    private static void updateDigest(final Digest digest, final ECPoint ecPoint) {
        final byte[] encoded = ecPoint.getEncoded(true);
        digest.update(encoded, 0, encoded.length);
        Arrays.fill(encoded, (byte)0);
    }
    
    private static void updateDigest(final Digest digest, final String s) {
        final byte[] utf8ByteArray = Strings.toUTF8ByteArray(s);
        digest.update(utf8ByteArray, 0, utf8ByteArray.length);
        Arrays.fill(utf8ByteArray, (byte)0);
    }
    
    private static void updateDigest(final Digest digest, final BigInteger bigInteger) {
        final byte[] unsignedByteArray = BigIntegers.asUnsignedByteArray(bigInteger);
        digest.update(unsignedByteArray, 0, unsignedByteArray.length);
        Arrays.fill(unsignedByteArray, (byte)0);
    }
    
    private static byte[] intToByteArray(final int n) {
        return new byte[] { (byte)(n >>> 24), (byte)(n >>> 16), (byte)(n >>> 8), (byte)n };
    }
    
    static {
        ZERO = BigInteger.valueOf(0L);
        ONE = BigInteger.valueOf(1L);
    }
}
