ELGamal 加密算法及Java实现

ElGamal算法,是一种较为常见的加密算法,它是基于1985年提出的公钥密码体制和椭圆曲线加密体系。既能用于数据加密也能用于数字签名,其安全性依赖于计算有限域上离散对数这一难题。在加密过程中,生成的密文长度是明文的两倍,且每次加密后都会在密文中生成一个随机数K,在密码中主要应用离散对数问题的几个性质:求解离散对数(可能)是困难的,而其逆运算指数运算可以应用平方-乘的方法有效地计算。也就是说,在适当的群G中,指数函数是单向函数。

密钥生成

  1. 随机选择一个大素数p,且要求p-1有大素数因子。再选择一个模p的本原元α。将p和α公开。
  2. sk = d:  随机选择一个整数d作为密钥,2≤d≤p-2 。
  3. pk = (p, α, y):  计算y=α^d mod p,y为公钥。

加密 : 对M加密

  1. 随机地选取整数k,2≤k≤p-2
  2. U=y^k mod p
  3. C1=α^k mod p
  4. C2=UM mod p
  5. 密文为(C1,C2)

解密

  1. V=C1^d
  2. M=C2/V mod p=C2V^-1 mod p

加解密过程实现

import java.math.BigInteger;
import java.util.Random;

public class ElGamal {
    public static void main(String[] args) {

    }
    /*
        y=α^x(mod p),1≤x≤p-1
        x=logαy,1≤y≤p-1
     */
    public BigInteger p, alpha, y;
    private BigInteger d;   //private key

    public ElGamal() {
        do {
            p = BigInteger.probablePrime(100, new Random());
        } while (p.subtract(BigInteger.ONE).divide(new BigInteger("2")).isProbablePrime(100));
        do {
            alpha = new BigInteger(100, new Random());
        } while (! isOrigin(alpha, p));
        do {
            d = new BigInteger(100, new Random());
        } while (d.compareTo(BigInteger.ONE) != 1 || d.compareTo(p.subtract(BigInteger.ONE)) != -1);
        y = alpha.modPow(d, p);
    }

    public ElGamal(BigInteger p, BigInteger alpha, BigInteger d) {
        this.p = p;
        this.alpha = alpha;
        this.d = d;
        y = alpha.modPow(d, p);
    }

    /**
     * 加密
     * @param M
     * @return
     */
    BigInteger[] encrypt(BigInteger M) {
        BigInteger[] C = new BigInteger[2];
        BigInteger k, U;
        do {
            do {
                k = new BigInteger(100, new Random());
            } while (k.compareTo(BigInteger.ONE) != 1 || k.compareTo(p.subtract(BigInteger.ONE)) != -1);
            U = y.modPow(k, p);
        } while (U.intValue() != 1);
        C[0] = alpha.modPow(k, p);
        C[1] = U.multiply(M).mod(p);
        return C;
    }

    /**
     * 加密
     * @param M
     * @param k
     * @return
     */
    BigInteger[] encrypt(BigInteger M, BigInteger k) {
        BigInteger[] C = new BigInteger[2];
        BigInteger U = y.modPow(k, p);
        C[0] = alpha.modPow(k, p);
        C[1] = U.multiply(M).mod(p);
        return C;
    }

    /**
     * 解密
     * @param C
     * @return
     */
    BigInteger decrypt(BigInteger[] C) {
        BigInteger V = C[0].modPow(d, p);
        BigInteger M = C[1].multiply(V.modPow(new BigInteger("-1"), p)).mod(p);
        return M;
    }

    /**
     * 判断a是否为模m的原根,其中m为素数
     * @param a
     * @param m
     * @return
     */
    static boolean isOrigin(BigInteger a, BigInteger m) {
        if (a.gcd(m).intValue() != 1) return false;
        BigInteger i = new BigInteger("2");
        while (i.compareTo(m.subtract(BigInteger.ONE)) == -1) {
            if (m.mod(i).intValue() == 0) {
                if (a.modPow(i, m).intValue() == 1)
                    return false;
                while (m.mod(i).intValue() == 0)
                    m = m.divide(i);
            }
            i = i.add(BigInteger.ONE);
        }
        return true;
    }

    public BigInteger getD() {
        return d;
    }



}

测试代码

import java.math.BigInteger;

public class TestElGamal {
    public static void main(String[] args) {
        //BigInteger p=BigInteger.valueOf(2579L);
        System.out.println("initial...");
        BigInteger p=new BigInteger("2579");
        BigInteger alpha=new BigInteger("2");
        BigInteger d=new BigInteger("765");//sk
        ElGamal elGamalDemo=new ElGamal(p,alpha,d);

        System.out.println("System Parameter...");
        System.out.println("p="+elGamalDemo.p);
        System.out.println("alpha="+elGamalDemo.alpha);
        System.out.println("d="+elGamalDemo.getD());
        System.out.println("y="+elGamalDemo.y);

        BigInteger M=new BigInteger("2023");
        BigInteger k=new BigInteger("853");
        System.out.println("M="+M);

        System.out.println("Encrypt...");
        BigInteger[] C=elGamalDemo.encrypt(M,k);
        System.out.print("After encryption : ");
        System.out.println(C[0]+" "+C[1]);

        BigInteger newM=elGamalDemo.decrypt(C);
        System.out.println("Decrypt...");
        System.out.print("After decryption : ");
        System.out.println(newM);

    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值