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

package org.bouncycastle.math.ec.rfc7748;

import org.bouncycastle.math.ec.rfc8032.Ed25519;
import java.security.SecureRandom;
import org.bouncycastle.util.Arrays;

public abstract class X25519
{
    public static final int POINT_SIZE = 32;
    public static final int SCALAR_SIZE = 32;
    private static final int C_A = 486662;
    private static final int C_A24 = 121666;
    
    public static boolean calculateAgreement(final byte[] array, final int n, final byte[] array2, final int n2, final byte[] array3, final int n3) {
        scalarMult(array, n, array2, n2, array3, n3);
        return !Arrays.areAllZeroes(array3, n3, 32);
    }
    
    public static void clampPrivateKey(final byte[] array) {
        if (array.length != 32) {
            throw new IllegalArgumentException("k");
        }
        final int n = 0;
        array[n] &= (byte)248;
        final int n2 = 31;
        array[n2] &= 0x7F;
        final int n3 = 31;
        array[n3] |= 0x40;
    }
    
    private static int decode32(final byte[] array, int n) {
        return (array[n] & 0xFF) | (array[++n] & 0xFF) << 8 | (array[++n] & 0xFF) << 16 | array[++n] << 24;
    }
    
    private static void decodeScalar(final byte[] array, final int n, final int[] array2) {
        for (int i = 0; i < 8; ++i) {
            array2[i] = decode32(array, n + i * 4);
        }
        final int n2 = 0;
        array2[n2] &= 0xFFFFFFF8;
        final int n3 = 7;
        array2[n3] &= Integer.MAX_VALUE;
        final int n4 = 7;
        array2[n4] |= 0x40000000;
    }
    
    public static void generatePrivateKey(final SecureRandom secureRandom, final byte[] bytes) {
        if (bytes.length != 32) {
            throw new IllegalArgumentException("k");
        }
        secureRandom.nextBytes(bytes);
        clampPrivateKey(bytes);
    }
    
    public static void generatePublicKey(final byte[] array, final int n, final byte[] array2, final int n2) {
        scalarMultBase(array, n, array2, n2);
    }
    
    private static void pointDouble(final int[] array, final int[] array2) {
        final int[] create = X25519Field.create();
        final int[] create2 = X25519Field.create();
        X25519Field.apm(array, array2, create, create2);
        X25519Field.sqr(create, create);
        X25519Field.sqr(create2, create2);
        X25519Field.mul(create, create2, array);
        X25519Field.sub(create, create2, create);
        X25519Field.mul(create, 121666, array2);
        X25519Field.add(array2, create2, array2);
        X25519Field.mul(array2, create, array2);
    }
    
    public static void precompute() {
        Ed25519.precompute();
    }
    
    public static void scalarMult(final byte[] array, final int n, final byte[] array2, final int n2, final byte[] array3, final int n3) {
        final int[] array4 = new int[8];
        decodeScalar(array, n, array4);
        final int[] create = X25519Field.create();
        X25519Field.decode(array2, n2, create);
        final int[] create2 = X25519Field.create();
        X25519Field.copy(create, 0, create2, 0);
        final int[] create3 = X25519Field.create();
        create3[0] = 1;
        final int[] create4 = X25519Field.create();
        create4[0] = 1;
        final int[] create5 = X25519Field.create();
        final int[] create6 = X25519Field.create();
        final int[] create7 = X25519Field.create();
        int i = 254;
        int n4 = 1;
        do {
            X25519Field.apm(create4, create5, create6, create4);
            X25519Field.apm(create2, create3, create5, create2);
            X25519Field.mul(create6, create2, create6);
            X25519Field.mul(create4, create5, create4);
            X25519Field.sqr(create5, create5);
            X25519Field.sqr(create2, create2);
            X25519Field.sub(create5, create2, create7);
            X25519Field.mul(create7, 121666, create3);
            X25519Field.add(create3, create2, create3);
            X25519Field.mul(create3, create7, create3);
            X25519Field.mul(create2, create5, create2);
            X25519Field.apm(create6, create4, create4, create5);
            X25519Field.sqr(create4, create4);
            X25519Field.sqr(create5, create5);
            X25519Field.mul(create5, create, create5);
            final int n5 = array4[--i >>> 5] >>> (i & 0x1F) & 0x1;
            final int n6 = n4 ^ n5;
            X25519Field.cswap(n6, create2, create4);
            X25519Field.cswap(n6, create3, create5);
            n4 = n5;
        } while (i >= 3);
        for (int j = 0; j < 3; ++j) {
            pointDouble(create2, create3);
        }
        X25519Field.inv(create3, create3);
        X25519Field.mul(create2, create3, create2);
        X25519Field.normalize(create2);
        X25519Field.encode(create2, array3, n3);
    }
    
    public static void scalarMultBase(final byte[] array, final int n, final byte[] array2, final int n2) {
        final int[] create = X25519Field.create();
        final int[] create2 = X25519Field.create();
        Ed25519.scalarMultBaseYZ(Friend.INSTANCE, array, n, create, create2);
        X25519Field.apm(create2, create, create, create2);
        X25519Field.inv(create2, create2);
        X25519Field.mul(create, create2, create);
        X25519Field.normalize(create);
        X25519Field.encode(create, array2, n2);
    }
    
    private static class F extends X25519Field
    {
    }
    
    public static class Friend
    {
        private static final Friend INSTANCE;
        
        private Friend() {
        }
        
        static {
            INSTANCE = new Friend();
        }
    }
}
