$EL\ Gamal$ 密码方案的椭圆曲线形式

\(EL\ Gamal\) 密码方案的椭圆曲线形式

\(1.\) 问题背景

公私钥生成\(E\)\(F_{q}\) 上的椭圆曲线,一般记为 \(E(F_{q})\),设 \(P = (x_{p},\ y_{p})\in E(F_{q})\),且 \(P\) 的阶数为大素数,取 \(s\in F_{q}\),满足 \(1 < s < ord(P)\),令 \(Q = (x_{q},\ y_{q}) = sP\),则 \((E(F_{q}),\ P,\ Q)\) 为公钥,\(s\) 为私钥

加密过程 将消息 \(m\) 映射到 \(F_{q}^{*}\),任取 \(1 < r < ord(P)\),计算 \((x_{1},\ y_{1}) = rP,\ (x_{2},\ y_{2}) = rQ,\ c = m\cdot x_{2}\),则密文为 \((x_{1},\ y_{1},\ c)\)

解密过程 计算 \((x',\ y') = s\cdot (x_{1},\ y_{1}) = s\cdot rP\),再计算 \(m' = c\cdot x'^{-1}\),解得明文,这是因为 \(c = m\cdot s\cdot r\cdot x_{p},\ x' = s\cdot r\cdot x_{p}\),所以 \(m' = (m\cdot s\cdot r\cdot x_{p})\cdot (s\cdot r\cdot x_{p})^{-1} = m\)

\(2.\) 问题描述

