Ошибка заполнения при использовании шифрования RSA в C # и дешифрования в Java

В настоящее время я получаю следующую ошибку при использовании Java для расшифровки зашифрованной строки RSA в кодировке Base64, созданной на C #:

javax.crypto.BadPaddingException: не PKCS # 1 тип блока 2 или нулевое заполнение

Процесс настройки между обменом между .NET и Java выполняется путем создания закрытого ключа в хранилище ключей .NET, а затем из извлеченного файла PEM, созданного с помощью keytool для создания версии JKS с закрытым ключом. Java загружает уже созданный JKS и декодирует строку Base64 в массив байтов, а затем использует закрытый ключ для дешифрования.

Вот код, который у меня есть на C #, который создает зашифрованную строку:

public string Encrypt(string value) {
    byte[] baIn = null;
    byte[] baRet = null;
    string keyContainerName = "test";

    CspParameters cp = new CspParameters();
    cp.Flags = CspProviderFlags.UseMachineKeyStore;
    cp.KeyContainerName = keyContainerName;
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);

    // Convert the input string to a byte array 
    baIn = UnicodeEncoding.Unicode.GetBytes(value);

    // Encrypt
    baRet = rsa.Encrypt(baIn, false);

    // Convert the encrypted byte array to a base64 string
    return Convert.ToBase64String(baRet);
}

Вот код, который у меня есть в Java, который расшифровывает введенную строку:

public void decrypt(String base64String) {
    String keyStorePath = "C:\Key.keystore";
    String storepass = "1234";
    String keypass = "abcd";
    byte[] data = Base64.decode(base64String);
    byte[] cipherData = null;

    keystore = KeyStore.getInstance("JKS");
    keystore.load(new FileInputStream(keyStorePath), storepass.toCharArray());

    RSAPrivateKey privateRSAKey = (RSAPrivateKey) keystore.getKey(alias, keypass.toCharArray());

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateRSAKey);
    cipherData = cipher.doFinal(data);

    System.out.println(new String(cipherData));
}

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

Мы очень ценим вашу помощь.

Спасибо. -Матт


person Matt Shaver    schedule 19.08.2009    source источник
comment
Где заполнение указано в коде C #? Откуда вы знаете, что OAEP (это PKCS # 1 вер. 2) не используется во время шифрования?   -  person erickson    schedule 20.08.2009
comment
Первым делом выделите шифрование и кодирование в отдельные задачи. Т.е. убедитесь, что декодированный байт Java [] идентичен исходному байту C # []. тогда вы можете спросить, это проблема с RSA или с Base64. Как сказал Эриксон, вероятно, разница в PKCS по умолчанию между библиотеками C # и Java.   -  person Remus Rusanu    schedule 20.08.2009
comment
@erickson - второй параметр метода .NET Encrypt () выбирает заполнение - true указывает OAEP, а false (используется в примере) указывает PKCS # 1 ver 1.5.   -  person Michael Burr    schedule 20.08.2009
comment
Где вы устанавливаете ключ для шифрования?   -  person Accipitridae    schedule 20.08.2009
comment
@Remus - Кодировка Base64 каждый раз дает разные результаты, но RSA все еще может ее расшифровать. @Accipitridae - хранилище ключей задается в параметрах CspParameters в .NET и десять импортировано в Java. Шифрование и дешифрование работают, когда значение зашифровано и дешифровано в .NET или когда оно зашифровано и дешифровано в Java. Однако не тогда, когда значение передается между ними.   -  person Matt Shaver    schedule 21.08.2009
comment
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что пользователь использовал неправильный закрытый ключ для расшифровки, как указывает принятый ответ. Это не проблема программирования, а просто плохое управление ключами.   -  person Maarten Bodewes    schedule 14.01.2020


Ответы (4)


Убедитесь, что вы правильно обменяли ключ.

Попытка расшифровать неверным ключом неотличима от расшифровки плохо заполненных данных.

person Rasmus Faber    schedule 20.08.2009

У меня была точно такая же проблема, и я наконец нашел решение!

Я упорно использовал PKCS1Padding, но мне не удалось заставить его работать.

Лучший результат, который я получил, используя «rsa.Encrypt (baIn, false)» на стороне C # и «RSA / NONE / NoPadding» на стороне Java, был таким строка: "☻? o + _> ?? 5? l0Q * ??? *? R ▲ ??? ♀7 ...", за которой следует моя расшифрованная строка. Таким образом, он был расшифрован, но, поскольку не указано заполнение, данные сдвигаются. Поэтому я попробовал все дополнения, доступные в bouncycastle, но всегда получал такие ошибки, как «неправильный размер блока» или «неправильный хеш данных».

Поэтому я решил начать пробовать дополнения OAEP, и мне, наконец, удалось заставить его работать, используя «rsa.Encrypt (baIn, true)» на стороне C # и «RSA / NONE / OAEPWithSHA1AndMGF1Padding» на стороне Java!

У меня это сработало, надеюсь, сработает и у вас! Если это не сработает, убедитесь, что вы используете правильный ключ, очень часто проблема связана с ключом.

person Migs    schedule 31.05.2010
comment
Это положило конец двухдневной боли !. Большое спасибо. - person Gboyega Sulaiman; 02.10.2017

Я работаю над аналогичной проблемой, возникающей между .Net и iPhone в Objective-C, и я думаю, что ответ кроется в этой маленькой жемчужине из документации RSACryptoServiceProvider:

В отличие от реализации RSA в неуправляемом CAPI, класс RSACryptoServiceProvider меняет порядок зашифрованного массива байтов после шифрования и до дешифрования. По умолчанию данные, зашифрованные классом RSACryptoServiceProvider, не могут быть дешифрованы функцией CAPI CryptDecrypt, а данные, зашифрованные методом CAPI CryptEncrypt, не могут быть расшифрованы классом RSACryptoServiceProvider.

Подробнее см. Здесь: http://msdn.microsoft.com/en-us/library/s575f7e2(v=VS.90).aspx.

person DJBHiney    schedule 12.04.2010

У меня была такая же проблема при использовании Bouncy Castle 1.48, но это не было связано с ключом. Вместо этого я обнаружил, что мне нужно установить следующее системное свойство:

-Dorg.bouncycastle.pkcs1.strict=false
person Nathan    schedule 31.07.2013
comment
Я не думаю, что .NET когда-либо использовал кодировку BER хеш-значения внутри подписи, поэтому для этого вопроса ответ не по теме, но он может быть полезен для других, 1. которые имеют проблемы с подписями с использованием правильного ключа и алгоритма и 2. - конечно же - с использованием провайдера Bouncy Castle. - person Maarten Bodewes; 14.01.2020