Example #1
0
 /* copy this=P */
 public void Copy(ECP2 P)
 {
     x.Copy(P.x);
     y.Copy(P.y);
     z.Copy(P.z);
     //		INF=P.INF;
 }
        /**
         * check whether the issuer public key is correct
         *
         * @return true iff valid
         */
        public bool Check()
        {
            // check formalities of IdemixIssuerPublicKey
            if (AttributeNames == null || Hsk == null || HRand == null || HAttrs == null || BarG1 == null || BarG1.IsInfinity() || BarG2 == null || HAttrs.Length < AttributeNames.Length)
            {
                return(false);
            }

            for (int i = 0; i < AttributeNames.Length; i++)
            {
                if (HAttrs[i] == null)
                {
                    return(false);
                }
            }

            // check proofs
            ECP2 t1 = IdemixUtils.GenG2.Mul(ProofS);
            ECP  t2 = BarG1.Mul(ProofS);

            t1.Add(W.Mul(BIG.ModNeg(ProofC, IdemixUtils.GROUP_ORDER)));
            t2.Add(BarG2.Mul(BIG.ModNeg(ProofC, IdemixUtils.GROUP_ORDER)));

            // Generating proofData that will contain 3 elements in G1 (of size 2*FIELD_BYTES+1)and 3 elements in G2 (of size 4 * FIELD_BYTES)
            byte[] proofData = new byte[0];
            proofData = proofData.Append(t1.ToBytes());
            proofData = proofData.Append(t2.ToBytes());
            proofData = proofData.Append(IdemixUtils.GenG2.ToBytes());
            proofData = proofData.Append(BarG1.ToBytes());
            proofData = proofData.Append(W.ToBytes());
            proofData = proofData.Append(BarG2.ToBytes());

            // Hash proofData to hproofdata and compare with proofC
            return(Enumerable.SequenceEqual(proofData.HashModOrder().ToBytes(), ProofC.ToBytes()));
        }
Example #3
0
        /* convert to byte array */
        public void ToBytes(sbyte[] b)
        {
            sbyte[] t = new sbyte[BIG.MODBYTES];
            ECP2    W = new ECP2(this);

            W.Affine();
            W.x.A.ToBytes(t);
            for (int i = 0; i < BIG.MODBYTES; i++)
            {
                b[i] = t[i];
            }
            W.x.B.ToBytes(t);
            for (int i = 0; i < BIG.MODBYTES; i++)
            {
                b[i + BIG.MODBYTES] = t[i];
            }

            W.y.A.ToBytes(t);
            for (int i = 0; i < BIG.MODBYTES; i++)
            {
                b[i + 2 * BIG.MODBYTES] = t[i];
            }
            W.y.B.ToBytes(t);
            for (int i = 0; i < BIG.MODBYTES; i++)
            {
                b[i + 3 * BIG.MODBYTES] = t[i];
            }
        }
Example #4
0
        /* Test if P == Q */
        public bool Equals(ECP2 Q)
        {
            //		if (is_infinity() && Q.is_infinity()) return true;
            //		if (is_infinity() || Q.is_infinity()) return false;


            FP2 a = new FP2(x);             // *****
            FP2 b = new FP2(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);
        }
Example #5
0
        /* Conditional move of Q to P dependant on d */
        public void CMove(ECP2 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;
        }
Example #6
0
        /* convert this to hex string */
        public override string ToString()
        {
            ECP2 W = new ECP2(this);

            W.Affine();
            if (W.IsInfinity())
            {
                return("infinity");
            }
            return("(" + W.x.ToString() + "," + W.y.ToString() + ")");
        }
Example #7
0
        /* set this-=Q */
        public int Sub(ECP2 Q)
        {
            ECP2 NQ = new ECP2(Q);

            NQ.Neg();
            int D = Add(NQ);

            //Q.neg();
            //int D=add(Q);
            //Q.neg();
            return(D);
        }