问题描述如下

  • \(E:\ y^2 = x^3 + x + 6\)\(F_{11}\) 上的一条椭圆曲线,求 \(E\) 上所有点
  • \(P = (2,\ 7)\),取 \(s = 5\),求公钥
  • 设消息 \(m = 3\),取 \(r = 7\),计算 \(m\) 的密文 \((x_{1},\ y_{1},\ c)\)
  • \((x_{1},\ y_{1},\ c)\) 做解密运算,求 \((x',\ y')\),并进一步求其明文 \(m'\)

\(3.\) 问题分析与解

\(3.1\)\(E(F_{11})\) 上所有点

\(x_{i},\ y_{j}\) 遍历 \(F_{11}\) 上所有元素,验证是否满足 \(y_{j}^2\equiv x_{i}^3 + x_{i} + 6\ (mod\ 11)\)

或者,令 \(x_{i}\) 遍历 \(F_{11}\) 上所有元素,计算二次剩余 \(y^2\equiv x_{i}^3 + x_{i} + 6\ (mod\ 11)\)

我们选择第一个方法进行计算,将满足题意的点加入集合 \(ans\),时间复杂度为 \(O(q^2)\)\(q\) 为域 \(F_{q}\) 的大小

相关代码如下

/* 得到 E(F11) 上所有点 */
void getAllPoints()
{
    for(int x = 0; x < MOD; ++x) {
        for(int y = 0; y < MOD; ++y) {
            if(qpow(y, 2) == addMOD(qpow(x, 3), addMOD(mulMOD(A, x), B))) {
                ans.pb({x, y});
            }
        }
    }
    ans.pb(O);
}

/* 输出点坐标 */
void out(pii P) {printf("(%d, %d)\n", P.fi, P.se);}

/* 展示 E(F11) 上所有点 */
void showAllPoints()
{
    printf("一共有 %d 个点\n", ans.size());
    for(auto i: ans) out(i);
    puts("");
}

\(3.2\)\(P = (2,\ 7)\),取 \(s = 5\),求公钥

公钥 \((E(F_{11}),\ P)\) 已知,最后一个公钥参数即为椭圆曲线上点 \(Q\),满足 \(Q = sP = 5(2,\ 7)\)

为了计算 \(Q = sP\),我们需要先讨论椭圆曲线上的 \(1\) 次加法,再椭圆曲线上的 \(n\) 次加法

\(3.2.1\) 计算 \(P_{1} + P_{2} = R\)

考虑椭圆曲线 \(E(F_{11})\) 上的加法,设 \(P_{1} + P_{2} = R\),其中 \(P_{1} = (x_{1},\ y_{1}),\ P_{2} = (x_{2},\ y_{2})\),则 \(R = (x_{3},\ y_{3})\) 为直线 \(P_{1}P_{2}\)\(E(F_{11})\) 的第三个交点 \(R'\) 关于 \(X\) 轴的对称点

设无穷远点为 \(O\),下面讨论 \(P_{1}\)\(P_{2}\) 的关系,以及对应的 \(R = P_{1} + P_{2}\) 的求解,并给出 \(R\) 的显式解

易知,这样的计算时间复杂度是 \(O(1)\)

\(3.2.1.1\ P_{1} = O\) 或者 \(P_{2} = O\)

分两种情况

  • \(P_{1} = O\),则 \(R = P_{1} + P_{2} = P_{2}\)
  • \(P_{2} = O\),则 \(R = P_{1} + P_{2} = P_{1}\)
\(3.2.1.2\ P_{1} = P_{2}\)

\(y_{1} = 0\) 时,\(k_{1} = \infty\),则 \(R = P_{1} + P_{2} = O\)

示例图如下

1

\(y_{1}\neq 0\) 时,计算 \(E(F_{11})\)\(P_{1} = P_{2} = (x_{1},\ y_{1})\) 处的切线,设斜率为 \(k_{1}\)

对于方程 \(y^2 = x^3 + x + 6\),两边同时对 \(x\) 求导,得到

\[2y\frac{dy}{dx} = 3x^2 + 1,\ \frac{dy}{dx} = (3x^2 + 1)\cdot (2y)^{-1} \]

所以

\[k_{1} = \frac{dy}{dx}\mid_{x = x_{1},\ y = y_{1}} = (3x_{1}^2 + 1)\cdot (2y_{1})^{-1} \]

对应的切线方程为

\[y = k_{1}\cdot (x - x_{1}) + y_{1} \]

\[y = (3x_{1}^2 + 1)\cdot (2y_{1})^{-1}\cdot (x - x_{1}) + y_{1} \]

代入椭圆方程解得

\[\begin{aligned} x_{R} & = k^2 - 2\cdot x_{1}\\ y_{R} & = MOD - [y_{1} + k\cdot (x_{R} - x_{1})] \end{aligned} \]

示例图如下

2

\(3.2.1.3\ P_{1}\neq P_{2}\)

\(x_{2} = x_{1}\) 时,对应的第三个交点 \(R\) 为无穷远点 \(O\)

示例图如下

3

\(x_{2}\neq x_{1}\) 时,直线方程 \(P_{1}P_{2}\)

\[y - y_{2} = k\cdot (x - x_{2}) \]

其中

\[k = (y_{2} - y_{1})(x_{2} - x_{1})^{-1} \]

\[y = (y_{2} - y_{1})\cdot(x_{2} - x_{1})^{-1} \cdot (x - x_{2}) + y_{2} \]

代入椭圆方程解得

\[\begin{aligned} x_{R} & = k^2 - x_{1} - x_{2}\\ y_{R} & = MOD - [y_{1} + k\cdot (x_{R} - x_{1})] \end{aligned} \]

示例图如下

4

\(3.2.2\) 计算 \(nP\)

为了计算 \(nP\),最简单的想法是进行 \(n - 1\) 次递推,算法的复杂度为 \(O(n)\)

进一步的,我们可以利用快速幂算法将时间复杂度优化到 \(O(logn)\)

相关代码如下

/* 计算点 P 处切线斜率 */
int getTangentAtPoint(pii P)
{
    return mulMOD(addMOD(mulMOD(3, qpow(P.fi, 2)), A), getInv(mulMOD(2, P.se)));
}

/* 计算直线 P1P2 斜率 */
int getTangentOfP1P2(pii P1, pii P2)
{
    return mulMOD(subMOD(P2.se, P1.se), getInv(subMOD(P2.fi, P1.fi)));
}

/* 处理切线 */
pii handleTangent(pii P)
{
    if(P.se == 0) return O;
    int tangentAtP = getTangentAtPoint(P);
    int xr = subMOD(qpow(tangentAtP, 2), mulMOD(P.fi, 2));
    int yr = addMOD(P.se, mulMOD(tangentAtP, subMOD(xr, P.fi)));
    return {xr, MOD - yr};
}

/* 处理割线 */
pii handleSecant(pii P1, pii P2)
{
    if(P1.fi == P2.fi) return O;
    int tangentOfP1P2 = getTangentOfP1P2(P1, P2);
    int xr = subMOD(qpow(tangentOfP1P2, 2), addMOD(P1.fi, P2.fi));
    int yr = addMOD(P1.se, mulMOD(tangentOfP1P2, subMOD(xr, P1.fi)));
    return {xr, MOD - yr};
}

/* 计算 P1P2 与 E(F11) 的第三个交点 */
pii addP1P2(pii P1, pii P2)
{
    if(P1 == O || P2 == O) return P1 == O ? P2 : P1;
    else if(P1 == P2) return handleTangent(P1);
    else if(P1 != P2) return handleSecant(P1, P2);
}

/* 点幂普通算法 */
pii getNP(pii P, int n)
{
    pii nP = O;
    for(int i = 0; i < n; ++i) {
        nP = addP1P2(nP, P);
        //cout << nP.fi << ' ' << nP.se << endl;
    }
    return nP;
}

/* 点幂快速幂算法 */
pii qGetNP(pii P, int n)
{
    if(P == O) return O;
    pii ans = O;
    while(n) {
        if(n & 1) ans = addP1P2(ans, P);
        P = addP1P2(P, P), n >>= 1;
    }
    return ans;
}

/* EL'Gamal 方案生成公钥 */
publicKey getPublicKey(pii P, int s)
{
    pii Q = qGetNP(P, s);
    publicKey pk = publicKey(P, Q);
    return pk;
}

\(3.3\) 设消息 \(m = 3\),取 \(r = 7\),计算 \(m\) 的密文 \((x_{1},\ y_{1},\ c)\)

考虑加密过程

消息 \(m\) 满足 \(m\in F_{q}^{*}\),任取 \(1 < r < ord(P)\),计算 \((x_{1},\ y_{1}) = rP,\ (x_{2},\ y_{2}) = rQ,\ c = m\cdot x_{2}\),则密文为 \((x_{1},\ y_{1},\ c)\)

只需要按照公式分别计算出 \(rP,\ rQ,\ c\) 即可

相关代码如下

/* EL'Gamal 方案加密过程 */
cipherText encryption(pii P, pii Q, int r, int m)
{
    pii rP = qGetNP(P, r); // rP = (7, 9)
    pii rQ = qGetNP(Q, r);
    int c = mulMOD(m, rQ.fi);
    cipherText ciphertext = cipherText(rP.fi, rP.se, c);
    return ciphertext;
}

\(3.4\)\((x_{1},\ y_{1},\ c)\) 做解密运算,求 \((x',\ y')\),并进一步求其明文 \(m'\)

考虑解密过程

计算 \((x',\ y') = s\cdot (x_{1},\ y_{1}) = s\cdot rP\),再计算 \(m' = c\cdot x'^{-1}\),解得明文,这是因为 \(c = m\cdot s\cdot r\cdot x_{p},\ x' = s\cdot r\cdot x_{p}\),所以 \(m' = (m\cdot s\cdot r\cdot x_{p})\cdot (s\cdot r\cdot x_{p})^{-1} = m\)

只需要利用密文 \(x_{1},\ y_{1}\),公钥 \(s\),计算出 \(s\cdot (x_{1},\ y_{1})\),再根据密文 \(c\),便可以计算出明文 \(m = m' = c\cdot x'^{-1}\)

相关代码如下

/* EL'Gamal 方案解密过程 */
int decryption(int x, int y, int c, int s)
{
    pii rP = {x, y};
    pii srP = qGetNP(rP, s);
    int plaintext = mulMOD(c, getInv(srP.fi));
    return plaintext;
}

\(4.\) 完整代码

\(CPP\) 编写,注释写在代码中

#include <iostream>
#include <vector>
#include <set>
#define pii pair<int, int>
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;

const int MOD = 11;
const int A = 1;
const int B = 6;
pii O = {inf, inf};
vector<pii> ans; // 用来存储 E(F11) 上所有点

struct publicKey
{
    char* EF11 = "y^2 = x^3 + x + 6";
    pii P, Q;
    publicKey(pii _P, pii _Q): P(_P), Q(_Q) {}
};

struct cipherText
{
    int x, y, c;
    cipherText(int _x, int _y, int _c): x(_x), y(_y), c(_c) {}
};

/* 整数快速幂算法 */
int qpow(int a, int b)
{
    if(!a) return 0;
    int ans = 1;
    while(b) {
        if(b & 1) ans *= a, ans %= MOD;
        a *= a, a %= MOD, b >>= 1;
    }
    return ans;
}

/* 模运算与求逆元 */
int addMOD(int a, int b) {return (a + b) % MOD;}
int subMOD(int a, int b) {return (a % MOD - b % MOD + MOD) % MOD;}
int mulMOD(int a, int b) {return a * b % MOD;}
int getInv(int x) {return qpow(x, MOD - 2);}

/* 得到 E(F11) 上所有点 */
void getAllPoints()
{
    for(int x = 0; x < MOD; ++x) {
        for(int y = 0; y < MOD; ++y) {
            if(qpow(y, 2) == addMOD(qpow(x, 3), addMOD(mulMOD(A, x), B))) {
                ans.pb({x, y});
            }
        }
    }
    ans.pb(O);
}

/* 输出点坐标 */
void out(pii P) {printf("(%d, %d)\n", P.fi, P.se);}

/* 展示 E(F11) 上所有点 */
void showAllPoints()
{
    printf("一共有 %d 个点\n", ans.size());
    for(auto i: ans) out(i);
    puts("");
}

/* 计算点 P 处切线斜率 */
int getTangentAtPoint(pii P)
{
    return mulMOD(addMOD(mulMOD(3, qpow(P.fi, 2)), A), getInv(mulMOD(2, P.se)));
}

/* 计算直线 P1P2 斜率 */
int getTangentOfP1P2(pii P1, pii P2)
{
    return mulMOD(subMOD(P2.se, P1.se), getInv(subMOD(P2.fi, P1.fi)));
}

/* 处理切线 */
pii handleTangent(pii P)
{
    if(P.se == 0) return O;
    int tangentAtP = getTangentAtPoint(P);
    int xr = subMOD(qpow(tangentAtP, 2), mulMOD(P.fi, 2));
    int yr = addMOD(P.se, mulMOD(tangentAtP, subMOD(xr, P.fi)));
    return {xr, MOD - yr};
}

/* 处理割线 */
pii handleSecant(pii P1, pii P2)
{
    if(P1.fi == P2.fi) return O;
    int tangentOfP1P2 = getTangentOfP1P2(P1, P2);
    int xr = subMOD(qpow(tangentOfP1P2, 2), addMOD(P1.fi, P2.fi));
    int yr = addMOD(P1.se, mulMOD(tangentOfP1P2, subMOD(xr, P1.fi)));
    return {xr, MOD - yr};
}

/* 计算 P1P2 与 E(F11) 的第三个交点 */
pii addP1P2(pii P1, pii P2)
{
    if(P1 == O || P2 == O) return P1 == O ? P2 : P1;
    else if(P1 == P2) return handleTangent(P1);
    else if(P1 != P2) return handleSecant(P1, P2);
}

/* 点幂普通算法 */
pii getNP(pii P, int n)
{
    pii nP = O;
    for(int i = 0; i < n; ++i) {
        nP = addP1P2(nP, P);
        //cout << nP.fi << ' ' << nP.se << endl;
    }
    return nP;
}

/* 点幂快速幂算法 */
pii qGetNP(pii P, int n)
{
    if(P == O) return O;
    pii ans = O;
    while(n) {
        if(n & 1) ans = addP1P2(ans, P);
        P = addP1P2(P, P), n >>= 1;
    }
    return ans;
}

/* EL'Gamal 方案生成公钥 */
publicKey getPublicKey(pii P, int s)
{
    pii Q = qGetNP(P, s);
    publicKey pk = publicKey(P, Q);
    return pk;
}

/* EL'Gamal 方案加密过程 */
cipherText encryption(pii P, pii Q, int r, int m)
{
    pii rP = qGetNP(P, r); // rP = (7, 9)
    pii rQ = qGetNP(Q, r);
    int c = mulMOD(m, rQ.fi);
    cipherText ciphertext = cipherText(rP.fi, rP.se, c);
    return ciphertext;
}

/* EL'Gamal 方案解密过程 */
int decryption(int x, int y, int c, int s)
{
    pii rP = {x, y};
    pii srP = qGetNP(rP, s);
    int plaintext = mulMOD(c, getInv(srP.fi));
    return plaintext;
}


int main()
{
    getAllPoints();
    showAllPoints();
    pii P = {2, 7};
    int sk = 5;
    publicKey pk = getPublicKey(P, sk);
    printf("公钥为 [%s, (%d, %d), (%d, %d)]\n\n", pk.EF11, pk.P.fi, pk.P.se, pk.Q.fi, pk.Q.se);

    int r = 7, m = 3;
    cipherText ciphertext = encryption(pk.P, pk.Q, r, m);
    printf("密文为 (%d, %d, %d)\n\n", ciphertext.x, ciphertext.y, ciphertext.c);

    int plaintext = decryption(ciphertext.x, ciphertext.y, ciphertext.c, sk);
    printf("明文为 %d\n\n", plaintext);
    return 0;
}
posted @ 2020-12-23 20:05  徐摆渡  阅读(307)  评论(0编辑  收藏  举报