Ошибка расшифровки RSA из-за входной строки

У меня следующая проблема. У меня есть 2 функции в моем коде, которые предназначены для шифрования / дешифрования простой строки.

ТАК:

Я должен передать строку "someString" в функцию:

public static String doEncryption(String input) {


    try {

        if (!RSAService.areKeysPresent()) {
            RSAService.generateKey();
        }


        ObjectInputStream inputStream;

        // Encrypt the string using the public key
        inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        PublicKey publicKey = (PublicKey) inputStream.readObject();
        byte[] cipherText = RSAService.encrypt(input, publicKey);
        return cipherText.toString();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return "ERROR: Public key file is probably missing";
}

функция doEncryption("someString") возвращает "[B@61decc8c"

Теперь мне нужно вставить эту строку в URL, и код на стороне сервера должен получить ее оттуда.

Пока все хорошо, но когда я вызываю функцию

public static String doDecryption(String input) {

           try {

        if (!RSAService.areKeysPresent()) {
            RSAService.generateKey();
        }

        ObjectInputStream inputStream;


        // Decrypt the cipher text using the private key.
        inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        PrivateKey privateKey = (PrivateKey) inputStream.readObject();
        String out = decrypt(input.getBytes(), privateKey);
        return out;

    } catch (Exception e) {
        e.printStackTrace();
    }
    return "ERROR: Private key file is probably missing or doesn't match the public key";
}

doDecryption("[B@61decc8c") кричит со следующим исключением:

javax.crypto.BadPaddingException: Data must start with zero
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:325)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at rsaendecryptor.RSAService.decrypt(RSAService.java:132)
    at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
    at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)
java.lang.NullPointerException
    at java.lang.String.<init>(String.java:556)
    at rsaendecryptor.RSAService.decrypt(RSAService.java:138)
    at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
    at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)

Есть ли способ, которым я могу обойти это? Я должен передать строку между клиентом и сервером, потому что они могут быть даже в разных доменах. Не говоря уже о том, что строка будет фактически сгенерирована из логики. Net и отправлена ​​на серверную часть Java. Шифрование в строку работает нормально... Что я должен сделать, чтобы исправить дешифрование.

Вот полный код класса:

public class RSAService {

/**
 * String to hold name of the encryption algorithm.
 */
public static final String ALGORITHM = "RSA";

/**
 * String to hold the name of the private key file.
 */
public static final String PRIVATE_KEY_FILE = "private.key";

/**
 * String to hold name of the public key file.
 */
public static final String PUBLIC_KEY_FILE = "public.key";

/**
 * Generate key which contains a pair of private and public key using 1024
 * bytes. Store the set of keys in Prvate.key and Public.key files.
 *
 */
public static void generateKey() {

    try {
        final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
        keyGen.initialize(1024);
        final KeyPair key = keyGen.generateKeyPair();

        File privateKeyFile = new File(PRIVATE_KEY_FILE);
        File publicKeyFile = new File(PUBLIC_KEY_FILE);

        // Create files to store public and private key
        privateKeyFile.createNewFile();

        if (publicKeyFile.getParentFile() != null) {
            publicKeyFile.getParentFile().mkdirs();
        }
        publicKeyFile.createNewFile();

        // Saving the Public key in a file
        ObjectOutputStream publicKeyOS = new ObjectOutputStream(
                new FileOutputStream(publicKeyFile));
        publicKeyOS.writeObject(key.getPublic());
        publicKeyOS.close();

        // Saving the Private key in a file
        ObjectOutputStream privateKeyOS = new ObjectOutputStream(
                new FileOutputStream(privateKeyFile));
        privateKeyOS.writeObject(key.getPrivate());
        privateKeyOS.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

/**
 * The method checks if the pair of public and private key has been
 * generated.
 *
 * @return flag indicating if the pair of keys were generated.
 */
public static boolean areKeysPresent() {

    File privateKey = new File(PRIVATE_KEY_FILE);
    File publicKey = new File(PUBLIC_KEY_FILE);

    if (privateKey.exists() && publicKey.exists()) {
        return true;
    }
    return false;
}

/**
 * Encrypt the plain text using public key.
 *
 * @param text : original plain text
 * @param key :The public key
 * @return Encrypted text
 * @throws java.lang.Exception
 */
public static byte[] encrypt(String text, PublicKey key) {
    byte[] cipherText = null;
    try {
        // get an RSA cipher object and print the provider
        final Cipher cipher = Cipher.getInstance(ALGORITHM);
        // encrypt the plain text using the public key
        cipher.init(Cipher.ENCRYPT_MODE, key);
        cipherText = cipher.doFinal(text.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return cipherText;
}

/**
 * Decrypt text using private key.
 *
 * @param text :encrypted text
 * @param key :The private key
 * @return plain text
 * @throws java.lang.Exception
 */
public static String decrypt(byte[] text, PrivateKey key) {
    byte[] dectyptedText = null;
    try {
        // get an RSA cipher object and print the provider
        final Cipher cipher = Cipher.getInstance(ALGORITHM);

        // decrypt the text using the private key
        cipher.init(Cipher.DECRYPT_MODE, key);
        dectyptedText = cipher.doFinal(text);

    } catch (Exception ex) {
        ex.printStackTrace();
    }

    return new String(dectyptedText);
}

public static String doEncryption(String input) {


    try {

        if (!RSAService.areKeysPresent()) {
            RSAService.generateKey();
        }


        ObjectInputStream inputStream;

        // Encrypt the string using the public key
        inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        PublicKey publicKey = (PublicKey) inputStream.readObject();
        byte[] cipherText = RSAService.encrypt(input, publicKey);
        return cipherText.toString();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return "ERROR: Public key file is probably missing";
}


public static String doDecryption(String input) {

           try {

        if (!RSAService.areKeysPresent()) {
            RSAService.generateKey();
        }

        ObjectInputStream inputStream;


        // Decrypt the cipher text using the private key.
        inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        PrivateKey privateKey = (PrivateKey) inputStream.readObject();
        String out = decrypt(input.getBytes(), privateKey);
        return out;

    } catch (Exception e) {
        e.printStackTrace();
    }
    return "ERROR: Private key file is probably missing or doesn't match the public key";
}

}

2 ответа

Решение
public static String doEncryption(String input)

Остановись прямо там. String не является контейнером для двоичных данных, и, следовательно, не должен был использоваться, чтобы в первую очередь содержать зашифрованный текст. Это должно было быть передано как byte[],

Обратите внимание: когда вы получаете исключение, не пытайтесь угадать, каково было условие, и возвращайте строку, которая говорит, что это было "вероятно". Это делает отладку, угадывание пришло. Используйте сообщение, которое пришло с исключением.

Благодаря shikjohari и этой статье я смог исправить свой код!

в doEncryption() Метод я изменил возвращение следующим образом:

return (Base64.encode(cipherText)).toString();

И в doDecryption() Метод я изменил возвращение следующим образом:

String out = decrypt(Base64.decode(input), privateKey);
return out;

Вы можете получить полный код из моего первого поста и просто отредактировать результаты двух методов согласно этому посту. Надеюсь это поможет.

Другие вопросы по тегам