Example #8
0
        /* Constant time select from pre-computed table */
        public void Select(ECP2[] W, int b)
        {
            ECP2 MP   = new ECP2();
            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));
        }
        /**
         * verify cryptographically verifies the credential
         *
         * @param sk  the secret key of the user
         * @param ipk the public key of the issuer
         * @return true iff valid
         */
        public bool Verify(BIG sk, IdemixIssuerPublicKey ipk)
        {
            if (ipk == null || Attrs.Length != ipk.AttributeNames.Length)
            {
                return(false);
            }

            foreach (byte[] attr in Attrs)
            {
                if (attr == null)
                {
                    return(false);
                }
            }

            ECP bPrime = new ECP();

            bPrime.Copy(IdemixUtils.GenG1);
            bPrime.Add(ipk.Hsk.Mul2(sk, ipk.HRand, S));
            for (int i = 0; i < Attrs.Length / 2; i++)
            {
                bPrime.Add(ipk.HAttrs[2 * i].Mul2(BIG.FromBytes(Attrs[2 * i]), ipk.HAttrs[2 * i + 1], BIG.FromBytes(Attrs[2 * i + 1])));
            }

            if (Attrs.Length % 2 != 0)
            {
                bPrime.Add(ipk.HAttrs[Attrs.Length - 1].Mul(BIG.FromBytes(Attrs[Attrs.Length - 1])));
            }

            if (!B.Equals(bPrime))
            {
                return(false);
            }

            ECP2 a = IdemixUtils.GenG2.Mul(E);

            a.Add(ipk.W);
            a.Affine();
            return(PAIR.FExp(PAIR.Ate(a, A)).Equals(PAIR.FExp(PAIR.Ate(IdemixUtils.GenG2, B))));
        }
        /**
         * Constructor
         *
         * @param attributeNames the names of attributes as String array (must not contain duplicates)
         * @param isk            the issuer secret key
         */
        public IdemixIssuerPublicKey(string[] attributeNames, BIG isk)
        {
            // check null input
            if (attributeNames == null || isk == null)
            {
                throw new ArgumentException("Cannot create IdemixIssuerPublicKey from null input");
            }

            // Checking if attribute names are unique
            HashSet <string> map = new HashSet <string>();

            foreach (string item in attributeNames)
            {
                if (map.Contains(item))
                {
                    throw new ArgumentException("Attribute " + item + " appears multiple times in attributeNames");
                }
                map.Add(item);
            }

            RAND rng = IdemixUtils.GetRand();

            // Attaching Attribute Names array correctly
            AttributeNames = attributeNames;

            // Computing W value
            W = IdemixUtils.GenG2.Mul(isk);

            // Filling up HAttributes correctly in Issuer Public Key, length
            // preserving
            HAttrs = new ECP[attributeNames.Length];

            for (int i = 0; i < attributeNames.Length; i++)
            {
                HAttrs[i] = IdemixUtils.GenG1.Mul(rng.RandModOrder());
            }

            // Generating Hsk value
            Hsk = IdemixUtils.GenG1.Mul(rng.RandModOrder());

            // Generating HRand value
            HRand = IdemixUtils.GenG1.Mul(rng.RandModOrder());

            // Generating BarG1 value
            BarG1 = IdemixUtils.GenG1.Mul(rng.RandModOrder());

            // Generating BarG2 value
            BarG2 = BarG1.Mul(isk);

            // Zero Knowledge Proofs

            // Computing t1 and t2 values with random local variable r for later use
            BIG  r  = rng.RandModOrder();
            ECP2 t1 = IdemixUtils.GenG2.Mul(r);
            ECP  t2 = BarG1.Mul(r);

            // Generating proofData that will contain 3 elements in G1 (of size 2*FIELD_BYTES+1)and 3 elements in G2 (of size 4 * FIELD_BYTES)
            byte[] proofData = new byte[0];
            proofData = proofData.Append(t1.ToBytes());
            proofData = proofData.Append(t2.ToBytes());
            proofData = proofData.Append(IdemixUtils.GenG2.ToBytes());
            proofData = proofData.Append(BarG1.ToBytes());
            proofData = proofData.Append(W.ToBytes());
            proofData = proofData.Append(BarG2.ToBytes());

            // Hashing proofData to proofC
            ProofC = proofData.HashModOrder();

            // Computing ProofS = (ProofC*isk) + r mod GROUP_ORDER
            ProofS = BIG.ModMul(ProofC, isk, IdemixUtils.GROUP_ORDER).Plus(r);
            ProofS.Mod(IdemixUtils.GROUP_ORDER);

            // Compute Hash of IdemixIssuerPublicKey
            byte[] serializedIpk = ToProto().ToByteArray();
            Hash = serializedIpk.HashModOrder().ToBytes();
        }
