All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.math.ec.custom.sec.SecT233Field Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. This jar contains APIs for JDK 1.5 and up. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.

There is a newer version: 1.2.2.1-jre17
Show newest version
package org.bouncycastle.math.ec.custom.sec;

import java.math.BigInteger;

import org.bouncycastle.math.raw.Interleave;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat256;

public class SecT233Field
{
    private static final long M41 = -1L >>> 23;
    private static final long M59 = -1L >>> 5;

    public static void add(long[] x, long[] y, long[] z)
    {
        z[0] = x[0] ^ y[0];
        z[1] = x[1] ^ y[1];
        z[2] = x[2] ^ y[2];
        z[3] = x[3] ^ y[3];
    }

    public static void addExt(long[] xx, long[] yy, long[] zz)
    {
        zz[0] = xx[0] ^ yy[0];
        zz[1] = xx[1] ^ yy[1];
        zz[2] = xx[2] ^ yy[2];
        zz[3] = xx[3] ^ yy[3];
        zz[4] = xx[4] ^ yy[4];
        zz[5] = xx[5] ^ yy[5];
        zz[6] = xx[6] ^ yy[6];
        zz[7] = xx[7] ^ yy[7];
    }

    public static void addOne(long[] x, long[] z)
    {
        z[0] = x[0] ^ 1L;
        z[1] = x[1];
        z[2] = x[2];
        z[3] = x[3];
    }

    private static void addTo(long[] x, long[] z)
    {
        z[0] ^= x[0];
        z[1] ^= x[1];
        z[2] ^= x[2];
        z[3] ^= x[3];
    }

    public static long[] fromBigInteger(BigInteger x)
    {
        return Nat.fromBigInteger64(233, x);
    }

    public static void halfTrace(long[] x, long[] z)
    {
        long[] tt = Nat256.createExt64();

        Nat256.copy64(x, z);
        for (int i = 1; i < 233; i += 2)
        {
            implSquare(z, tt);
            reduce(tt, z);
            implSquare(z, tt);
            reduce(tt, z);
            addTo(x, z);
        }
    }

    public static void invert(long[] x, long[] z)
    {
        if (Nat256.isZero64(x))
        {
            throw new IllegalStateException();
        }

        // Itoh-Tsujii inversion

        long[] t0 = Nat256.create64();
        long[] t1 = Nat256.create64();

        square(x, t0);
        multiply(t0, x, t0);
        square(t0, t0);
        multiply(t0, x, t0);
        squareN(t0, 3, t1);
        multiply(t1, t0, t1);
        square(t1, t1);
        multiply(t1, x, t1);
        squareN(t1, 7, t0);
        multiply(t0, t1, t0);
        squareN(t0, 14, t1);
        multiply(t1, t0, t1);
        square(t1, t1);
        multiply(t1, x, t1);
        squareN(t1, 29, t0);
        multiply(t0, t1, t0);
        squareN(t0, 58, t1);
        multiply(t1, t0, t1);
        squareN(t1, 116, t0);
        multiply(t0, t1, t0);
        square(t0, z);
    }

    public static void multiply(long[] x, long[] y, long[] z)
    {
        long[] tt = Nat256.createExt64();
        implMultiply(x, y, tt);
        reduce(tt, z);
    }

    public static void multiplyAddToExt(long[] x, long[] y, long[] zz)
    {
        long[] tt = Nat256.createExt64();
        implMultiply(x, y, tt);
        addExt(zz, tt, zz);
    }

    public static void reduce(long[] xx, long[] z)
    {
        long x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3];
        long x4 = xx[4], x5 = xx[5], x6 = xx[6], x7 = xx[7];

        x3 ^= (x7 <<  23);
        x4 ^= (x7 >>> 41) ^ (x7 <<  33);
        x5 ^= (x7 >>> 31);

        x2 ^= (x6 <<  23);
        x3 ^= (x6 >>> 41) ^ (x6 <<  33);
        x4 ^= (x6 >>> 31);

        x1 ^= (x5 <<  23);
        x2 ^= (x5 >>> 41) ^ (x5 <<  33);
        x3 ^= (x5 >>> 31);

        x0 ^= (x4 <<  23);
        x1 ^= (x4 >>> 41) ^ (x4 <<  33);
        x2 ^= (x4 >>> 31);

