手工推算 Dual-EC-DRBG 序列
已知 \(F_{11}\) 上的椭圆曲线 \(E : y ^2 = x ^3 + x + 6\), 以及 \(E\) 上的有理点群
\(E(F_{11} ) =\) { \(O,(2,7),(5,2),(8,3),(10,2),(3,6),(7,9),(7,2),(3,5),(10,9),(8,8),(5,9),(2,4)\)}
手工推算出一段 \(Dual-EC-DRBG\) 伪随机数样本序列(在此我们不涉及安全性问题),自己设定参数。
概念回顾
\(11\)的二进制数为\(1011\),即这里的\(p\)为\(4\)
\(R=(x,y)∈E\) 则记 \(χ (R)=x\) (横坐标,视为整数,这里是\(4\)比特)
\(Trunc(x,m)\)表示\(x\)的低\(p-m\)比特
参数选取
取种子\(S_0 = 4(0100)\)
取\(m = 2\)
推算过程
\(E(F_{11} )\)={ \(O,(2,7),(5,2),(8,3),(10,2),(3,6),(7,9),(7,2),(3,5),(10,9),(8,8),(5,9),(2,4)\)}
倍点计算后面再说,这里直接写结果了。
\(P(2,7) Q(5,2)\)
输出随机数\(Trunc(χ (S_0Q),m) = Trunc(χ (4*(5,2)),m) = Trunc(0011,2)\)
取\(0011\)的低\(2\)比特即输出\(11\)
更新\(S_1 = χ (S_0P) = 10\)
\(P(8,3) Q(10,2)\)
输出随机数\(,Trunc(χ (S_1Q),m) = Trunc(χ (10*(10,2),m) = Trunc(0010,2)\)
取\(0010\)的低\(2\)比特即输出\(10\)
更新\(S_2 = χ (S_1P) = 10\)
\(P(3,6)Q(7,9)\)
输出随机数\(Trunc(χ (S_2Q),m) = Trunc(χ (10(7,9)),m) = Trunc(0011,2)\)
取\(0011\)的低\(2\)比特即输出\(11\)
更新\(S_3 = χ (S_2P) = 5\)
\(P(7,2)Q(3,5)\)
输出随机数\(Trunc(χ (S_3Q),m) = Trunc(χ (5*(3,5)),m) = Trunc(0010,2)\)
取\(0010\)的低\(2\)比特即输出\(10\)
更新\(S_4 = χ (S_3P) = 10\)
\(P(10,9)Q(8,8)\)
输出随机数\(Trunc(χ (S_4Q),m) = Trunc(χ (10*(8,8)),m) = Trunc(1010,2)\)
取\(1010\)的低\(2\)比特即输出\(10\)
更新\(S_5 = χ (S_4P) = 2\)
\(P(5,9)Q(2,4)\)
输出随机数\(Trunc(χ (S_5Q),m) = Trunc(χ (2*(2,4)),m) = Trunc(0101,2)\)
取\(0101\)的低\(2\)比特即输出\(01\)
则推算出 \(Dual-EC-DRBG\) 序列为\(111011101001\)
倍点计算举例
已知\(G(2,7)\)在上述椭圆曲线上,求\(2G\)。
步骤:求\(G\)与曲线相切时的斜率(求导),得到直线方程;将直线方程代入曲线方程,解三次方程。
计算时注意\(P+Q\)并不在\(PQ\)上,而是在\(-PQ\)上。
设\(P(x_1,y_1)Q(x_2,y_2)R(x_3,y_3)\) 椭圆曲线\(y^2 = x^3+ax+b\)
\(PQ\)斜率:
\(K = \frac{y_2-y_1}{x_2-x_1}\) \(P≠Q\)
\(K = \frac{3x^2+a}{2y}\) \(P=Q\)
此时我们算的是\(2G\)即\(P = Q\)化简可得\(y_3 = kx_3 + C\)
将\(y_3\)代入椭圆曲线方程解得
\(y_3 = k(x_1-x_3)-y_1\)
\(x_3 = k^2 - x_2 -x_1\)
将\(G(2,7)\)代入解得\(K = \frac{12+1}{2x7} = \frac{13}{14} mod11\)
关于分数求模可参考链接 https://wenku.baidu.com/view/6f2879cca1c7aa00b52acb5f.html
解得\(K= 8\),代入 \((x_3,y_3)\) 可得 \(2G\) 为 \((5,2)\)
倍点计算代码展示
参考链接 https://wenku.baidu.com/view/5e2cce4d767f5acfa1c7cd3b.html
import java.io.*;
public class ecc{
public static int x,y,n,a,p;
public static int getX(int x)
{
int i=1;
while(true)
{
if(modP(x*i)==1)
{
break;
}
i++;
}
return i;
}
public static int modP(int x)
{
if(x<0)
{
while(x<0)
{
x=x+p;
}
}
else
x=x%p;
return x;
}
public static void getR()
{
int X=x,Y=y;
for(int i=1;i<n;i++)
{
if(X==x&Y==y)
{
int k=getK(a,x,y);
X=modP(k*k-x-X);
Y=modP(k*(x-X)-y);
}
else
{
int k=getk(x,y,X,Y);
X=modP(k*k-x-X);
Y=modP(k*(x-X)-y);
}
}
System.out.println("("+X+","+Y+")");
}
public static int getK(int a,int x,int y)
{
int k=(3*x*x+a)*getX(2*y);
return modP(k);
}
public static int getk(int x1,int y1,int x2,int y2)
{
int k=(y2-y1)*getX(x2-x1);
return modP(k);
}
public static void main(String args[]) throws IOException
{
BufferedReader f=new BufferedReader(new InputStreamReader(System.in));
System.out.println("按如下格式输入要计算的倍点:");
System.out.println("椭圆曲线方程:y^2=aX^3+bx+c,请输入:a");
String s=f.readLine();
a=Integer.parseInt(s);
System.out.println("所求坐标Q(x,y),输入x,y");
s=f.readLine();
x=Integer.parseInt(s);
s=f.readLine();
y=Integer.parseInt(s);
System.out.println("输入素数p");
s=f.readLine();
p=Integer.parseInt(s);
System.out.println("倍点nQ,输入n");
s=f.readLine();
n=Integer.parseInt(s);
System.out.println("点Q("+x+","+y+")的"+n+"倍点结果"+n+"Q是");
getR();
}
}