使用模数和指数进行 RSA 解密

发布于 2024-10-31 07:42:10 字数 2314 浏览 0 评论 0原文

我的任务:我已将(RSA)数据和公钥加密为模数和指数。我必须写解密代码。
我的问题:我的实现不起作用;)据我所知,哲学很简单 "open text" == rsa(public_key, rsa(private_key, "open text") ) 编辑:我的假设完全是错误的(假设是所有fu..ups之母;))。它应该是 "open text" == rsa(private_key, rsa(public_key, "open text")) 因为在 RSA 中,公钥用于加密,私有密钥用于解密。

我假设我可以拥有与加密期间使用的私钥不对应的公钥,因此对于测试,我以这种方式创建了自己的密钥:

openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

我使用命令获得了公钥模数和指数:

openssl x509 -in server.crt -text

对于加密测试我正在使用代码

//Reads private key from file
//StringPasswordFinder is my tmp implementation of PasswordFinder
PEMReader pemReader = new PEMReader(new FileReader("/path/to/server.key"), new StringPasswordFinder());
KeyPair keyPair = (KeyPair) pemReader.readObject();
PrivateKey pk = keyPair.getPrivate();
//text for encryption
String openText = "openText";
//encryption
Cipher rsaCipher = Cipher.getInstance("RSA", "BC");
rsaCipher.init(Cipher.ENCRYPT_MODE, pk);
byte[] encrypted = rsaCipher.doFinal(openText.getBytes("utf-8"));

为了解密加密文本我使用代码

//modulus hex got using openssl
byte[] modulus = Hex.decodeHex("very long hex".toCharArray());
//exponent hex got using openssl
byte[] exponent = Hex.decodeHex("010001".toCharArray());
//initialization of rsa decryption engine
RSAEngine rsaEngine = new RSAEngine();
rsaEngine.init(false, new RSAKeyParameters(false, new BigInteger(modulus), new BigInteger(exponent)));
//input - encrypted stream
ByteArrayInputStream bais = new ByteArrayInputStream(encrypted);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//reading blocks from the input stream and decrypting them
int bytesRead = 0;
byte[] block = new byte[rsaEngine.getInputBlockSize()];
while ((bytesRead = bais.read(block)) > -1) {
    baos.write(rsaEngine.processBlock(block, 0, bytesRead));
}
//dispalying decrypted text
System.out.println(new String(baos.toByteArray(), "utf-8"));

毕竟显示的文本不是。有人能告诉我哪里错了吗?

编辑:总结这个问题没有解决办法。因为不可能使用私钥对消息进行加密,然后使用公钥对其进行解密。一般来说,我将加密与签名消息以及解密与验证混合在一起。因为签名时使用私钥,验证时使用公钥。顺便说一句,MByD 感谢您提供重要线索。

My task: I have encrypted (RSA) data and public key as modulus and exponent. I have to write decryption code.
My problem with it: My implementation doesn't work ;) As far as I know philosophy is simple "open text" == rsa(public_key, rsa(private_key, "open text")) Edit: Exactly my assumption was wrong (Assumption is mother of all fu..ups ;) ). It should be "open text" == rsa(private_key, rsa(public_key, "open text")) because in RSA, public key is used for encryption and private for decryption.

I assumed that I can have public key which doesn't correspond to private key using during encryption so for tests I created own keys in such way:

openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

I got public key modulus and exponent using command:

openssl x509 -in server.crt -text

For encryption testing I'm using code

//Reads private key from file
//StringPasswordFinder is my tmp implementation of PasswordFinder
PEMReader pemReader = new PEMReader(new FileReader("/path/to/server.key"), new StringPasswordFinder());
KeyPair keyPair = (KeyPair) pemReader.readObject();
PrivateKey pk = keyPair.getPrivate();
//text for encryption
String openText = "openText";
//encryption
Cipher rsaCipher = Cipher.getInstance("RSA", "BC");
rsaCipher.init(Cipher.ENCRYPT_MODE, pk);
byte[] encrypted = rsaCipher.doFinal(openText.getBytes("utf-8"));

And for decryption of encrypted text I use code

//modulus hex got using openssl
byte[] modulus = Hex.decodeHex("very long hex".toCharArray());
//exponent hex got using openssl
byte[] exponent = Hex.decodeHex("010001".toCharArray());
//initialization of rsa decryption engine
RSAEngine rsaEngine = new RSAEngine();
rsaEngine.init(false, new RSAKeyParameters(false, new BigInteger(modulus), new BigInteger(exponent)));
//input - encrypted stream
ByteArrayInputStream bais = new ByteArrayInputStream(encrypted);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//reading blocks from the input stream and decrypting them
int bytesRead = 0;
byte[] block = new byte[rsaEngine.getInputBlockSize()];
while ((bytesRead = bais.read(block)) > -1) {
    baos.write(rsaEngine.processBlock(block, 0, bytesRead));
}
//dispalying decrypted text
System.out.println(new String(baos.toByteArray(), "utf-8"));

And after all displayed text is not. Can anybody show me where I'm wrong?

Edit: Summing up this problem has no solution. Because it's not possible encrypt message using private key and later decrypt it using public one. At general I mixed up encryption with signing message and decryption with verification. Because during making signature private key is used and public is used during verification. Btw, MByD thx for important clue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

同尘 2024-11-07 07:42:10

我对 RSA 的 java 库不太熟悉,我尝试在 java 中实现 RSA 的时候是自己构建所有计算,但是如果我理解正确,我看到两个问题:

  1. 数据应该用公钥加密并用私钥解密,而不是相反(因为拥有公钥的每个人都能够解密它......)
  2. 公钥应该与私钥匹配,否则,任何拥有私钥的人都会能够解密使用任何公钥加密的数据...

此外,对于很长的数据,您不应该使用公钥加密。相反,使用其他算法(RC4、AES 等)加密数据并使用 RSA 加密密钥(类似于 PGP 方法)

I am not so familiar with java libraries for RSA, the times I tried to implement RSA in java was to build all calculations by myself, but if I understood you correct, I see 2 problems:

  1. the data should be encrypted with the public key and decrypted with private key, not the other way around (since everyone with public key will be able to decrypt it...)
  2. the public key should match the private key, otherwise, anyone with any private key will be able to decrypt data encrypted with any public key...

Also, for very long data, you should not use public key encryption. Instead, encrypt the data in some other algorithm (RC4, AES, etc.) and encrypt the key in RSA (similar to PGP approach)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文