一、ElGamal算法概述
ElGamal加密算法是1985年由Taher Elgamal提出的基于离散对数问题的非对称加密算法,与RSA不同,它直接建立在Diffie-Hellman密钥交换协议之上。ElGamal具有概率加密特性(同一明文每次加密产生不同密文),使其在安全性上具有独特优势,广泛应用于PGP、GnuPG等安全系统中。
核心特性
特性 | 描述 |
---|
安全性基础 | 离散对数难题 |
加密特性 | 概率加密(随机性) |
密钥结构 | 公钥=(p, g, h),私钥=x |
应用场景 | 安全通信、数字签名、电子投票 |
二、ElGamal算法原理
1. 密钥生成
1. 选择大素数 p
2. 选择生成元 g ∈ Zₚ*
3. 选择私钥 x(1 < x < p-1)
4. 计算公钥 h = g^x mod p
2. 加密过程(分组处理)
对于明文分组 m(0 ≤ m < p):
1. 随机选择整数 k(1 < k < p-1)
2. 计算 c₁ = g^k mod p
3. 计算共享密钥 s = h^k mod p
4. 计算 c₂ = m · s mod p
5. 输出密文 (c₁, c₂)
3. 解密过程
1. 计算共享密钥 s = c₁^x mod p
2. 计算 s 的模逆元 s^{-1} mod p
3. 恢复明文 m = c₂ · s^{-1} mod p
三、Java实现
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class ElGamalAlgorithm {private static final int PRIME_BITS = 1024;private BigInteger p;private BigInteger g;private BigInteger x;private BigInteger h;private int blockSize;public void generateKeys() {SecureRandom random = new SecureRandom();p = BigInteger.probablePrime(PRIME_BITS, random);g = findGenerator(p, random);BigInteger pMinusTwo = p.subtract(BigInteger.TWO);x = new BigInteger(PRIME_BITS - 1, random).mod(pMinusTwo).add(BigInteger.ONE);h = g.modPow(x, p);blockSize = (p.bitLength() - 1) / 8 - 1; }private BigInteger findGenerator(BigInteger p, SecureRandom random) {BigInteger g;do {g = new BigInteger(p.bitLength(), random).mod(p.subtract(BigInteger.ONE)).add(BigInteger.ONE);} while (!isGenerator(g, p));return g;}private boolean isGenerator(BigInteger g, BigInteger p) {return g.compareTo(BigInteger.ONE) > 0 &&g.compareTo(p) < 0;}public List<BigInteger[]> encrypt(byte[] plaintext) {SecureRandom random = new SecureRandom();List<BigInteger[]> ciphertext = new ArrayList<>();for (int i = 0; i < plaintext.length; i += blockSize) {int length = Math.min(blockSize, plaintext.length - i);byte[] block = Arrays.copyOfRange(plaintext, i, i + length);BigInteger m = new BigInteger(1, block);if (m.compareTo(p) >= 0) {throw new IllegalArgumentException("明文分组太大,请使用更小的blockSize");}ciphertext.add(encryptBlock(m, random));}return ciphertext;}private BigInteger[] encryptBlock(BigInteger m, SecureRandom random) {BigInteger k;do {k = new BigInteger(p.bitLength(), random);} while (k.compareTo(BigInteger.ONE) <= 0 ||k.compareTo(p.subtract(BigInteger.ONE)) >= 0);BigInteger c1 = g.modPow(k, p);BigInteger s = h.modPow(k, p);BigInteger c2 = m.multiply(s).mod(p);return new BigInteger[]{c1, c2};}public byte[] decrypt(List<BigInteger[]> ciphertext) {ByteArrayOutputStream output = new ByteArrayOutputStream();for (BigInteger[] block : ciphertext) {BigInteger m = decryptBlock(block[0], block[1]);byte[] bytes = m.toByteArray();if (bytes[0] == 0) {output.write(bytes, 1, bytes.length - 1);} else {output.write(bytes, 0, bytes.length);}}return output.toByteArray();}private BigInteger decryptBlock(BigInteger c1, BigInteger c2) {BigInteger s = c1.modPow(x, p);BigInteger sInv = s.modInverse(p);return c2.multiply(sInv).mod(p);}public static void main(String[] args) {ElGamalAlgorithm elgamal = new ElGamalAlgorithm();elgamal.generateKeys();System.out.println("公钥(p): " + elgamal.p.toString(16).substring(0, 20) + "...");System.out.println("公钥(g): " + elgamal.g.toString(16).substring(0, 20) + "...");System.out.println("公钥(h): " + elgamal.h.toString(16).substring(0, 20) + "...");System.out.println("分组大小: " + elgamal.blockSize + " 字节");String longText = "ElGamal加密算法是一种基于离散对数问题的非对称加密算法," +"由Taher Elgamal于1985年提出。" +"同一明文每次加密产生不同的密文,增强安全性。";System.out.println("\n测试文本: " + longText);byte[] plaintext = longText.getBytes(StandardCharsets.UTF_8);List<BigInteger[]> ciphertext = elgamal.encrypt(plaintext);System.out.println("分组数量: " + ciphertext.size());byte[] decrypted = elgamal.decrypt(ciphertext);String decryptedText = new String(decrypted, StandardCharsets.UTF_8);System.out.println("解密文本: " + decryptedText);System.out.println("解密是否成功: " + longText.equals(decryptedText));}
}
四、ElGamal安全性分析
1. 安全优势与局限
优势 | 局限 |
---|
基于离散对数难题 | 密文膨胀(2-4倍) |
概率加密特性 | 计算开销大 |
可证明安全性 | 需大素数参数 |
支持同态运算 | 需安全随机数 |
2. 已知攻击与防御
攻击类型 | 防御措施 |
---|
小子群攻击 | 使用安全素数 |
随机数重用 | 每次加密使用新随机数 |
CCA攻击 | 使用OAEP填充 |
量子计算威胁 | 迁移到后量子密码 |
五、Java标准库实现
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;public class ElGamalWithJCE {public static KeyPair generateKeyPair(int keySize) throws Exception {KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ElGamal");keyGen.initialize(keySize);return keyGen.generateKeyPair();}public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {Cipher cipher = Cipher.getInstance("ElGamal/None/OAEPWithSHA-256AndMGF1Padding");cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data);}public static byte[] decrypt(PrivateKey privateKey, byte[] encrypted) throws Exception {Cipher cipher = Cipher.getInstance("ElGamal/None/OAEPWithSHA-256AndMGF1Padding");cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(encrypted);}public static String encodePublicKey(PublicKey publicKey) {ElGamalPublicKey elgKey = (ElGamalPublicKey) publicKey;return "p=" + elgKey.getParams().getP().toString(16) + "&g=" + elgKey.getParams().getG().toString(16) + "&y=" + elgKey.getY().toString(16);}public static void main(String[] args) throws Exception {KeyPair keyPair = generateKeyPair(2048);PublicKey publicKey = keyPair.getPublic();PrivateKey privateKey = keyPair.getPrivate();System.out.println("公钥参数: " + encodePublicKey(publicKey));String message = "JCE实现ElGamal加密";byte[] encrypted = encrypt(publicKey, message.getBytes());System.out.println("加密结果 (Base64): " + Base64.getEncoder().encodeToString(encrypted));byte[] decrypted = decrypt(privateKey, encrypted);System.out.println("解密结果: " + new String(decrypted));long start = System.nanoTime();encrypt(publicKey, message.getBytes());long time = System.nanoTime() - start;System.out.println("加密时间: " + time / 1000 + " μs");}
}
六、ElGamal优化与发展
1. 性能优化技术
技术 | 效果 | 实现方式 |
---|
预计算 | 加速加密 | 预计算gk和hk |
中国剩余定理 | 加速解密 | 使用p-1因子分解 |
并行处理 | 提高吞吐量 | 多核分组处理 |
硬件加速 | 10-100倍提升 | 专用模幂运算器 |
2. 变体算法比较
算法 | 特点 | 适用场景 |
---|
标准ElGamal | 基础实现 | 通用加密 |
椭圆曲线ElGamal | 密钥更短 | 移动设备 |
阈值ElGamal | 分布式解密 | 安全多方计算 |
同态ElGamal | 支持密文运算 | 隐私计算 |
3. 后量子时代发展
总结
ElGamal加密算法作为离散对数难题的经典实现,具有以下核心价值:
- 安全性强:基于数学难题,具有可证明安全性
- 概率加密:抵御选择明文攻击(CPA)
- 功能丰富:支持加密、签名、零知识证明
- 同态特性:乘法同态(m₁m₂的密文 = E(m₁) × E(m₂))