views:

353

answers:

1

I need to send an encrypted string from a private key to a webserver for authentication. I have Java client code that generates the encrypted string correctly (such that the webserver can decrypt it with the public key). I am trying to write C# code to perform the exact same encryption - but have not succeeded.

First a keystore was generated in java using keytool similar to this:

keytool -genkey -dname "cn=Application Test, ou=XXX, o=YYY, c=US" -alias AppTest -keypass AppTest -keystore AppTest.jks -storepass AppTest -validity 1800 -keyalg RSA

Then this java code correctly reads the keystore and encrypts the data (privateKey.getAlgorithm() returns "RSA"):

KeyStore ks = KeyStore.getInstance("JKS");
InputStream is = new FileInputStream("AppTest.jks");
ks.load(is, "AppTest".toCharArray());
is.close();
PrivateKey privateKey = (PrivateKey) ks.getKey(user, password.toCharArray());

// Encrypt with the private key
String stamp = "123456";
byte[] bytesStampUtf8Unencrypted = stamp.getBytes(Charset.forName("UTF-8"));
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] bytesTimestampUtf8Encrypted = cipher.doFinal(bytesStampUtf8Unencrypted);
String encrypted = new String((new Base64()).encode(bytesStampUtf8Unencrypted));

This all works great when passed to the web service. I then used keytool to convert from the java keystore to an PKCS12 certificate for use in my .NET application:

keytool -importkeystore -srckeystore AppTest.keystore -destkeystore KEYSTORE.p12  -srcstoretype JKS -deststoretype PKCS12 -srcstorepass AppTest -deststorepass AppTest-srcalias AppTest -destalias AppTest -srckeypass AppTest -destkeypass AppTest -noprompt

Using keytool I compared the finger prints of the keystore and P12 files - identical. I thought the following C# code should work:

X509Certificate2 myCertificate =
   new X509Certificate2(@"C:\Temp\KEYSTORE.p12", "AppTest");
RSACryptoServiceProvider privateKey =
   myCertificate.PrivateKey as RSACryptoServiceProvider;
String stamp = "123456";
byte[] buffer = Encoding.UTF8.GetBytes(stamp);
byte[] encryptedBytes = privateKey.Encrypt(buffer, false);
String encrypted = Convert.ToBase64String(encryptedBytes);

It reads the converted keystore file correctly, executes without problem, and generates what appears to be encrypted data, but the web service does NOT like the encrypted string (can't decrypt with the public key). When I replaced the C# encrypted string with the Java encrypted one (in the debugger) and sent that string through the C# program to the web service - it all worked as well - so I am confident the problem is in the encryption process, and not in the web service communication.

I have no control over the way the original key was generated (as a java keystore), nor what encryption method is expected by the web service. I can only control the .NET client that interacts with the Java based web service.

Am I missing some flag, setting, variable, what?

+1  A: 

Are you certain that the encryption algorithm, the block cipher mode and padding mode are equivalent in your C# implementation when compared to your java implementation?

Edit: Actually for RSACryptoProvider you probably don't need cipher/padding mode - take a look at the example on MSDN, specifically the section on importing public key information via ImportParameters

RandomNoob