Шифрование RSA: разница между Java и Android - PullRequest
26 голосов
/ 20 мая 2011

Я использую RSA для шифрования имени пользователя и пароля на Android и расшифровки их на сервере (tomcat 6, java 1.6). Шифрование Android:

    PublicKey pubKey = readPublicKeyFromFile(mod, ex);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    byte[] cipherData = cipher.doFinal(data);
    return cipherData;

Расшифровка Java Tomcat:

    PrivateKey pubKey = readPrivateKeyFromFile(mod, ex);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, pubKey);
    byte[] cipherData = cipher.doFinal(data);
    return cipherData;

Если я использую часть андроида ВНЕ андроида (только в основном методе), он работает нормально. Но не внутри моего андроида (эмулятора). На стороне сервера я получаю следующую ошибку:

javax.crypto.BadPaddingException: Blocktype mismatch: 0
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:311)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255)
    at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)

Я сохраняю mod и ex константами BigIntegers, поэтому не записываю их в файл. Я знаю, что есть разница между шифрованием java1.6 и java 1.5, поэтому оба скомпилированы с java 1.6.

Некоторая отладочная информация:

Во время отладки в Android я вижу, что pubKey содержит модуль и показатель в шестнадцатеричном формате. И если я отлаживаю в основном методе (опять тот же код), я вижу, что pubKey содержит модуль и показатель степени в десятичном виде.

Что я делаю не так?

Спасибо

Ответы [ 3 ]

42 голосов
/ 14 октября 2011

Я делаю RSA Encrypt в Android 2.2+ и расшифровываю на сервере Tomcat 6 java 1.6.

Я получил именно эту проблему, читая повсюду, и частично благодаря ответу @Femi я наткнулся на то, что мне нужно.

Решением было использовать спецификацию алгоритма для шифра следующим образом:

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

Работает с шифрованием на смартфонах Android и BlackBerry. Я знаю, что прошло четыре месяца с тех пор, как вопрос был задан, но на тот случай, если кто-то еще пройдет через эту проблему.

11 голосов
/ 23 мая 2011

Я предлагаю вам использовать специальную инициализацию шифра: в качестве примера,

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");

будет работать на обоих. Возникает исключение ( BadPaddingException ), так как заполнение инициализации шифра по умолчанию, по-видимому, отличается между JVM рабочего стола и JVM Android.

1 голос
/ 23 мая 2011

Во-первых, похоже, что вы инициализируете оба шифра с открытым ключом. Для шифрования используется открытый ключ, для расшифровки используется закрытый ключ. Я надеюсь, что это просто опечатка.

У меня тоже было много проблем с шифрованием RSA, много было проб и ошибок. Я предлагаю вам попробовать другого поставщика. Мне удалось реализовать RSA с помощью BouncyCastle.

Cipher wrapper = Cipher.getInstance("RSA", "BC");
wrapper.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedData= wrapper.doFinal(unencryptedData);

Хотя я сгенерировал свою собственную пару ключей, поскольку это было шифрование сеанса.

kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.genKeyPair();
        publicKey = kp.getPublic();
        privateKey = kp.getPrivate();
...