        long t = x3 >>> 41;
        z[0]   = x0 ^ t;
        z[1]   = x1 ^ (t << 10);
        z[2]   = x2;
        z[3]   = x3 & M41;
    }

    public static void reduce23(long[] z, int zOff)
    {
        long z3      = z[zOff + 3], t = z3 >>> 41;
        z[zOff    ] ^= t;
        z[zOff + 1] ^= (t << 10);
        z[zOff + 3]  = z3 & M41;
    }

    public static void sqrt(long[] x, long[] z)
    {
        long u0, u1;
        u0 = Interleave.unshuffle(x[0]); u1 = Interleave.unshuffle(x[1]);
        long e0 = (u0 & 0x00000000FFFFFFFFL) | (u1 << 32);
        long c0 = (u0 >>> 32) | (u1 & 0xFFFFFFFF00000000L);

        u0 = Interleave.unshuffle(x[2]); u1 = Interleave.unshuffle(x[3]);
        long e1 = (u0 & 0x00000000FFFFFFFFL) | (u1 << 32);
        long c1 = (u0 >>> 32) | (u1 & 0xFFFFFFFF00000000L);

        long c2;
        c2  = (c1 >>> 27);
        c1 ^= (c0 >>> 27) | (c1 << 37);
        c0 ^=               (c0 << 37);

        long[] tt = Nat256.createExt64();

        int[] shifts = { 32, 117, 191 };
        for (int i = 0; i < shifts.length; ++i)
        {
            int w = shifts[i] >>> 6, s = shifts[i] & 63;
//            assert s != 0;
            tt[w    ] ^= (c0 << s);
            tt[w + 1] ^= (c1 << s) | (c0 >>> -s);
            tt[w + 2] ^= (c2 << s) | (c1 >>> -s);
            tt[w + 3] ^=             (c2 >>> -s);
        }

        reduce(tt, z);

        z[0] ^= e0;
        z[1] ^= e1;
    }

    public static void square(long[] x, long[] z)
    {
        long[] tt = Nat256.createExt64();
        implSquare(x, tt);
        reduce(tt, z);
    }

    public static void squareAddToExt(long[] x, long[] zz)
    {
        long[] tt = Nat256.createExt64();
        implSquare(x, tt);
        addExt(zz, tt, zz);
    }

    public static void squareN(long[] x, int n, long[] z)
    {
//        assert n > 0;

        long[] tt = Nat256.createExt64();
        implSquare(x, tt);
        reduce(tt, z);

        while (--n > 0)
        {
            implSquare(z, tt);
            reduce(tt, z);
        }
    }

    public static int trace(long[] x)
    {
        // Non-zero-trace bits: 0, 159
        return (int)(x[0] ^ (x[2] >>> 31)) & 1;
    }

    protected static void implCompactExt(long[] zz)
    {
        long z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7];
        zz[0] =  z0         ^ (z1 << 59);
        zz[1] = (z1 >>>  5) ^ (z2 << 54);
        zz[2] = (z2 >>> 10) ^ (z3 << 49);
        zz[3] = (z3 >>> 15) ^ (z4 << 44);
        zz[4] = (z4 >>> 20) ^ (z5 << 39);
        zz[5] = (z5 >>> 25) ^ (z6 << 34);
        zz[6] = (z6 >>> 30) ^ (z7 << 29);
        zz[7] = (z7 >>> 35);
    }

    protected static void implExpand(long[] x, long[] z)
    {
        long x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
        z[0] = x0 & M59;
        z[1] = ((x0 >>> 59) ^ (x1 <<  5)) & M59;
        z[2] = ((x1 >>> 54) ^ (x2 << 10)) & M59;
        z[3] = ((x2 >>> 49) ^ (x3 << 15));
    }

    protected static void implMultiply(long[] x, long[] y, long[] zz)
    {
        /*
         * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein.
         */

        long[] f = new long[4], g = new long[4];
        implExpand(x, f);
        implExpand(y, g);

        long[] u = new long[8];

        implMulwAcc(u, f[0], g[0], zz, 0);
        implMulwAcc(u, f[1], g[1], zz, 1);
        implMulwAcc(u, f[2], g[2], zz, 2);
        implMulwAcc(u, f[3], g[3], zz, 3);

        // U *= (1 - t^n)
        for (int i = 5; i > 0; --i)
        {
            zz[i] ^= zz[i - 1];
        }

        implMulwAcc(u, f[0] ^ f[1], g[0] ^ g[1], zz, 1);
        implMulwAcc(u, f[2] ^ f[3], g[2] ^ g[3], zz, 3);

        // V *= (1 - t^2n)
        for (int i = 7; i > 1; --i)
        {
            zz[i] ^= zz[i - 2];
        }

        // Double-length recursion
        {
            long c0 = f[0] ^ f[2], c1 = f[1] ^ f[3];
            long d0 = g[0] ^ g[2], d1 = g[1] ^ g[3];
            implMulwAcc(u, c0 ^ c1, d0 ^ d1, zz, 3);
            long[] t = new long[3];
            implMulwAcc(u, c0, d0, t, 0);
            implMulwAcc(u, c1, d1, t, 1);
            long t0 = t[0], t1 = t[1], t2 = t[2];
            zz[2] ^= t0;
            zz[3] ^= t0 ^ t1;
            zz[4] ^= t2 ^ t1;
            zz[5] ^= t2;
        }

        implCompactExt(zz);
    }

    protected static void implMulwAcc(long[] u, long x, long y, long[] z, int zOff)
    {
//        assert x >>> 59 == 0;
//        assert y >>> 59 == 0;

//      u[0] = 0;
        u[1] = y;
        u[2] = u[1] << 1;
        u[3] = u[2] ^  y;
        u[4] = u[2] << 1;
        u[5] = u[4] ^  y;
        u[6] = u[3] << 1;
        u[7] = u[6] ^  y;

        int j = (int)x;
        long g, h = 0, l = u[j & 7]
                         ^ (u[(j >>> 3) & 7] << 3);
        int k = 54;
        do
        {
            j  = (int)(x >>> k);
            g  = u[j & 7]
               ^ u[(j >>> 3) & 7] << 3;
            l ^= (g <<   k);
            h ^= (g >>> -k);
        }
        while ((k -= 6) > 0);

//        assert h >>> 53 == 0;

        z[zOff    ] ^= l & M59;
        z[zOff + 1] ^= (l >>> 59) ^ (h << 5);
    }

    protected static void implSquare(long[] x, long[] zz)
    {
        Interleave.expand64To128(x, 0, 4, zz, 0);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy