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

org.apache.milagro.amcl.BLS48.ECP8 Maven / Gradle / Ivy

The newest version!
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

/* AMCL Weierstrass elliptic curve functions over FP8 */

package org.apache.milagro.amcl.BLS48;

public final class ECP8 {
	private FP8 x;
	private FP8 y;
	private FP8 z;
//	private boolean INF;

/* Constructor - set this=O */
	public ECP8() {
//		INF=true;
		x=new FP8(0);
		y=new FP8(1);
		z=new FP8(0);
	}

    public ECP8(ECP8 e) {
        this.x = new FP8(e.x);
        this.y = new FP8(e.y);
        this.z = new FP8(e.z);
    }

/* Test this=O? */
	public boolean is_infinity() {
//		if (INF) return true;                    //******
		return (x.iszilch() && z.iszilch());
	}
/* copy this=P */
	public void copy(ECP8 P)
	{
		x.copy(P.x);
		y.copy(P.y);
		z.copy(P.z);
//		INF=P.INF;
	}
/* set this=O */
	public void inf() {
//		INF=true;
		x.zero();
		y.one();
		z.zero();
	}

/* Conditional move of Q to P dependant on d */
	public void cmove(ECP8 Q,int d)
	{
		x.cmove(Q.x,d);
		y.cmove(Q.y,d);
		z.cmove(Q.z,d);

//		boolean bd;
//		if (d==0) bd=false;
//		else bd=true;
//		INF^=(INF^Q.INF)&bd;
	}

/* return 1 if b==c, no branching */
	public static int teq(int b,int c)
	{
		int x=b^c;
		x-=1;  // if x=0, x now -1
		return ((x>>31)&1);
	}

/* Constant time select from pre-computed table */
	public void select(ECP8 W[],int b)
	{
		ECP8 MP=new ECP8(); 
		int m=b>>31;
		int babs=(b^m)-m;

		babs=(babs-1)/2;

		cmove(W[0],teq(babs,0));  // conditional move
		cmove(W[1],teq(babs,1));
		cmove(W[2],teq(babs,2));
		cmove(W[3],teq(babs,3));
		cmove(W[4],teq(babs,4));
		cmove(W[5],teq(babs,5));
		cmove(W[6],teq(babs,6));
		cmove(W[7],teq(babs,7));
 
		MP.copy(this);
		MP.neg();
		cmove(MP,(int)(m&1));
	}

/* Test if P == Q */
	public boolean equals(ECP8 Q) {
//		if (is_infinity() && Q.is_infinity()) return true;
//		if (is_infinity() || Q.is_infinity()) return false;


		FP8 a=new FP8(x);                            // *****
		FP8 b=new FP8(Q.x);
		a.mul(Q.z); 
		b.mul(z); 
		if (!a.equals(b)) return false;

		a.copy(y); a.mul(Q.z); 
		b.copy(Q.y); b.mul(z); 
		if (!a.equals(b)) return false;

		return true;
	}

/* set this=-this */
	public void neg() {
//		if (is_infinity()) return;
		y.norm();
		y.neg(); y.norm();
		return;
	}
/* set to Affine - (x,y,z) to (x,y) */
	public void affine() {
		if (is_infinity()) return;
		FP8 one=new FP8(1);
		if (z.equals(one))
		{
			x.reduce();
			y.reduce();
			return;
		}
		z.inverse();

		x.mul(z); x.reduce();               // *****
		y.mul(z); y.reduce();
		z.copy(one);
	}

/* extract affine x as FP8 */
	public FP8 getX()
	{
		ECP8 W= new ECP8(this);
		W.affine();
		return W.x;
	}
/* extract affine y as FP8 */
	public FP8 getY()
	{
		ECP8 W= new ECP8(this);
		W.affine();
		return W.y;
	}
/* extract projective x */
	public FP8 getx()
	{
		return x;
	}
/* extract projective y */
	public FP8 gety()
	{
		return y;
	}
/* extract projective z */
	public FP8 getz()
	{
		return z;
	}

/* convert to byte array */
	public void toBytes(byte[] b)
	{
		byte[] t=new byte[BIG.MODBYTES];
		ECP8 W=new ECP8(this);
		W.affine();
		int MB=BIG.MODBYTES;

		W.x.geta().geta().getA().toBytes(t);
		for (int i=0;i=0;i--)
		{
			Q.select(W,w[i]);
			P.dbl();
			P.dbl();
			P.dbl();
			P.dbl();
			P.add(Q);
		}
		P.sub(C);
		P.affine();
		return P;
	}

/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... */
// Bos & Costello https://eprint.iacr.org/2013/458.pdf
// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
// Side channel attack secure 

