
org.apache.milagro.amcl.RSA4096.FF Maven / Gradle / Ivy
Show all versions of milagro-crypto-java Show documentation
/*
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.
*/
/* Large Finite Field arithmetic */
/* AMCL mod p functions */
package org.apache.milagro.amcl.RSA4096;
import org.apache.milagro.amcl.RAND;
public final class FF {
/* RSA/DH modulus length as multiple of BIGBITS */
public static final int FFLEN=8;
/* Don't Modify from here... */
/* Finite field support - for RSA, DH etc. */
public static final int FF_BITS=(BIG.BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
public static final int HFLEN=(FFLEN/2); /* Useful for half-size RSA private key operations */
public static final int P_MBITS=BIG.MODBYTES*8;
public static final int P_TBITS=(P_MBITS%BIG.BASEBITS);
private final BIG[] v;
private final int length;
/**************** 64-bit specific ************************/
public static final long P_OMASK=((long)(-1)<<(P_MBITS%BIG.BASEBITS));
public static final long P_FEXCESS=((long)1<<(BIG.BASEBITS*BIG.NLEN-P_MBITS-1));
public static long EXCESS(BIG a)
{
return ((a.get(BIG.NLEN-1)&P_OMASK)>>(P_TBITS))+1;
}
/* Check if product causes excess */
public static boolean pexceed(BIG a,BIG b)
{
long ea,eb;
ea=EXCESS(a);
eb=EXCESS(b);
if ((ea+1)>P_FEXCESS/(eb+1)) return true;
return false;
}
/* Check if square causes excess */
public static boolean sexceed(BIG a)
{
long ea;
ea=EXCESS(a);
if ((ea+1)>P_FEXCESS/(ea+1)) return true;
return false;
}
/******************************************************/
/* Constructors */
public FF(int n)
{
v=new BIG[n];
for (int i=0;i>BIG.BASEBITS));
}
/* copy from FF b */
public void copy(FF b)
{
for (int i=0;i>n */
public void sducopy(FF b)
{
for (int i=0;i=0;i--)
{
j=BIG.comp(a.v[i],b.v[i]);
if (j!=0) return j;
}
return 0;
}
/* recursive add */
public void radd(int vp,FF x,int xp,FF y,int yp,int n)
{
for (int i=0;i0;i--)
{
carry=v[i].fshr(1);
v[i-1].xortop((long)carry<=0;i--)
{
s+=v[i].toString(); //s+=" ";
}
return s;
}
/*
public String toRawString(int len)
{
// norm(len);
String s="";
for (int i=len-1;i>=0;i--)
{
s+=v[i].toRawString(); s+=" ";
}
return s;
}
*/
/* Convert FFs to/from byte arrays */
public void toBytes(byte[] b)
{
for (int i=0;i=0);
while (k>0)
{
c.shr();
if (comp(this,c)>=0)
{
sub(c);
norm();
}
k--;
}
}
/* return This mod modulus, N is modulus, ND is Montgomery Constant */
public FF reduce(FF N,FF ND)
{ /* fast karatsuba Montgomery reduction */
int n=N.length;
FF t=new FF(2*n);
FF r=new FF(n);
FF m=new FF(n);
r.sducopy(this);
m.karmul_lower(0,this,0,ND,0,t,0,n);
karmul_upper(N,m,t,n);
m.sducopy(this);
r.add(N);
r.sub(m);
r.norm();
return r;
}
/* Set r=this mod b */
/* this is of length - 2*n */
/* r,b is of length - n */
public FF dmod(FF b)
{
int k,n=b.length;
FF m=new FF(2*n);
FF x=new FF(2*n);
FF r=new FF(n);
x.copy(this);
x.norm();
m.dsucopy(b); k=BIG.BIGBITS*n;
while (comp(x,m)>=0)
{
x.sub(m);
x.norm();
}
while (k>0)
{
m.shr();
if (comp(x,m)>=0)
{
x.sub(m);
x.norm();
}
k--;
}
r.copy(x);
r.mod(b);
return r;
}
/* Set return=1/this mod p. Binary method - a=0)
{
u.sub(v);
u.norm();
if (comp(x1,x2)>=0) x1.sub(x2);
else
{
t.copy(p);
t.sub(x2);
x1.add(t);
}
x1.norm();
}
else
{
v.sub(u);
v.norm();
if (comp(x2,x1)>=0) x2.sub(x1);
else
{
t.copy(p);
t.sub(x1);
x2.add(t);
}
x2.norm();
}
}
if (comp(u,one)==0)
copy(x1);
else
copy(x2);
}
/* nresidue mod m */
public void nres(FF m)
{
int n=m.length;
if (n==1)
{
DBIG d=new DBIG(this.v[0]);
d.shl(BIG.NLEN*BIG.BASEBITS);
this.v[0].copy(d.mod(m.v[0]));
}
else
{
FF d=new FF(2*n);
d.dsucopy(this);
copy(d.dmod(m));
}
}
public void redc(FF m,FF ND)
{
int n=m.length;
if (n==1)
{
DBIG d=new DBIG(this.v[0]);
this.v[0].copy(BIG.monty(m.v[0],(BIG.cast_to_chunk(1)<=0;i--)
{
b=e.v[i/BIG.BIGBITS].bit(i%BIG.BIGBITS);
copy(R0);
modmul(R1,p,ND);
cswap(R0,R1,b);
R0.modsqr(p,ND);
R1.copy(this);
cswap(R0,R1,b);
}
copy(R0);
redc(p,ND);
}
/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
public void skpow(BIG e,FF p)
{
int i,b,n=p.length;
FF R0=new FF(n);
FF R1=new FF(n);
FF ND=p.invmod2m();
mod(p);
R0.one();
R1.copy(this);
R0.nres(p);
R1.nres(p);
for (i=8*BIG.MODBYTES-1;i>=0;i--)
{
b=e.bit(i);
copy(R0);
modmul(R1,p,ND);
cswap(R0,R1,b);
R0.modsqr(p,ND);
R1.copy(this);
cswap(R0,R1,b);
}
copy(R0);
redc(p,ND);
}
/* raise to an integer power - right-to-left method */
public void power(int e,FF p)
{
int n=p.length;
FF w=new FF(n);
FF ND=p.invmod2m();
boolean f=true;
w.copy(this);
w.nres(p);
if (e==2)
{
copy(w);
modsqr(p,ND);
}
else for (; ; )
{
if (e%2==1)
{
if (f) copy(w);
else modmul(w,p,ND);
f=false;
}
e>>=1;
if (e==0) break;
w.modsqr(p,ND);
}
redc(p,ND);
}
/* this=this^e mod p, faster but not side channel resistant */
public void pow(FF e,FF p)
{
int i,b,n=p.length;
FF w=new FF(n);
FF ND=p.invmod2m();
w.copy(this);
one();
nres(p);
w.nres(p);
for (i=8*BIG.MODBYTES*n-1;i>=0;i--)
{
modsqr(p,ND);
b=e.v[i/BIG.BIGBITS].bit(i%BIG.BIGBITS);
if (b==1) modmul(w,p,ND);
}
redc(p,ND);
}
/* double exponentiation r=x^e.y^f mod p */
public void pow2(BIG e,FF y,BIG f,FF p)
{
int i,eb,fb,n=p.length;
FF xn=new FF(n);
FF yn=new FF(n);
FF xy=new FF(n);
FF ND=p.invmod2m();
xn.copy(this);
yn.copy(y);
xn.nres(p);
yn.nres(p);
xy.copy(xn); xy.modmul(yn,p,ND);
one();
nres(p);
for (i=8*BIG.MODBYTES-1;i>=0;i--)
{
eb=e.bit(i);
fb=f.bit(i);
modsqr(p,ND);
if (eb==1)
{
if (fb==1) modmul(xy,p,ND);
else modmul(xn,p,ND);
}
else
{
if (fb==1) modmul(yn,p,ND);
}
}
redc(p,ND);
}
private static int igcd(int x,int y)
{ /* integer GCD, returns GCD of x and y */
int r;
if (y==0) return x;
while ((r=x%y)!=0)
{x=y;y=r;}
return y;
}
/* quick and dirty check for common factor with n */
public boolean cfactor(int s)
{
int r,n=length;
int g;
FF x=new FF(n);
FF y=new FF(n);
y.set(s);
x.copy(this);
x.norm();
do
{
x.sub(y);
x.norm();
while (!x.iszilch() && x.parity()==0) x.shr();
}
while (comp(x,y)>0);
g=(int)x.v[0].get(0);
r=igcd(s,g);
if (r>1) return true;
return false;
}
/* Miller-Rabin test for primality. Slow. */
public static boolean prime(FF p,RAND rng)
{
int i,j,s=0,n=p.length;
boolean loop;
FF d=new FF(n);
FF x=new FF(n);
FF unity=new FF(n);
FF nm1=new FF(n);
int sf=4849845; /* 3*5*.. *19 */
p.norm();
if (p.cfactor(sf)) return false;
unity.one();
nm1.copy(p);
nm1.sub(unity);
nm1.norm();
d.copy(nm1);
while (d.parity()==0)
{
d.shr();
s++;
}
if (s==0) return false;
for (i=0;i<10;i++)
{
x.randomnum(p,rng);
x.pow(d,p);
if (comp(x,unity)==0 || comp(x,nm1)==0) continue;
loop=false;
for (j=1;j