Можно ли сгенерировать 2 идентичных зашифрованных текста RSA с одинаковым открытым текстом и открытым ключом?

Я играю с RSA на Android и понимаю, что шифрование RSA генерирует другой зашифрованный текст с использованием одного и того же открытого текста и открытого ключа из-за заполнения. Есть ли способ сгенерировать один и тот же зашифрованный текст с тем же открытым текстом и открытым ключом?

Точно так же различаются ли цифровые подписи между запусками с одинаковым открытым текстом и закрытым ключом, и есть ли способ генерировать одинаковые цифровые подписи?

Вот мой кейген:

        KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
        AlgorithmParameterSpec spec = null;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            spec = new KeyPairGeneratorSpec.Builder(ctx)
                    .setAlias(mAlias)
                    .setSubject(new X500Principal("CN=" + mAlias))
                    .setSerialNumber(BigInteger.valueOf(1337))
                    .setStartDate(start.getTime())
                    .setEndDate(end.getTime())
                    .build();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            spec = new KeyGenParameterSpec.Builder(mAlias,
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                    .build();
        kpGenerator.initialize(spec);
        KeyPair kp = kpGenerator.generateKeyPair();

Вот как я шифрую:

        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(mAlias, null);
        Cipher cip = null;

        RSAPublicKey pubKey = (RSAPublicKey)entry.getCertificate().getPublicKey();
        cip = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cip.init(Cipher.ENCRYPT_MODE, pubKey);

        byte[] encryptBytes = cip.doFinal(challenge.getBytes());

Спасибо.


person user1118764    schedule 02.03.2017    source источник
comment
Можете ли вы показать нам, как вы шифруете? Алгоритм RSA сам по себе является детерминированным, поэтому при одинаковом открытом тексте и открытом ключе зашифрованный вывод не должен отличаться. Если вы используете шифр Java, некоторые из режимов (например, CBC) будут начинаться со случайного IV, если не указано иное.   -  person ephemient    schedule 02.03.2017
comment
Да, вы можете запросить строку шифра без заполнения. Но почему вы хотите это сделать?   -  person Artjom B.    schedule 02.03.2017
comment
Как мне запросить строку шифра без заполнения?   -  person user1118764    schedule 02.03.2017


Ответы (1)


Чтобы всегда генерировать один и тот же зашифрованный текст, используйте алгоритм без заполнения. Замените RSA/ECB/PKCS1Padding на RSA/ECB/NoPadding.

Но, из соображений безопасности, предлагаю использовать алгоритм с отступами и по возможности OAEP RSA/ECB/OAEPWithSHA-1AndMGF1Padding (доступен с андроида 23). Заполнение не должно быть проблемой для стороны дешифрования.

Цифровая подпись PCKS#1 даст тот же результат для того же закрытого ключа и данных для подписи.

person pedrofb    schedule 02.03.2017
comment
Спасибо! Это работает. Вы случайно не знаете, доступен ли ключевой материал только процессу создания/приложению? Кроме того, сохраняется ли материал ключа (как в программном хранилище ключей, так и в хранилище ключей с аппаратной поддержкой)? Под этим я подразумеваю, удаляются ли ключи в KeyStore после удаления создающего приложения, а также после сброса настроек? - person user1118764; 02.03.2017
comment
Ключевой материал доступен (но не извлекается) только создавшему его приложению. Аппаратная поддержка зависит от устройства, если оно доступно, оно будет использоваться (есть метод API для проверки наличия). Если вы удалите приложение или перезагрузите устройство, то ключи больше не будут доступны. - person pedrofb; 02.03.2017
comment
Спасибо. Как насчет рутированного устройства? Смогут ли другие приложения или пользователь root получить доступ к ключевому материалу в этом случае? Кроме того, действительно ли сброс к заводским настройкам также стирает ключевой материал, который поддерживается аппаратно (находится в TEE)? - person user1118764; 02.03.2017
comment
Нет, никто не может извлечь ключевой материал. Посмотрите здесь: developer.android.com/about/versions/android -4.3.html#Security Даже ядро ​​ОС не может получить доступ к этому ключевому материалу. Я не знаю, действительно ли аппаратный сброс удалит ключи (вероятно, да), но они станут непригодными для использования, как если бы вы удалили приложение. - person pedrofb; 02.03.2017
comment
Спасибо еще раз. Это было полезно - person user1118764; 03.03.2017