	public static ECP8 mul16(ECP8[] Q,BIG[] u)
	{
		int i,j,k,nb,pb1,pb2,pb3,pb4;
		ECP8 W=new ECP8();
		ECP8 P=new ECP8();
		ECP8[] T1=new ECP8[8];
		ECP8[] T2=new ECP8[8];
		ECP8[] T3=new ECP8[8];
		ECP8[] T4=new ECP8[8];

		BIG mt=new BIG();
		BIG[] t=new BIG[16];

		byte[] w1=new byte[BIG.NLEN*BIG.BASEBITS+1];
		byte[] s1=new byte[BIG.NLEN*BIG.BASEBITS+1];
		byte[] w2=new byte[BIG.NLEN*BIG.BASEBITS+1];
		byte[] s2=new byte[BIG.NLEN*BIG.BASEBITS+1];
		byte[] w3=new byte[BIG.NLEN*BIG.BASEBITS+1];
		byte[] s3=new byte[BIG.NLEN*BIG.BASEBITS+1];
		byte[] w4=new byte[BIG.NLEN*BIG.BASEBITS+1];
		byte[] s4=new byte[BIG.NLEN*BIG.BASEBITS+1];

		for (i=0;i<16;i++)
		{
			t[i]=new BIG(u[i]);
			//Q[i].affine();
			t[i].norm();
		}

        T1[0] = new ECP8(); T1[0].copy(Q[0]);  // Q[0]
        T1[1] = new ECP8(); T1[1].copy(T1[0]); T1[1].add(Q[1]);  // Q[0]+Q[1]
        T1[2] = new ECP8(); T1[2].copy(T1[0]); T1[2].add(Q[2]);  // Q[0]+Q[2]
        T1[3] = new ECP8(); T1[3].copy(T1[1]); T1[3].add(Q[2]);  // Q[0]+Q[1]+Q[2]
        T1[4] = new ECP8(); T1[4].copy(T1[0]); T1[4].add(Q[3]);  // Q[0]+Q[3]
        T1[5] = new ECP8(); T1[5].copy(T1[1]); T1[5].add(Q[3]);  // Q[0]+Q[1]+Q[3]
        T1[6] = new ECP8(); T1[6].copy(T1[2]); T1[6].add(Q[3]);  // Q[0]+Q[2]+Q[3]
        T1[7] = new ECP8(); T1[7].copy(T1[3]); T1[7].add(Q[3]);  // Q[0]+Q[1]+Q[2]+Q[3]

//  Use Frobenius 
		FP2[] F=ECP8.frob_constants();

		for (i=0;i<8;i++) {
			T2[i] = new ECP8(); T2[i].copy(T1[i]);
			T2[i].frob(F,4);
			T3[i] = new ECP8(); T3[i].copy(T2[i]);
			T3[i].frob(F,4);
			T4[i] = new ECP8(); T4[i].copy(T3[i]);
			T4[i].frob(F,4);

		}

    // Make it odd
        pb1=1-t[0].parity();
        t[0].inc(pb1);
        t[0].norm();

        pb2=1-t[4].parity();
        t[4].inc(pb2);
        t[4].norm();

        pb3=1-t[8].parity();
        t[8].inc(pb3);
        t[8].norm();

        pb4=1-t[12].parity();
        t[12].inc(pb4);
        t[12].norm();

    // Number of bits
        mt.zero();
        for (i=0;i<16;i++) {
            mt.or(t[i]);
        }
        nb=1+mt.nbits();

    // Sign pivot 
        s1[nb-1]=1;
		s2[nb-1]=1;
        s3[nb-1]=1;
		s4[nb-1]=1;
        for (i=0;i>1);
                t[j].norm();
                w1[i]+=bt*(byte)k;
                k*=2;
            }

            w2[i]=0;
            k=1;
            for (j=5; j<8; j++) {
                byte bt=(byte)(s2[i]*t[j].parity());
                t[j].fshr(1);
                t[j].dec((int)(bt)>>1);
                t[j].norm();
                w2[i]+=bt*(byte)k;
                k*=2;
            }

            w3[i]=0;
            k=1;
            for (j=9; j<12; j++) {
                byte bt=(byte)(s3[i]*t[j].parity());
                t[j].fshr(1);
                t[j].dec((int)(bt)>>1);
                t[j].norm();
                w3[i]+=bt*(byte)k;
                k*=2;
            }

