Java ненадежное RSA-шифрование / дешифрование строк - PullRequest
2 голосов
/ 03 марта 2012

У меня очень неприятная проблема с ненадежным шифрованием и дешифрованием строки с помощью алгоритма RSA в Java.Похоже, он работает только в 35% случаев, и я не могу понять, почему иногда это работает, а иногда нет.Вот некоторый тестовый код, который я написал, чтобы попытаться проверить случайность при шифровании / дешифровании.Он проходит 100 кругов, каждый раз шифрует и дешифрует одну и ту же строку и печатает число успешных попыток:

    public static void main(String[] args) throws Exception {
    byte[] dataToEncrypt = "Hello World!".getBytes("UTF-16LE");
    byte[] cipherData = null;
    byte[] decryptedData;

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(512);
    KeyPair kp = kpg.genKeyPair();
    Key publicKey = kp.getPublic();
    Key privateKey = kp.getPrivate();
    KeyFactory fact = KeyFactory.getInstance("RSA");

    RSAPublicKeySpec pub = (RSAPublicKeySpec) fact.getKeySpec(publicKey,
            RSAPublicKeySpec.class);

    RSAPublicKeySpec spec = new RSAPublicKeySpec(pub.getModulus(), pub
            .getPublicExponent());
    KeyFactory factory = KeyFactory.getInstance("RSA");

    PublicKey publicKeyRSA = factory.generatePublic(spec);
    Cipher cipher = Cipher.getInstance("RSA");

    int k = 0;
    for (int i = 0; i < 100; i++) {
        try {
            cipher.init(Cipher.ENCRYPT_MODE, publicKeyRSA);
            cipherData = cipher.doFinal(dataToEncrypt);
        } catch (Exception e1) {
            System.out.println("Encrypt error");
        }

        String s = new String(cipherData, "UTF-16LE");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        try {
            decryptedData = cipher.doFinal(s.getBytes("UTF-16LE"));
            System.out.println("Decrypted: "
                    + new String(decryptedData, "UTF-16LE"));
            k += 1;
        } catch (Exception e1) {
            System.out.println("Decrypt error");
        }
    }
    System.out.println("Number of correct decryptions is: " + k);

}

Я попытался инициализировать KeyPairGenerator различными значениями без какого-либо успеха.

Редактировать: теперь это работает как шарм, благодаря Base64 :

    import java.io.FileOutputStream;
    import java.io.OutputStream;
    import java.security.Key;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PublicKey;
    import java.security.spec.RSAPublicKeySpec;
    import javax.crypto.Cipher;

    public class Test {

    public static void main(String[] args) throws Exception {
    byte[] dataToEncrypt = "Hello World!".getBytes("UTF-16LE");
    byte[] cipherData = null;
    byte[] decryptedData;


    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(512);
    KeyPair kp = kpg.genKeyPair();
    Key publicKey = kp.getPublic();
    Key privateKey = kp.getPrivate();
    KeyFactory fact = KeyFactory.getInstance("RSA");

    RSAPublicKeySpec pub = (RSAPublicKeySpec) fact.getKeySpec(publicKey,
            RSAPublicKeySpec.class);

    RSAPublicKeySpec spec = new RSAPublicKeySpec(pub.getModulus(), pub
            .getPublicExponent());
    KeyFactory factory = KeyFactory.getInstance("RSA");

    PublicKey publicKeyRSA = factory.generatePublic(spec);
    Cipher cipher = Cipher.getInstance("RSA");

    int k = 0;
    for (int i = 0; i < 100; i++) {
        try {
            cipher.init(Cipher.ENCRYPT_MODE, publicKeyRSA);
            cipherData = cipher.doFinal(dataToEncrypt);
        } catch (Exception e1) {
            System.out.println("Encrypt error");
        }

        String s = Base64.encodeBytes(cipherData);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        try {
            decryptedData = cipher.doFinal(Base64.decode(s));
            System.out.println("Decrypted: "
                    + new String(decryptedData, "UTF-16LE"));
            k += 1;
        } catch (Exception e1) {
            System.out.println("Decrypt error");
        }
    }
    System.out.println("Number of correct decryptions is: " + k);

}

}

Ответы [ 2 ]

5 голосов
/ 03 марта 2012

Это проблема, или, по крайней мере, a проблема:

String s = new String(cipherData, "UTF-16LE");

Вы берете произвольные двоичные данные и пытаетесь создать из них строку, обрабатывая его так, как если бы он был в кодировке UTF-16.Это не.Это произвольные двоичные данные.

Либо сохраните их в двоичном виде (как byte[]), либо используйте base64 для преобразования его в текст безопасным и обратимым образом.( Этот общедоступный кодировщик base64 имеет приемлемый API, например.)

4 голосов
/ 03 марта 2012

Возможно, потому что вы конвертируете зашифрованный поток сообщений в UTF16-LE, чего не следует делать.

...