Example #11
0
        /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */

        /*
         *      public static ECP2 mul4(ECP2[] Q,BIG[] u)
         *      {
         *              int i,j,nb;
         *              int[] a=new int[4];
         *              ECP2 T=new ECP2();
         *              ECP2 C=new ECP2();
         *              ECP2 P=new ECP2();
         *              ECP2[] W=new ECP2[8];
         *
         *              BIG mt=new BIG();
         *              BIG[] t=new BIG[4];
         *
         *              byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1];
         *
         *              for (i=0;i<4;i++)
         *              {
         *                      t[i]=new BIG(u[i]);
         *                      Q[i].affine();
         *              }
         *
         * // precompute table
         *
         *              W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
         *
         *              W[1]=new ECP2(); W[1].copy(W[0]);
         *              W[2]=new ECP2(); W[2].copy(W[0]);
         *              W[3]=new ECP2(); W[3].copy(W[0]);
         *              W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
         *              W[5]=new ECP2(); W[5].copy(W[4]);
         *              W[6]=new ECP2(); W[6].copy(W[4]);
         *              W[7]=new ECP2(); W[7].copy(W[4]);
         *              T.copy(Q[2]); T.sub(Q[3]);
         *              W[1].sub(T);
         *              W[2].add(T);
         *              W[5].sub(T);
         *              W[6].add(T);
         *              T.copy(Q[2]); T.add(Q[3]);
         *              W[0].sub(T);
         *              W[3].add(T);
         *              W[4].sub(T);
         *              W[7].add(T);
         *
         * // if multiplier is even add 1 to multiplier, and add P to correction
         *              mt.zero(); C.inf();
         *              for (i=0;i<4;i++)
         *              {
         *                      if (t[i].parity()==0)
         *                      {
         *                              t[i].inc(1); t[i].norm();
         *                              C.add(Q[i]);
         *                      }
         *                      mt.add(t[i]); mt.norm();
         *              }
         *
         *              nb=1+mt.nbits();
         *
         * // convert exponent to signed 1-bit window
         *              for (j=0;j<nb;j++)
         *              {
         *                      for (i=0;i<4;i++)
         *                      {
         *                              a[i]=(byte)(t[i].lastbits(2)-2);
         *                              t[i].dec(a[i]); t[i].norm();
         *                              t[i].fshr(1);
         *                      }
         *                      w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
         *              }
         *              w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
         *
         *              P.copy(W[(w[nb]-1)/2]);
         *              for (i=nb-1;i>=0;i--)
         *              {
         *                      T.select(W,w[i]);
         *                      P.dbl();
         *                      P.add(T);
         *              }
         *              P.sub(C); // apply correction
         *
         *              P.affine();
         *              return P;
         *      }
         */

        /* needed for SOK */
        public static ECP2 MapIt(sbyte[] h)
        {
            BIG  q   = new BIG(ROM.Modulus);
            BIG  x   = BIG.FromBytes(h);
            BIG  one = new BIG(1);
            FP2  X;
            ECP2 Q;

            x.Mod(q);
            while (true)
            {
                X = new FP2(one, x);
                Q = new ECP2(X);
                if (!Q.IsInfinity())
                {
                    break;
                }
                x.Inc(1);
                x.Norm();
            }

            BIG Fra = new BIG(ROM.Fra);
            BIG Frb = new BIG(ROM.Frb);

            X = new FP2(Fra, Frb);

            if (ECP.SEXTIC_TWIST == ECP.M_TYPE)
            {
                X.Inverse();
                X.Norm();
            }

            x = new BIG(ROM.CURVE_Bnx);

            /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */

            if (ECP.CURVE_PAIRING_TYPE == ECP.BN)
            {
                ECP2 T, K;

                T = new ECP2();
                T.Copy(Q);
                T = T.Mul(x);

                if (ECP.SIGN_OF_X == ECP.NEGATIVEX)
                {
                    T.Neg();
                }
                K = new ECP2();
                K.Copy(T);
                K.Dbl();
                K.Add(T);                 //K.affine();

                K.Frob(X);
                Q.Frob(X);
                Q.Frob(X);
                Q.Frob(X);
                Q.Add(T);
                Q.Add(K);
                T.Frob(X);
                T.Frob(X);
                Q.Add(T);
            }

            /* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */
            /* Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) */

            if (ECP.CURVE_PAIRING_TYPE == ECP.BLS)
            {
                //	ECP2 xQ,x2Q;
                //	xQ=new ECP2();
                //	x2Q=new ECP2();

                ECP2 xQ  = Q.Mul(x);
                ECP2 x2Q = xQ.Mul(x);

                if (ECP.SIGN_OF_X == ECP.NEGATIVEX)
                {
                    xQ.Neg();
                }

                x2Q.Sub(xQ);
                x2Q.Sub(Q);

                xQ.Sub(Q);
                xQ.Frob(X);

                Q.Dbl();
                Q.Frob(X);
                Q.Frob(X);

                Q.Add(x2Q);
                Q.Add(xQ);
            }
            Q.Affine();
            return(Q);
        }
Example #12
0
        /* 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 ECP2 Mul4(ECP2[] Q, BIG[] u)
        {
            int  i, j, nb, pb;
            ECP2 W = new ECP2();
            ECP2 P = new ECP2();

            ECP2[] T = new ECP2[8];

            BIG mt = new BIG();

            BIG[] t = new BIG[4];

            sbyte[] w = new sbyte[BIG.NLEN * BIG.BASEBITS + 1];
            sbyte[] s = new sbyte[BIG.NLEN * BIG.BASEBITS + 1];

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

            T[0] = new ECP2();
            T[0].Copy(Q[0]);             // Q[0]
            T[1] = new ECP2();
            T[1].Copy(T[0]);
            T[1].Add(Q[1]);             // Q[0]+Q[1]
            T[2] = new ECP2();
            T[2].Copy(T[0]);
            T[2].Add(Q[2]);             // Q[0]+Q[2]
            T[3] = new ECP2();
            T[3].Copy(T[1]);
            T[3].Add(Q[2]);             // Q[0]+Q[1]+Q[2]
            T[4] = new ECP2();
            T[4].Copy(T[0]);
            T[4].Add(Q[3]);             // Q[0]+Q[3]
            T[5] = new ECP2();
            T[5].Copy(T[1]);
            T[5].Add(Q[3]);             // Q[0]+Q[1]+Q[3]
            T[6] = new ECP2();
            T[6].Copy(T[2]);
            T[6].Add(Q[3]);             // Q[0]+Q[2]+Q[3]
            T[7] = new ECP2();
            T[7].Copy(T[3]);
            T[7].Add(Q[3]);             // Q[0]+Q[1]+Q[2]+Q[3]

            // Make it odd
            pb = 1 - t[0].Parity();
            t[0].Inc(pb);
            t[0].Norm();

            // Number of bits
            mt.Zero();
            for (i = 0; i < 4; i++)
            {
                mt.Or(t[i]);
            }
            nb = 1 + mt.NBits();

            // Sign pivot
            s[nb - 1] = 1;
            for (i = 0; i < nb - 1; i++)
            {
                t[0].FShr(1);
                s[i] = (sbyte)(2 * t[0].Parity() - 1);
            }

            // Recoded exponent
            for (i = 0; i < nb; i++)
            {
                w[i] = 0;
                int k = 1;
                for (j = 1; j < 4; j++)
                {
                    sbyte bt = (sbyte)(s[i] * t[j].Parity());
                    t[j].FShr(1);
                    t[j].Dec((int)(bt) >> 1);
                    t[j].Norm();
                    w[i] += (sbyte)(bt * (sbyte)k);
                    k    *= 2;
                }
            }

            // Main loop
            P.Select(T, (int)(2 * w[nb - 1] + 1));
            for (i = nb - 2; i >= 0; i--)
            {
                P.Dbl();
                W.Select(T, (int)(2 * w[i] + s[i]));
                P.Add(W);
            }

            // apply correction
            W.Copy(P);
            W.Sub(Q[0]);
            P.CMove(W, pb);
            P.Affine();
            return(P);
        }
Example #13
0
        /* P*=e */
        public ECP2 Mul(BIG e)
        {
            /* fixed size windows */
            int  i, nb, s, ns;
            BIG  mt = new BIG();
            BIG  t  = new BIG();
            ECP2 P  = new ECP2();
            ECP2 Q  = new ECP2();
            ECP2 C  = new ECP2();

            ECP2[]  W = new ECP2[8];
            sbyte[] w = new sbyte[1 + (BIG.NLEN * BIG.BASEBITS + 3) / 4];

            if (IsInfinity())
            {
                return(new ECP2());
            }

            //affine();

            /* precompute table */
            Q.Copy(this);
            Q.Dbl();
            W[0] = new ECP2();
            W[0].Copy(this);

            for (i = 1; i < 8; i++)
            {
                W[i] = new ECP2();
                W[i].Copy(W[i - 1]);
                W[i].Add(Q);
            }

            /* make exponent odd - add 2P if even, P if odd */
            t.Copy(e);
            s = t.Parity();
            t.Inc(1);
            t.Norm();
            ns = t.Parity();
            mt.Copy(t);
            mt.Inc(1);
            mt.Norm();
            t.CMove(mt, s);
            Q.CMove(this, ns);
            C.Copy(Q);

            nb = 1 + (t.NBits() + 3) / 4;
            /* convert exponent to signed 4-bit window */
            for (i = 0; i < nb; i++)
            {
                w[i] = (sbyte)(t.LastBits(5) - 16);
                t.Dec(w[i]);
                t.Norm();
                t.FShr(4);
            }
            w[nb] = (sbyte)t.LastBits(5);

            P.Copy(W[(w[nb] - 1) / 2]);
            for (i = nb - 1; 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);
        }