            w4[i]=0;
            k=1;
            for (j=13; j<16; j++) {
                byte bt=(byte)(s4[i]*t[j].parity());
                t[j].fshr(1);
                t[j].dec((int)(bt)>>1);
                t[j].norm();
                w4[i]+=bt*(byte)k;
                k*=2;
            }

        } 

    // Main loop
        P.select(T1,(int)(2*w1[nb-1]+1));  
		W.select(T2,(int)(2*w2[nb-1]+1)); 
		P.add(W);
		W.select(T3,(int)(2*w3[nb-1]+1));
		P.add(W);
		W.select(T4,(int)(2*w4[nb-1]+1));
		P.add(W);
        for (i=nb-2;i>=0;i--) {
            P.dbl();
            W.select(T1,(int)(2*w1[i]+s1[i]));
            P.add(W);
            W.select(T2,(int)(2*w2[i]+s2[i]));
            P.add(W);
            W.select(T3,(int)(2*w3[i]+s3[i]));
            P.add(W);
            W.select(T4,(int)(2*w4[i]+s4[i]));
            P.add(W);

        }

    // apply correction
        W.copy(P);   
        W.sub(Q[0]);
        P.cmove(W,pb1);   

        W.copy(P);   
        W.sub(Q[4]);
        P.cmove(W,pb2);  

        W.copy(P);   
        W.sub(Q[8]);
        P.cmove(W,pb3);   

        W.copy(P);   
        W.sub(Q[12]);
        P.cmove(W,pb4);  

		P.affine();
		return P;
	}        

/* needed for SOK */
	public static ECP8 mapit(byte[] h)
	{
		BIG q=new BIG(ROM.Modulus);
		BIG x=BIG.fromBytes(h);
		BIG one=new BIG(1);
		FP8 X;
		FP2 X2;
		FP4 X4;
		ECP8 Q;
		x.mod(q);
		while (true)
		{
			X2=new FP2(one,x);
			X4=new FP4(X2);
			X=new FP8(X4);
			Q=new ECP8(X);
			if (!Q.is_infinity()) break;
			x.inc(1); x.norm();
		}

		FP2[] F=ECP8.frob_constants();
		x=new BIG(ROM.CURVE_Bnx);

/* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */

		ECP8 xQ=Q.mul(x);
		ECP8 x2Q=xQ.mul(x);
		ECP8 x3Q=x2Q.mul(x);
		ECP8 x4Q=x3Q.mul(x);
		ECP8 x5Q=x4Q.mul(x);
		ECP8 x6Q=x5Q.mul(x);
		ECP8 x7Q=x6Q.mul(x);
		ECP8 x8Q=x7Q.mul(x);

		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
		{
			xQ.neg();
			x3Q.neg();
			x5Q.neg();
			x7Q.neg();
		}	

		x8Q.sub(x7Q);
		x8Q.sub(Q);

		x7Q.sub(x6Q);
		x7Q.frob(F,1);

		x6Q.sub(x5Q);
		x6Q.frob(F,2);

		x5Q.sub(x4Q);
		x5Q.frob(F,3);

		x4Q.sub(x3Q);
		x4Q.frob(F,4);

		x3Q.sub(x2Q);
		x3Q.frob(F,5);

		x2Q.sub(xQ);
		x2Q.frob(F,6);

		xQ.sub(Q);
		xQ.frob(F,7);

		Q.dbl();
		Q.frob(F,8);

		Q.add(x8Q);
		Q.add(x7Q);
		Q.add(x6Q);
		Q.add(x5Q);

		Q.add(x4Q);
		Q.add(x3Q);
		Q.add(x2Q);
		Q.add(xQ);

		Q.affine();
		return Q;
	}

	public static ECP8 generator()
	{
		return new ECP8(
			new FP8(
				new FP4(
					new FP2(
						new BIG(ROM.CURVE_Pxaaa),new BIG(ROM.CURVE_Pxaab)),
					new FP2(
						new BIG(ROM.CURVE_Pxaba),new BIG(ROM.CURVE_Pxabb))),
				new FP4(
					new FP2(
						new BIG(ROM.CURVE_Pxbaa),new BIG(ROM.CURVE_Pxbab)),
					new FP2(
						new BIG(ROM.CURVE_Pxbba),new BIG(ROM.CURVE_Pxbbb)))),
			new FP8(
				new FP4(
					new FP2(
						new BIG(ROM.CURVE_Pyaaa),new BIG(ROM.CURVE_Pyaab)),
					new FP2(
						new BIG(ROM.CURVE_Pyaba),new BIG(ROM.CURVE_Pyabb))),
				new FP4(
					new FP2(
						new BIG(ROM.CURVE_Pybaa),new BIG(ROM.CURVE_Pybab)),
					new FP2(
						new BIG(ROM.CURVE_Pybba),new BIG(ROM.CURVE_Pybbb)))));

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy