简体   繁体   中英

Decrypt with public key?

I've made a mistake when I was writing a promgram in Java.

package cf.huzpsb.jnip.security;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class Cipher {
    private static final byte[] pub = Base64.getDecoder().decode("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUjb+/Ea3i9W53tASAu5OJ8vxf7+7oGberM5B6GIfu2uBMD0YfaQuGqInREop6kho7AHYd4oCq68fhQ4DbAtE+RSy9Us4sCMpvvE4luLWoR3iZQtii7hyIoDSeXGaNVu6L3xbjFji7kSDPpWubdCuD6dCVYD5kS2N07m74d5grOwIDAQAB");
    private static final byte[] pri = Base64.getDecoder().decode("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJSNv78RreL1bne0BIC7k4ny/F/v7ugZt6szkHoYh+7a4EwPRh9pC4aoidESinqSGjsAdh3igKrrx+FDgNsC0T5FLL1SziwIym+8TiW4tahHeJlC2KLuHIigNJ5cZo1W7ovfFuMWOLuRIM+la5t0K4Pp0JVgPmRLY3Tubvh3mCs7AgMBAAECgYAPimSs0GSogZR04Vg3P2hH3iuYvbj4fvg/6L0MiNRvoGYmjtJ/JrYV+Duyq4XhHLexxHKW3cMoHlJitnUcdEb/W5L0iOSXRN4W1WGBkGLv+FE3TbFT0ruxbLTdcK+cmiE6hWh2sO9xVXjIPxixuTrDvd7qyO0XyX0aNUU0/42FQQJBANwpKF6ZJRIHvF32RIfPjAxkTEY6Mq8IbxeuxsbN3IJ1aywK3bQdSxz0rd+b/gR/3CJhjp9OUGt0KqYm6emVJrcCQQCsvHu30wrK8qfjQmlVxYlwgVitb3u+pgRPO64neuucsbXPUEYnB/Ae9Y1QrdRUBWInhWfXpRK7m4LzK0udJvudAkEArWU9BkRXjfvJv7dWAiDUjG3yJN1xTam21VAx/iHkqlsQLX/hXRo1LnkG+DZDugd5uRpc2ds0O20iqfm8ANwXwQJBAIVagdy5lfR1/zzIkY+BEAkGIpLKpWrauir9NQcPs4PmAilJnM8XJr6P7YgimvA+s7c1G6T0sJCbjy3x988cQFUCQBnPIMFNyfz+t9Cg+gA42ivbKQC9OnIpTD0Jsm8gyvh1C15Pkb4I0WYOQuh66AWHwrlqlkF6IdUVyM8JlNArI/M=");

    public static String encrypt(String text) {
        try {
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pri);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, privateKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(text.getBytes()));
        } catch (Exception e) {
            return "Failed";
        }
    }

    public static String decrypt(String text) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pub);
            PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(javax.crypto.Cipher.DECRYPT_MODE, pubKey);
            return new String(cipher.doFinal(Base64.getDecoder().decode(text)));
        } catch (Exception e) {
            return "Failed";
        }
    }
}

As you can see, I've used the wrong key when trying to encrypt/decrypt the data. However, the code didn't generate any exception.

If I compile and run:

String str = Cipher.encrypt("uwu");
System.out.println(str);
System.out.println(Cipher.decrypt(str));

The console would show:

GrKyCCML73yuJN/fsdevN00eOvWUDl7MTpW50iWhhnhqhMxelWPEQ4I2A7PPd0G8flVaZrabAIsYNNUBpEg96x+8zj3ZTh5u9rXbhJKbzHXSMbsuPCY39WqUOf6qqqWRxGL44E3ltIdE/wQr7XeRvqJa4Z089mSxl6VYB468BnA=
uwu

Although I've fixed the mistake, I still have a question:

What's going on here? Why did it seemingly running "properly"?


Edit:

I've seen some may say that it's a type of "sign". But if that's the case, is there a way that I read the data without either key, if I don't care whether or not the data is tampered? Why or why not? Thanks!

Trying to encrypt data using RSA with a private key doesn't make sense. However, instead of throwing an exception when trying to do so, the Cipher class does something a little different. It assumes that you want to perform a signature operation and that you are supplying just the payload portion of the signature. It will then apply the PKCS1 padding string directly to your data, in this case the padding is 0x00 0x01 followed by as many 0xff 0xff... 0xff 0x00 bytes as needed to fill out the length of the RSA block (128 bytes in this case) apply the exponentiation primitive with the private exponent. Thus the padded contents look like this in hex:

0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00757775

Proper PKCS1 signing requires that the data is hashed and then encapsulated into a DigestInfo ASN.1 structure, but Cipher doesn't do that. The Signature class will do that however.

The result can only be verified (or "decrypted") with the correct public key. You can't get the plaintext unless you have the public key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM