Android RSA Keypair Generation - Должен ли я использовать стандартный Java/Bouncy Castle/Spongy Castle/JSch/Other?

Я искал около недели + для реализации метода, который я имею в виду. Я натолкнулся (и прочитал) много статей по всем этим различным методам, но я все еще оставлен в замешательстве, поэтому я надеялся, что кто-то сможет распространять свои знания по этим темам, чтобы я мог более легко начать создавать мой популярный метод и реализуя его в Android.

Мой метод поиска:

  • Должен генерировать общедоступные и приватные ключи RSA
  • Публика должна иметь дополнение PKCS # 1
  • Должно быть RSA 2048
  • Возвращает открытый ключ в массиве байтов

Очевидно, вы можете использовать четыре способа:

  • Стандартная Java
  • Bouncy Castle
  • Spongy Castle (Android Friendly?)
  • JSch

Поскольку я очень новичок в сфере безопасности и Java в целом, мне было интересно, может ли кто-нибудь наконец дать хорошее четкое объяснение всего этого.

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

1. Стандартная Java (не уверен, что PKCS # 1):

public byte[] returnPublicKeyInBytes() throws NoSuchAlgorithmException {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair keyPair = kpg.genKeyPair();
    byte[] pri = keyPair.getPrivate().getEncoded();
    byte[] pub = keyPair.getPublic().getEncoded();
    return pub;
}

2. Bouncy Castle (еще не функционирует =/Идеи?):

public byte[] returnPublicKeyInBytes() throws NoSuchAlgorithmException {
    RSAKeyPairGenerator r = new RSAKeyPairGenerator();
    r.init(new KeyGenerationParameters(new SecureRandom(),4096));
    AsymmetricCipherKeyPair keys = r.generateKeyPair();
    CipherParameters pri = keys.getPrivate();
    CipherParameters pub = keys.getPublic();
    byte[] pubbyte = pub.toString().getBytes();
    return pubbyte; //NOT WORKING
}

3. SpongyCastle (Havn't начал/То же, что и Bouncy Castle?):

4. JSch (очень не работает/не работает)

public byte[] returnPublicKeyInBytes(JSch jSch) {
    try { 
        KeyPair keyPair = KeyPair.genKeyPair(jSch, KeyPair.RSA);
        ByteArrayOutputStream bs = new ByteArrayOutputStream(); 
        keyPair.writePrivateKey(bs); 
        jSch.addIdentity("Generated", bs.toByteArray(), keyPair.getPublicKeyBlob(), null);
        return keyPair.getPublicKeyBlob(); 
    } catch (JSchException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
    }
    return null;
}

Мне бы хотелось, чтобы это действительно стало ресурсом для всех, у кого возникли проблемы с генерацией ключей RSA в Android (например, я и многие другие).


Я чувствую, что у Bouncy Castle очень мало информации об этом API, что делает его чрезвычайно трудным для начинающего (как я), чтобы понять его. Из моих исследований люди используют Bouncy Castle в Java вместо встроенного поставщика безопасности, потому что Bouncy Castle гораздо более надежный. Использование Bouncy Castle в Android не желательно, потому что оно "поставляется с поврежденной версией Bouncy Castle", которое может быть подвержено ошибкам. Spongy Castle - это просто переупаковка замка Bouncy.

С этой целью я задам свой последний вопрос о том, какой метод следует использовать для Android?

Update

Надеюсь, кто-то сможет ответить на это позже. Что касается того, что я сделал для решения моей проблемы, было просто использовать NDK.

Ответ 1

Это сложно, но я постараюсь объяснить, насколько это возможно. Думаю, я начну с Java. Мое обсуждение ориентировано на Java 6, я не уверен, что изменилось в Java 7.

Встроенная криптография Java доступна через расширение Java Cryptography Extension (JCE). Это расширение имеет две части: API приложения и API поставщика услуг. API приложения - это часть, с которой вы взаимодействуете. Вы используете методы getInstance() factory для различных криптографических классов. Аспект поставщика услуг более запутанный для среднего программиста. Они не заботятся о том, как криптография реализована, они просто хотят что-то, что работает. Но под капотом есть классы криптопровайдера, которые выполняют фактическую работу. Если вы посмотрите на аргументы getInstance(), вы увидите, что вы можете указать поставщика, если хотите. Зачем вам когда-нибудь захотеть? Возможно, вы заплатили $$$ за оптимизированную коммерческую реализацию RSA, поэтому вы хотите использовать ее. Возможно, у одного провайдера есть сертификат FIPS или какой-либо другой сертификат, который вам нужен для вашего приложения. Затем вы должны указать этого провайдера. Sun/Oracle отправляет свою среду Java с несколькими поставщиками, которые вместе составляют набор поставщиков по умолчанию для своей среды Java. Не смотрите на них слишком тщательно, потому что они накладываются друг на друга и, таким образом, запутываются из-за исторических артефактов. В основном, когда вы используете Oracle Java, вы запрашиваете некоторый криптоподобие, как KeyPairGenerator через KeyPairGenerator.getInstance("RSA");, вы получите соответствующий экземпляр класса от одного из этих поставщиков.

Далее, давайте посмотрим на bouncycastle. Библиотека bouncycastle состоит из двух частей. Одна из них - их уникальная крипто-библиотека, API которой вы экспериментировали в своем # 2 выше. Вторая часть - это много кода клея, позволяющего использовать эту библиотеку в качестве поставщика шифрования для JCE. Это означает, что у вас, как у программиста, есть выбор в том, как вы используете библиотеку криптовальной системы bouncycastle. Вы можете использовать их API напрямую, как в № 2 выше. Или вы можете использовать JCE api, но явно указывать реализацию bouncycastle чем-то вроде KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");.

Если вы предпочитаете использовать уникальный API-интерфейс bouncycastle напрямую (они называют его своим "легким API" ), тогда вам не нужен весь код клея, используемый для работы в качестве поставщика JCE. Для этого bouncycastle действительно обеспечивает загрузку только легких классов API.

И теперь, наконец, мы смотрим на реализацию Android. Google не лицензировал исходный код Oracle Java, поэтому у них не было ни одного поставщика Oracle JCE. Они должны были предоставить своих поставщиков. Поскольку у bouncycastle был весь необходимый код, он был с открытым исходным кодом и лицензированно лицензирован, Google/Android решил использовать bouncycastle в качестве основы для своего поставщика JCE по умолчанию. Но Android не прилагает никаких усилий, чтобы сделать доступным уникальный легкий API для Android-программистов. Они ожидают, что вы будете использовать эти классы исключительно через JCE. Они изменили код bouncycastle, чтобы настроить его для Android. Они факт, что вы можете найти и, возможно, использовать некоторые из легких API непосредственно на Android, просто побочный эффект от того, что он находится под капотом. И не все. Некоторые из них описали эту ситуацию, поскольку "bouncycastle на Android искалечен".

Чтобы на самом деле предоставить полнофункциональную версию библиотеки bouncycastle на Android, некоторые разработчики создали нечто, называемое библиотекой Spongycastle. Это не что иное, как библиотека bouncycastle, модифицированная так, чтобы она могла работать на Android. Главной модификацией было изменение имен пакетов от org.bouncycastle.* до org.spongycastle.* для предотвращения конфликтов пространства имен.

Итак, что вы должны использовать? Это зависит от того, что вы хотите делать, каковы ваши потребности в переносимости, каковы ваши предпочтения в стиле, и каков ваш уровень криптографии. В общем, когда вы используете эти библиотеки, вы используете криптографию на довольно низком уровне. Вы концентрируетесь на том, как это сделать (используйте RSA для транспортировки ключей, используйте AES для шифрования сообщений, используйте HMAC-SHA256 для целостности сообщений и т.д.) В сравнении с тем, что делать (я хочу отправить зашифрованное сообщение получателю по электронной почте подобный механизм). Очевидно, что если вы можете придерживаться библиотек более высокого уровня, которые непосредственно решают вашу проблему. Эти библиотеки уже понимают, что такое PKCS # 1 и как использовать его как часть более крупных и более полных протоколов.