ElGamal算法的數字簽名


1、准備步驟

1)隨機選取大素數 p 和 g<p(g 最好是 p 的素根)。
2)隨機選取整數 x,x∈[1, p-2],計算 y=g^x(mod p)。
3)設 m∈Z 是待簽名的消息,秘密隨機選取一個整數 k,k∈[1, p-2],且 k 與 p-1 互質

2、簽名過程

1)計算 r 和 s:

r=g^k(mod p)
s=k^-1(m-rx)(mod p-1)(k^-1 表示 k mod p-1 的逆元)
2)(m, r, s)為對消息 m 的數字簽名。


3、驗證簽名

1)對方收到對消息 m 的數字簽名(m, r, s)后,利用簽名者的公開密鑰(y, g, p)對簽名進行以下驗證:
(y^r)(r^s) mod p=g^m(mod p)(左式計算時可以使用快速冪取模)
如果上式成立,則接受該簽名,否則拒絕該簽名。

4、簽名過程實現(測試對消息 'A' 進行簽名):

import java.util.ArrayList;

public class Main {
    private static ArrayList<Integer> suArr = new ArrayList<>();
    private static int[] xy = new int[2];
    // 定義素數的范圍為 8-bit
    private static int MAX = 255;
    public static void main(String[] args) {
        int p, g, x, y, k, r, s;
        int m = (int)'A';

        // 初始化素數數組
        initSuArr();

        // 取一個素數 p
        p = suArr.get((int) (Math.random() * (suArr.size())));

        // g 是 p 的一個本原元
        g = 2;
        
        // x >= 1 && x <= p-2
        x = (int)(Math.random() * (p-2))+1;

        // y = g^x mod p
        y = myPow(g, x, p); // y是公開密鑰

        // k >= 1 && k <= p-2 且 k 與 (p-1) 互質
        k = (int)(Math.random() * (p-2))+1;
        while (isHuZhi(k, p-1) != 1) {
            k = (int)(Math.random() * (p-2));
        }

        // r = g^k mod p
        r = myPow(g, k, p);

        // 計算k^-1 mod p-1
        exGcd(k, (p-1));
        k = xy[0];
        if(k < 0) k += (p-1);

        // s = k^(-1)*(m-rx)(mod p-1)
        s = (k*(m-r*x)) % (p-1); // (m,r,s)為對消息m的數字簽名
        // s可能為負值,所以要將其轉化為正數,利用a%b=(a%b+b)%b
        if(s < 0) s = (s + p-1) % (p-1);

        if ((myPow(y, r, p) * myPow(r, s, p))%p == myPow(g, m, p)) {
            System.out.println("接受該簽名");
        } else {
            System.out.println("拒絕該簽名");
        }
    }

    // 判斷一個數是否為素數
    public static boolean isSuShu(int num) {
        int max = (int) Math.sqrt(num);
        for (int i = 2; i <= max; i++) {
            if (num % i == 0)
                return false;
        }
        return true;
    }

    // 初始化素數數組
    public static void initSuArr() {
        suArr.add(2);
        for (int i = 3; i <= MAX; i++) {
            if (isSuShu(i))
                suArr.add(i);
        }
    }

    // 判斷兩個數是否互質
    public static int isHuZhi(int a, int b) {
        return b == 0 ? a : isHuZhi(b, a % b);
    }

    public static int myPow(int a, int b, int m) {
        int res = 1;
        a %= m;
        while (b != 0) {
            if ((b & 1) == 1)
                res = (res * a) % m;
            a = (a * a) % m;
            b >>= 1;
        }
        return res;
    }

    // 求 a mod b 的逆元
    public static void exGcd(int a, int b) {
        if (b == 0) {
            xy[0] = 1;
            xy[1] = 0;
        } else {
            exGcd(b, a % b);
            int x = xy[0];
            xy[0] = xy[1];
            xy[1] = x - (a / b) * xy[1];
        }
    }
}

 

參考文檔:

1)https://blog.csdn.net/qq_34490018/article/details/79758620


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM