ElGamal加密的明文(不是数字)无法正常工作。

huangapple go评论70阅读模式
英文:

El Gamal encryption of clear Text (not numbers) not woring

问题

以下是我用中文翻译的 JAVA 代码,包含了加密和解密部分:

package com.porsche.main;

import java.util.*;
import java.math.BigInteger;

public class ElGamal {

    // 获取用户输入的素数。
    // static BigInteger p = new BigInteger("13256401");
    static BigInteger p = new BigInteger("14893003337626352152463254152616458181260144281");

    // 计算一个生成元。
    // static BigInteger g = new BigInteger("957");
    static BigInteger g = new BigInteger("4893003337626352152463254152616458181260144281");

    // 选择一个秘密数 a。
    // BigInteger a = new BigInteger(p.bitCount()-1, r);
    static BigInteger a = new BigInteger("843900337326351225463254152616458181260144281");

    public static void main(String[] args) {

        Random r = new Random();    

        // 计算对应的公钥 b。
        BigInteger b = g.modPow(a, p);

        // 打印出我们的公钥。
        System.out.println("p = " + p);
        System.out.println("g = " + g);
        System.out.println("b = " + b);

        // 当发送消息时,发送者选择一个随机数 k。
        BigInteger k = new BigInteger(p.bitCount()-1, r);

        // 在这里,发送者开始计算不涉及实际消息的密码文本的部分。
        BigInteger c1 = g.modPow(k, p);
        BigInteger c2 = b.modPow(k, p);

        // 在这里,我们从用户那里获取消息。
        String msg = "12345678901234567890123456789012345678901234567";
        BigInteger m = new BigInteger(msg.getBytes());
        System.out.println("消息的加密形式 = " + msg);

        // 现在,我们可以计算第二部分密码文本的其余部分。
        c2 = c2.multiply(m);
        c2 = c2.mod(p);

        // 打印出两个密码文本。
        System.out.println("对应的密码文本如下");
        System.out.println("c1 = " + c1);
        System.out.println("c2 = " + c2);

        // 首先,确定 c1 的 a 次幂模 p 的逆。
        BigInteger temp = c1.modPow(a,p);
        temp = temporariness(p);

        // 打印出这个值。
        System.out.println("这里是 c1^ -a = "+temp);

        // 现在,只需将这个值与第二部分密码文本相乘
        BigInteger recover = temp.multiply(c2);
        recover = recover.mod(p);

        // 这将还原出我们的原始消息!
        System.out.println("解密后的消息 = "+recover);
    }
}

如果你需要更多帮助或解释,请随时提问。

英文:

Below is my JAVA code for encrypting clear text (not numbers).
Code includes both encryption and decryption.

The decrypted text doesn't match clear text, what am I doing work?

My code works if I replace BigInteger m = new BigInteger(msg.getBytes()); with this code BigInteger m = new BigInteger(msg);

package com.porsche.main;
import java.util.*;
import java.math.BigInteger;
public class ElGamal {
// Get user input for prime.
// static BigInteger p = new BigInteger("13256401");
static BigInteger p = new BigInteger("14893003337626352152463254152616458181260144281");
// Calculate a generator.
// static BigInteger g = new BigInteger("957");
static BigInteger g = new BigInteger("4893003337626352152463254152616458181260144281");
// Pick a secret a.
// BigInteger a = new BigInteger(p.bitCount()-1, r);
static BigInteger a = new BigInteger("843900337326351225463254152616458181260144281");
public static void main(String[] args) {
Random r = new Random();	
// Calculate the corresponding public b.
BigInteger b = g.modPow(a, p);
// Print out our public keys.
System.out.println("p = " + p);
System.out.println("g = " + g);
System.out.println("b = " + b);
// When we send a message, the sender picks a random k.
BigInteger k = new BigInteger(p.bitCount()-1, r);
// Here, the sender starts calculating parts of the cipher text that
// don't involve the actual message.
BigInteger c1 = g.modPow(k, p);
BigInteger c2 = b.modPow(k, p);
// Here we get the message from the user.
String msg = "12345678901234567890123456789012345678901234567";
BigInteger m = new BigInteger(msg.getBytes());
System.out.println("The message encryption = " + msg);
// Now, we can calculate the rest of the second cipher text.
c2 = c2.multiply(m);
c2 = c2.mod(p);
// Print out the two cipher texts.
System.out.println("The corresponding cipher texts are");
System.out.println("c1 = " + c1);
System.out.println("c2 = " + c2);
// First, determine the inverse of c1 raised to the a power mod p.
BigInteger temp = c1.modPow(a,p);
temp = temporariness(p);
// Print this out.
System.out.println("Here is c1^ -a = "+temp);
// Now, just multiply this by the second cipher text
BigInteger recover = temp.multiply(c2);
recover = recover.mod(p);
// And this will give us our original message back!
System.out.println("The decrypted message = "+recover);
}
}

答案1

得分: 1

以下是翻译好的内容:

你提供的关于“El Gamal”算法的信息很少,所以很难找出你的代码为什么无法按预期工作。在网络上稍微搜索了一下,我找到了一个工作示例代码,与你的代码非常相似,而且它是可行的(http://faculty.washington.edu/moishe/javademos/Security/ElGamal.java)。
请记住,使用BigInteger变量意味着你会得到非常大的数字,这限制了你可以处理的数据(“明文”)的大小。示例代码限制了可以加密和解密的长度为19个字符,更长的明文将无法工作。因此,我使用了与你的不同的明文(“9876543210987654321”)。
结果如下:
El Gamal明文加密
密钥 = 12345678901234567890
p = 15228497165243954393
b = 3
c = 2082886678951242957
输入你的大数消息 --> 明文 = 9876543210987654321
加密
r = 8874033432052511920
EC = 2442890351962647176
b^r mod p = 8525328674077426405
解密
c^r mod p = 11673994647641103379
d = 9011480367194984320
Alice 解码:9876543210987654321
这是工作的代码(与链接的代码相比,几乎没有修改):
import java.math.*;
import java.util.*;
import java.security.*;
import java.io.*;
public class ElGamal2
{
public static void main(String[] args) throws IOException
{
// 来源:http://faculty.washington.edu/moishe/javademos/Security/ElGamal.java
System.out.println("El Gamal明文加密\n");
String msg = "9876543210987654321";
BigInteger p, b, c, secretKey;
Random sc = new SecureRandom();
secretKey = new BigInteger("12345678901234567890");
//
// 计算公钥
//
System.out.println("密钥 = " + secretKey);
p = BigInteger.probablePrime(64, sc);
b = new BigInteger("3");
c = b.modPow(secretKey, p);
System.out.println("p = " + p);
System.out.println("b = " + b);
System.out.println("c = " + c);
//
// 加密
//
System.out.print("输入你的大数消息 --> ");
//String s = Tools.getString();
String s = msg;
BigInteger X = new BigInteger(s);
BigInteger r = new BigInteger(64, sc);
BigInteger EC = X.multiply(c.modPow(r, p)).mod(p);
BigInteger brmodp = b.modPow(r, p);
System.out.println("明文 = " + X);
System.out.println("\n加密");
System.out.println("r = " + r);
System.out.println("EC = " + EC);
System.out.println("b^r mod p = " + brmodp);
//
// 解密
//
System.out.println("\n解密");
BigInteger crmodp = brmodp.modPow(secretKey, p);
BigInteger d = crmodp.modInverse(p);
BigInteger ad = d.multiply(EC).mod(p);
System.out.println("c^r mod p = " + crmodp);
System.out.println("d = " + d);
System.out.println("Alice 解码:" + ad);
}
}

编辑:
关于你的评论:“谢谢回复。明文是否需要只能是数字,它可以是像“Hello World!”这样的文本吗?”:

根据JavaDocs(https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigInteger.html),BigInteger可以使用这些构造函数来创建,它们都有一个共同点 - 它必须是表示BigInteger值的数字,而不是字符:

BigInteger​(byte[] val)
将包含BigInteger的二进制补码表示的字节数组转换为BigInteger。
BigInteger​(byte[] val, int off, int len)
将包含BigInteger的二进制补码表示的字节数组子数组转换为BigInteger。
BigInteger​(int signum, byte[] magnitude)
将BigInteger的符号-大小表示转换为BigInteger。
BigInteger​(int signum, byte[] magnitude, int off, int len)
将BigInteger的符号-大小表示转换为BigInteger。
BigInteger​(int bitLength, int certainty, Random rnd)
构造一个随机生成的可能为质数的正BigInteger,其位长度为指定的bitLength。
BigInteger​(int numBits, Random rnd)
构造一个随机生成的BigInteger,均匀分布在0到(2numBits - 1)范围内,包括两端。
BigInteger​(String val)
将十进制表示的BigInteger的字符串表示转换为BigInteger。
BigInteger​(String val, int radix)
将指定基数中的BigInteger的字符串表示转换为BigInteger。
英文:

You gave very less information about the "El Gamal" algorithm so it is hard to find why your code is not working as expected. Searching a little bit in the net I found a working example code that is very similar to your's and it is working (http://faculty.washington.edu/moishe/javademos/Security/ElGamal.java).

Please keep in mind that working with BigInteger variables mean you will get very large numbers and this is limiting the size of data ("cleartext") you can work with. The sample code has a limit of 19 chars that can be encrypted & decrypted, longer cleartexts won't work. For that reason I used a different cleartext from yours ("9876543210987654321").

The result is here:

El Gamal encryption of clear Text
secretKey = 12345678901234567890
p = 15228497165243954393
b = 3
c = 2082886678951242957
Enter your Big Number message --> Plaintext = 9876543210987654321
Encryption
r = 8874033432052511920
EC = 2442890351962647176
b^r mod p = 8525328674077426405
Decryption
c^r mod p = 11673994647641103379
d = 9011480367194984320
Alice decodes: 9876543210987654321

Thats the working code (minimal changed from the linked one):

import java.math.*;
import java.util.*;
import java.security.*;
import java.io.*;
public class ElGamal2
{
public static void main(String[] args) throws IOException
{
// source http://faculty.washington.edu/moishe/javademos/Security/ElGamal.java
System.out.println("El Gamal encryption of clear Text\n");
String msg = "9876543210987654321";
BigInteger p, b, c, secretKey;
Random sc = new SecureRandom();
secretKey = new BigInteger("12345678901234567890");
//
// public key calculation
//
System.out.println("secretKey = " + secretKey);
p = BigInteger.probablePrime(64, sc);
b = new BigInteger("3");
c = b.modPow(secretKey, p);
System.out.println("p = " + p);
System.out.println("b = " + b);
System.out.println("c = " + c);
//
// Encryption
//
System.out.print("Enter your Big Number message --> ");
//String s = Tools.getString();
String s = msg;
BigInteger X = new BigInteger(s);
BigInteger r = new BigInteger(64, sc);
BigInteger EC = X.multiply(c.modPow(r, p)).mod(p);
BigInteger brmodp = b.modPow(r, p);
System.out.println("Plaintext = " + X);
System.out.println("\nEncryption");
System.out.println("r = " + r);
System.out.println("EC = " + EC);
System.out.println("b^r mod p = " + brmodp);
//
// Decryption
//
System.out.println("\nDecryption");
BigInteger crmodp = brmodp.modPow(secretKey, p);
BigInteger d = crmodp.modInverse(p);
BigInteger ad = d.multiply(EC).mod(p);
System.out.println("c^r mod p = " + crmodp);
System.out.println("d = " + d);
System.out.println("Alice decodes: " + ad);
}
}

Edit:
Regarding your comment "Thanks for the reply. Does the clear text need to be all numbers only, can it be a text something like "Hellow World!"?":

According to the JavaDocs (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigInteger.html) a BigInteger is created with these constructors and all have one thing in common - it has to be a number that represents a BigInteger-value and that's not a char:

BigInteger​(byte[] val)
Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger.
BigInteger​(byte[] val, int off, int len)
Translates a byte sub-array containing the two's-complement binary representation of a BigInteger into a BigInteger.
BigInteger​(int signum, byte[] magnitude)
Translates the sign-magnitude representation of a BigInteger into a BigInteger.
BigInteger​(int signum, byte[] magnitude, int off, int len)
Translates the sign-magnitude representation of a BigInteger into a BigInteger.
BigInteger​(int bitLength, int certainty, Random rnd)
Constructs a randomly generated positive BigInteger that is probably prime, with the specified bitLength.
BigInteger​(int numBits, Random rnd)
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2numBits - 1), inclusive.
BigInteger​(String val)
Translates the decimal String representation of a BigInteger into a BigInteger.
BigInteger​(String val, int radix)
Translates the String representation of a BigInteger in the specified radix into a BigInteger.

huangapple
  • 本文由 发表于 2020年9月11日 07:47:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63839020.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定