2011-01-21 4 views
0

У меня возникли проблемы с шифрованием открытым ключом RSA. Вот пример кода JUnit, который воспроизводит проблему:Java RSA Encryption не повторяется?

public class CryptoTests { 

private static KeyPair keys; 

@BeforeClass 
public static void init() throws NoSuchAlgorithmException{ 
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); 
    SecureRandom random = CryptoUtils.getSecureRandom(); 
    keyGen.initialize(2176, random); 
    keys = keyGen.generateKeyPair(); 
} 
@Test 
public void testRepeatabilityPlainRSAPublic() throws EdrmCryptoException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{ 
    byte[] plaintext = new byte [10]; 
    Random r = new Random(); 
    r.nextBytes(plaintext); 

    Cipher rsa = Cipher.getInstance("RSA"); 
    rsa.init(Cipher.ENCRYPT_MODE, keys.getPublic()); 
    byte[] encrypted1 = rsa.doFinal(plaintext); 

    rsa = Cipher.getInstance("RSA"); 
    rsa.init(Cipher.ENCRYPT_MODE, keys.getPublic()); 
    byte[] encrypted2 = rsa.doFinal(plaintext); 

    rsa = Cipher.getInstance("RSA"); 
    rsa.init(Cipher.ENCRYPT_MODE, keys.getPublic()); 
    byte[] encrypted3 = rsa.doFinal(plaintext); 

    assertArrayEquals(encrypted1, encrypted2); 
    assertArrayEquals(encrypted1, encrypted3); 
} 
} 

В результате? Утверждение терпит неудачу.

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

Если по какой-либо причине шифрование RSA с открытым ключом запрещено, то почему я не получаю исключение?

Что я должен сделать, чтобы получить повторяющиеся результаты?

P.S. Мой JDK - 1.6.0_22, работающий на Ubuntu 10.10.

+0

P.S. Я использовал провайдера BouncyCastle, и мои тесты сейчас успешны. – malaverdiere

+0

Этот тест является действительно плохим знаком, поскольку шифрование RSA * должно быть рандомизировано. Очень важно использовать дополнение OEAP с шифрованием RSA. Ни одно учебное приложение RSA и PKCS # 1 v1.5 не защищено. – CodesInChaos

ответ

7

My Угадай это то, что оно применяет рандомизированное заполнение, чтобы сделать его более безопасным. Из RSA wikipedia page:

Поскольку шифрование RSA является детерминированным алгоритмом шифрования - т.е. не имеет случайную составляющей - злоумышленник может успешно запустить выбранную открытый текст атаки против криптосистемы, путем шифрования вероятных открытых текстов под открытым ключом и испытанием, если они равны зашифрованному тексту. Криптосистема называется семантически безопасной, если злоумышленник не может отличить две шифровки друг от друга, даже если злоумышленник знает (или выбрал) соответствующие открытые тексты. Как описано выше, RSA без заполнения не является семантически безопасным.

...

Чтобы избежать этих проблем, практические реализации RSA обычно встраивать некоторую форму структурированного рандомизированного заполнения в значение т перед шифрованием. Это заполнение гарантирует, что m не попадает в диапазон небезопасных открытых текстов и что данное сообщение, после заполнения, будет шифровать одно из большого числа различных возможных зашифрованных текстов.

+0

(+1) на одну минуту быстрее, и лучше объяснил, чем я. – Ralph

+1

Да - что на самом деле имеет значение, является ли оно ДЕКРИПЦИЯми одним и тем же оригинальным открытым текстом. –

1

Вы можете подтвердить, что происходит то, что случайное заполнение добавляется путем инициализации вашего шифра строкой «RSA/ECB/NoPadding». Теперь вы должны увидеть, что зашифрованный текст идентичен в каждом случае (хотя по причинам, указанным другим ответчиком, вы не должны делать это на практике).

0

Чтобы добавить дополнительные детали к ответу Джона:

Когда вы Cipher.getInstance("...") у вас есть несколько вариантов, как вы уже, наверное, собрались. The Standard Algorithm Names укажите, что это такое.

Тот, который вы просили, RSA по умолчанию RSA под PKCS1, который, цитировать Википедию статью:

Есть две схемы для шифрования и дешифрования :

  • RSAES- OAEP: улучшенная схема шифрования/дешифрования; основанный на Оптимальное асимметричное шифрование Схема заполнения, предложенная Mihir Bellare и Phillip Rogaway.
  • RSAES-PKCS1-v1_5: более ранняя схема шифрования/дешифрования как первая , стандартизованная в версии 1.5 PKCS # 1.

См RSALab-х PKCS1 documentation для деталей из указанных схем отступов.

+1

Важно подчеркнуть, что 'RSAES-PKCS1-v1_5' допускает практические атаки, поэтому ** не следует использовать **. «RSAES-OAEP» - это путь. – CodesInChaos