RSA C # Зашифровать Java Расшифровать - PullRequest
1 голос
/ 28 мая 2010

В моей программе (на стороне сервера - Java) я создал файл хранилища ключей с командой:

keytool -genkey -alias myalias -keyalg RSA -validity 10000 -keystore my.keystore

и экспортировал связанный сертификат X509 с:

keytool -export -alias myalias -file cert.cer -keystore my.keystore

После того, как я сохранилcert.cer на стороне клиента (C #), и я пишу этот код:

X509Certificate2 x509 = new X509Certificate2();
byte[] rawData = ReadFile("mycert.cer");
x509.Import(rawData);

RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)x509.PublicKey.Key;
byte[] plainbytes = System.Text.Encoding.ASCII.GetBytes("My Secret");
byte[] cipherbytes = rsa.Encrypt(plainbytes, true);
String cipherHex = convertToHex(cipherContent);
byte[] byteArray = encoding.GetBytes(cipherHex);

....

Я пишу этот код Java на стороне сервера:

keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream("C:\\my.keystore"), "mypass".toCharArray());
Key key = keyStore.getKey("myalias", "mypass".toCharArray());
if (key instanceof PrivateKey) {
    Certificate cert = keyStore.getCertificate("myalias");
    PublicKey pubKey = cert.getPublicKey();
    privKey = (PrivateKey)key;
}
byte[] toDecodeBytes = new BigInteger(encodeMessageHex, 16).toByteArray();
Cipher decCipher = Cipher.getInstance("RSA");
decCipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decodeMessageBytes = decCipher.doFinal(toDecodeBytes);
String decodeMessageString = new String(decodeMessageBytes);

Я получаю эту ошибку:

javax.crypto.BadPaddingException: Data must start with zero

Можете ли вы помочь мне, пожалуйста?Спасибо, спасибо,

Ответы [ 3 ]

1 голос
/ 29 мая 2010

Ваш метод шестнадцатеричного декодирования в Java с использованием BigInteger большую часть времени будет давать неправильный результат, поскольку класс Java BigInteger кодирует значение, старший байт которого>> 128 с дополнительным нулевым байтом впереди. Используйте кодек Apache Commons для шестнадцатеричного / де-кодирования.

РЕДАКТИРОВАТЬ: Ваш код C # неверен. Существует класс .NET System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary, который выполняет шестнадцатеричное en / de-кодирование для вашего кода C #. Следующий фрагмент кода C # должен работать лучше

public static String execute(String content)
{
    ASCIIEncoding encoding = new ASCIIEncoding();
    byte[] plainbytes = System.Text.Encoding.ASCII.GetBytes(content);
    byte[] cipherbytes = rsa.Encrypt(plainbytes, false);
    SoapHexBinary hexBinary = new SoapHexBinary(cipherbytes);
    String cipherHex = hexBinary.ToString();

    // This String is used on java side to decrypt
    Console.WriteLine("CIPHER HEX: " + cipherHex);
    return cipherHex;
}

РЕДАКТИРОВАТЬ 2:

Похоже, что класс SoapHexBinary, возможно, имел короткую жизнь в .NET. Есть несколько хороших решений проблемы на этой ссылке MSDN .

1 голос
/ 28 мая 2010

Хм, я не сделал точно, что вы здесь, у меня был DES, который я должен был сделать, и я получил ту же ошибку. Хитрость была в том, что мне нужно было получить совместимые CipherModes и PaddingModes с обеих сторон. Для меня это были PaddingMode.PKCS7 и CipherMode.CBC на стороне csharp, а на стороне java я использовал форму x DESEde / CBC / PKCS5Padding.

НТН Mike

0 голосов
/ 30 мая 2010

Благодаря ответам GregS я нашел решение своей проблемы. Теперь я отправляю это.

C # SIDE (на стороне клиента)

X509Certificate2 x509 = new X509Certificate2();
byte[] rawData = ReadFile("mycert.cer");
x509.Import(rawData);

После загрузки сертификата X509 я вызываю метод execute:

public static String execute(String content)
{
    ASCIIEncoding encoding = new ASCIIEncoding();
    byte[] plainbytes = System.Text.Encoding.ASCII.GetBytes(content);
    byte[] cipherbytes = rsa.Encrypt(plainbytes, false);
    SoapHexBinary hexBinary = new SoapHexBinary(cipherbytes);
    String cipherHex = hexBinary.ToString();

    // This String is used on java side to decrypt
    Console.WriteLine("CIPHER HEX: " + cipherHex);
    return cipherHex;
}

JAVA SIDE (на стороне сервера)

keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream("C:\\my.keystore"), "mypass".toCharArray());
Key key = keyStore.getKey("myalias", "mypass".toCharArray());
if (key instanceof PrivateKey) {
    Certificate cert = keyStore.getCertificate("myalias");
    PublicKey pubKey = cert.getPublicKey();
    privKey = (PrivateKey)key;
}
byte[] toDecodeBytes = new BigInteger(encodeMessageHex, 16).toByteArray();
Cipher decCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
decCipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decodeMessageBytes = decCipher.doFinal(toDecodeBytes);
String decodeMessageString = new String(decodeMessageBytes);

Проблема была в Hex-Encryption на стороне C #, которая полностью отличалась на стороне Java. Спасибо GregS, ты лучший;)

...