Example #14
0
        /* this+=Q - return 0 for add, 1 for double, -1 for O */
        public int Add(ECP2 Q)
        {
            //		if (INF)
            //		{
            //			copy(Q);
            //			return -1;
            //		}
            //		if (Q.INF) return -1;
            //System.out.println("Into add");
            int b  = 3 * ROM.CURVE_B_I;
            FP2 t0 = new FP2(x);

            t0.Mul(Q.x);             // x.Q.x
            FP2 t1 = new FP2(y);

            t1.Mul(Q.y);             // y.Q.y

            FP2 t2 = new FP2(z);

            t2.Mul(Q.z);
            FP2 t3 = new FP2(x);

            t3.Add(y);
            t3.Norm();             //t3=X1+Y1
            FP2 t4 = new FP2(Q.x);

            t4.Add(Q.y);
            t4.Norm();             //t4=X2+Y2
            t3.Mul(t4);            //t3=(X1+Y1)(X2+Y2)
            t4.Copy(t0);
            t4.Add(t1);            //t4=X1.X2+Y1.Y2

            t3.Sub(t4);
            t3.Norm();
            if (ECP.SEXTIC_TWIST == ECP.D_TYPE)
            {
                t3.Mul_Ip();
                t3.Norm();                 //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
            }
            t4.Copy(y);
            t4.Add(z);
            t4.Norm();             //t4=Y1+Z1
            FP2 x3 = new FP2(Q.y);

            x3.Add(Q.z);
            x3.Norm();             //x3=Y2+Z2

            t4.Mul(x3);            //t4=(Y1+Z1)(Y2+Z2)
            x3.Copy(t1);
            x3.Add(t2);            //X3=Y1.Y2+Z1.Z2

            t4.Sub(x3);
            t4.Norm();
            if (ECP.SEXTIC_TWIST == ECP.D_TYPE)
            {
                t4.Mul_Ip();
                t4.Norm();                 //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
            }
            x3.Copy(x);
            x3.Add(z);
            x3.Norm();             // x3=X1+Z1
            FP2 y3 = new FP2(Q.x);

            y3.Add(Q.z);
            y3.Norm();             // y3=X2+Z2
            x3.Mul(y3);            // x3=(X1+Z1)(X2+Z2)
            y3.Copy(t0);
            y3.Add(t2);            // y3=X1.X2+Z1+Z2
            y3.RSub(x3);
            y3.Norm();             // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1

            if (ECP.SEXTIC_TWIST == ECP.D_TYPE)
            {
                t0.Mul_Ip();
                t0.Norm();                 // x.Q.x
                t1.Mul_Ip();
                t1.Norm();                 // y.Q.y
            }
            x3.Copy(t0);
            x3.Add(t0);
            t0.Add(x3);
            t0.Norm();
            t2.IMul(b);
            if (ECP.SEXTIC_TWIST == ECP.M_TYPE)
            {
                t2.Mul_Ip();
                t2.Norm();
            }
            FP2 z3 = new FP2(t1);

            z3.Add(t2);
            z3.Norm();
            t1.Sub(t2);
            t1.Norm();
            y3.IMul(b);
            if (ECP.SEXTIC_TWIST == ECP.M_TYPE)
            {
                y3.Mul_Ip();
                y3.Norm();
            }
            x3.Copy(y3);
            x3.Mul(t4);
            t2.Copy(t3);
            t2.Mul(t1);
            x3.RSub(t2);
            y3.Mul(t0);
            t1.Mul(z3);
            y3.Add(t1);
            t0.Mul(t3);
            z3.Mul(t4);
            z3.Add(t0);

            x.Copy(x3);
            x.Norm();
            y.Copy(y3);
            y.Norm();
            z.Copy(z3);
            z.Norm();
            //System.out.println("Out of add");
            return(0);
        }
Example #15
0
 public ECP2(ECP2 e)
 {
     this.x = new FP2(e.x);
     this.y = new FP2(e.y);
     this.z = new FP2(e.z);
 }
 public byte[] RecomputeFSContribution(NonRevocationProof proof, BIG challenge, ECP2 epochPK, BIG proofSRh)
 {
     return(empty);
 }