Decrypt RSA encrypted value generated from .net in Android - c#
I have gone through many posts here but did not find the right solution. I want to decrypt a value encrypted in c# .net from Android.
I have successfully decrypted in .net platform using the following code snippet
public static void Main()
{
string _privateKey = Base64Decode("myprivatekey");
var rsa = new RSACryptoServiceProvider();
string data = "198,47,144,175,154,47,194,175,242,41,212,150,220,177,198,161,236,36,197,62,18,111,21,244,232,245,90,234,195,169,141,195,139,199,131,163,26,124,246,50,102,229,73,148,18,110,170,145,112,237,23,123,226,135,158,206,71,116,9,219,56,96,140,19,180,192,80,29,63,160,43,127,204,135,155,67,46,160,225,12,85,161,107,214,104,218,6,220,252,73,252,92,152,235,214,126,245,126,129,150,49,68,162,120,237,246,27,25,45,225,106,201,251,128,243,213,250,172,26,28,176,219,198,194,7,202,34,210";
var dataArray = data.Split(new char[] { ',' });
byte[] dataByte = new byte[dataArray.Length];
for (int i = 0; i < dataArray.Length; i++)
{
dataByte[i] = Convert.ToByte(dataArray[i]);
}
rsa.FromXmlString(_privateKey);
var decryptedByte = rsa.Decrypt(dataByte, false);
Console.WriteLine(_encoder.GetString(decryptedByte));
}
Now I want to do the same process in Android app. Please can somebody guide me through this?
I have tried the following code but its throwing javax.crypto.IllegalBlockSizeException: input must be under 128 bytes exception
String modulusString = "hm2oRCtP6usJKYpq7o1K20uUuL11j5xRrbV4FCQhn/JeXLT21laKK9901P69YUS3bLo64x8G1PkCfRtjbbZCIaa1Ci/BCQX8nF2kZVfrPyzcmeAkq4wsDthuZ+jPInknzUI3TQPAzdj6gim97E731i6WP0MHFqW6ODeQ6Dsp8pc=";
String publicExponentString = "AQAB";
byte[] modulusBytes = Base64.decode(modulusString, DEFAULT);
byte[] exponentBytes = Base64.decode(publicExponentString, DEFAULT);
BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger publicExponent = new BigInteger(1, exponentBytes);
RSAPrivateKeySpec rsaPubKey = new RSAPrivateKeySpec(modulus, publicExponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey pubKey = fact.generatePrivate(rsaPubKey);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] plainBytes = result.getBytes("UTF-16LE");
byte[] cipherData = cipher.doFinal(plainBytes);
String encryptedStringBase64 = Base64.decode(cipherData, DEFAULT).toString();
Related
ECDH nodejs and C# key exchange
I've lost my self and I need help to go in the right direction :) I have nodejs server that have to exchange some critical data with the server that is written in C#, so in that case, I want my data to be encrypted somehow. I was thinking about AES, and to safely exchange keys i want to use ECDH but I don't know how to make it work correctly... If I'm thinking right way I can make my C# "allice" side like this : ECDiffieHellman alice = ECDiffieHellman.Create(ECCurve.NamedCurves.brainpoolP192t1); var aliceKey = alice.PublicKey; var ketyToExport = Convert.ToBase64String(aliceKey.ToByteArray()); //send ketyToExport to nodejs //KEY FROM nodejs var key1 = Convert.FromBase64String("BIzSJ1dmTXpSS8rqkVFISZ+vumhqXYMWfWoU5vB9GHhOtxxDInu/GZ92VJpqhrE3vw==").ToList(); var keyType = new byte[] { 0x45, 0x43, 0x4B, 0x31 }; var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 }; key1.RemoveAt(0); key1 = keyType.Concat(keyLength).Concat(key1).ToList(); byte[] bobKeyBytes = key1.ToArray(); //and I have a problem with that line bellow, I do not know how to make it work var aliceSecret = alice.DeriveKeyMaterial(/*ECDiffieHellmanPublicKey bobKeyBytes*/); And nodejs "Bob" side like this: const crypto = require("crypto"); const bob = crypto.createECDH('brainpoolP192t1') const bobKey = bob.generateKeys('base64'); var bobLength = Buffer.from(bobKey, 'base64').length; //send bobkey to c# //recive alicekey var tmp = "RUNLUBgAAAAR9C7kO2o+vxNT/UBvvEuJHNdI8NfU4fUxUT431ER1q3kJbeUVHepoG5SWUM2NHj8=" var aliceKeyBuffer = Buffer.from(tmp, 'base64'); var aliceKey = Buffer.alloc(bobLength) aliceKeyBuffer.copy(aliceKey, 1, 8); aliceKey[0] = 4; bob.computeSecret(aliceKey); //create aes //get mesage and iv ... Okay so I've made some adjustments to all of that but right now I don't know what to do about this line how to make it work... var aliceSecret = alice.DeriveKeyMaterial(/*ECDiffieHellmanPublicKey bobKeyBytes*/); #BIG EDIT I got help in ECDiffieHellmanPublicKey from ByteArray (using ECDiffieHellman NamedCurves) and now I have another problem -_- my node js code didn't change from above but c# looks like: using (ECDiffieHellman alice = ECDiffieHellman.Create(ECCurve.NamedCurves.brainpoolP256r1)) { var alicePublicKey = Convert.ToBase64String(alice.PublicKey.ToByteArray()); //NODEJS brainpoolP256r1 publickey var key1 = Convert.FromBase64String("BASsbkule53ARqlMBA8hYysyyoRi3xGxGnSzIJ2fS5FlLniQD/zYiiGUVydmO/BBkQwVTUo5f4OMCxVNtQ/LuMQ="); byte[] keyX = new byte[key1.Length / 2]; byte[] keyY = new byte[keyX.Length]; Buffer.BlockCopy(key1, 1, keyX, 0, keyX.Length); Buffer.BlockCopy(key1, 1 + keyX.Length, keyY, 0, keyY.Length); ECParameters parameters = new ECParameters { Curve = ECCurve.NamedCurves.brainpoolP256r1, Q = { X = keyX, Y = keyY, }, }; byte[] derivedKey; using (ECDiffieHellman bob = ECDiffieHellman.Create(parameters)) using (ECDiffieHellmanPublicKey bobPublic = bob.PublicKey) { derivedKey = alice.DeriveKeyFromHash(bobPublic, HashAlgorithmName.SHA256); } var aliceKey = Convert.ToBase64String(derivedKey); byte[] encryptedMessage = null; byte[] iv = null; // Send(aliceKey, "Secret message", out encryptedMessage, out iv); } and it is working but it gives me different secret keys ... out of bob.computeSecret(aliceKey) i got iIoH9aJoWf3666QQ6X+kj4iUKrk9j+hbRuXbhgs7YzM= and out of alice.DeriveKeyFromHash(bobPublic, HashAlgorithmName.SHA256); I got wJ7O4Hm2Jxs1FcLx6KaMmENvqdTQJPZ/YNSs1+MQDOQ= if I'm thinking correctly they should be equal. am I thinking wrong? #EDIT DONE !! So this adding this code on end of js file gave me what I needed. const hash = crypto.createHash('sha256'); var tt = bob.computeSecret(aliceKey); hash.update(tt); console.log(hash.digest('base64'));
##SOLUTION## C# class Program { static void Main(string[] args) { using (ECDiffieHellman alice = ECDiffieHellman.Create(ECCurve.NamedCurves.brainpoolP256r1)) { var alicePublicKey = Convert.ToBase64String(alice.PublicKey.ToByteArray()); //send alicePublicKey var nodejsKey = ""; //NODEJS brainpoolP256r1 publickey base64 byte[] nodejsKeyBytes= Convert.FromBase64String(nodejsKey); var aliceKey = Convert.ToBase64String(getDeriveKey(nodejsKeyBytes,alice)); byte[] encryptedMessage = null; byte[] iv = null; // Send(aliceKey, "Secret message", out encryptedMessage, out iv); } } static byte[] getDeriveKey(byte[] key1, ECDiffieHellman alice) { byte[] keyX = new byte[key1.Length / 2]; byte[] keyY = new byte[keyX.Length]; Buffer.BlockCopy(key1, 1, keyX, 0, keyX.Length); Buffer.BlockCopy(key1, 1 + keyX.Length, keyY, 0, keyY.Length); ECParameters parameters = new ECParameters { Curve = ECCurve.NamedCurves.brainpoolP256r1, Q = { X = keyX, Y = keyY, }, }; byte[] derivedKey; using (ECDiffieHellman bob = ECDiffieHellman.Create(parameters)) using (ECDiffieHellmanPublicKey bobPublic = bob.PublicKey) { return derivedKey = alice.DeriveKeyFromHash(bobPublic, HashAlgorithmName.SHA256); } } } NODEJS const crypto = require("crypto"); const bob = crypto.createECDH('brainpoolP256r1') bob.generateKeys(); const bobKey = bob.getPublicKey('base64'); var bobLength = Buffer.from(bobKey, 'base64').length; //send bobkey to c# //recive alicekey var alicePublicKey = "RUNLUCAAAAB/xP7JhSIhYIYAijyC2zHu7obB5CwfK/ynQPxcRAIhBI6OLRRcHyPo61AhfSZN3qA2vGDfWO2mrdWWvqqhVaDf"; var aliceKeyBuffer = Buffer.from(alicePublicKey, 'base64'); var aliceKey = Buffer.alloc(bobLength) aliceKeyBuffer.copy(aliceKey, 1, 8); aliceKey[0] = 4; const hash = crypto.createHash('sha256'); var tt = bob.computeSecret(aliceKey); var bobSecretKey = hash.update(tt).digest('base64'); big thanks for #bartonjs and #Maarten Bodewes
The above answer helped me a lot. I am using secp521r1/nistP521 to do the key generation in both NodeJS and C#. In my case, a call to alice.PublicKey.ToByteArray() would result in an exception: Unhandled exception. System.PlatformNotSupportedException: Operation is not supported on this platform. at System.Security.Cryptography.ECDiffieHellmanImplementation.ECDiffieHellmanSecurityTransforms.ECDiffieHellmanSecurityTransformsPublicKey.ToByteArray() According to an issue logged with the dotnet runtime team here: ECDiffieHellmanPublicKey.ToByteArray() doesn't have a (standards-)defined export format. The version used by ECDiffieHellmanPublicKeyCng is Windows-specific, and only works for NIST P-256 (secp256r1), NIST P-384 (secp384r1), and NIST P-521 (secp521r1). To create a copy of a key you should use the ExportParameters() method to obtain the rich ECParameters object; which can then be sent through ECDiffieHellman.Create(ECParameters) and the PublicKey property of that object be read to get back a second instance of ECDiffieHellmanPublicKey. Assuming I send my X and Y from Alice to Bob (I used hex instead of base64), the corresponding process to arrive at the same shared secret on the NodeJS side looks like this: // Alice's public key X, Y coordinates from DotNet Core const aliceHexX = '00248F624728B17196B22005742C13D80D3DFF75BCA74AF865195E5A29F41C013653B0931BC544245402EDD7922F38692F38DCCF780CF1A9E27D3CFB5E09E53883C0'; const aliceHexY = '0043517F3B2EF33ED70EFA2BC4163E9B99558A7C2ECB7C659A12EA4024633CFA8B9FC997F0A42D30759B4280FDADC13A67A3E7BB0227047C907FAAE92E7716E8A10D'; const alicePublicKeyXBytes = Buffer.from(aliceHexX, 'hex'); const alicePublicKeyYBytes = Buffer.from(aliceHexY, 'hex'); const alicePublicKey = Buffer.concat([Buffer.from([0x04]), alicePublicKeyXBytes, alicePublicKeyYBytes]) const bobSecret = bob.computeSecret(alicePublicKey); const hash = crypto.createHash('sha256'); hash.update(bobSecret); const sharedSecret = hash.digest('hex'); console.log(`Shared Secret: ${sharedSecret.toString('hex')}`);
Encrypt Image in c# and decrypt in typescript
Am new to angular 2. I would like to encrypt my image with secret key in c# and decrypt it in typescript. Is that possible. If yes can anyone help me out. Thanks in advance. Code to encrypt public string EncryptImage(byte[] imageBytes) { var csp = new RSACryptoServiceProvider(2048); var privKey = csp.ExportParameters(true); var pubKey = csp.ExportParameters(false); string pubKeyString; { var sw = new System.IO.StringWriter(); var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters)); xs.Serialize(sw, pubKey); pubKeyString = sw.ToString(); } { var sr = new System.IO.StringReader(pubKeyString); var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters)); pubKey = (RSAParameters)xs.Deserialize(sr); } csp = new RSACryptoServiceProvider(); csp.ImportParameters(pubKey); var bytesCypherText = csp.Encrypt(imageBytes, false); var cypherText = Convert.ToBase64String(bytesCypherText); return cypherText; } Getting error at var bytesCypherText = csp.Encrypt(imageBytes, false); as bad length
Encrypting in C# public string EncryptData(string imageBytesBase64, string Encryptionkey) { RijndaelManaged objrij = new RijndaelManaged(); objrij.Mode = CipherMode.CBC; objrij.Padding = PaddingMode.PKCS7; byte[] keyBytes = Encoding.UTF8.GetBytes(Encryptionkey); byte[] ivBytes = Encoding.UTF8.GetBytes(Encryptionkey.Substring(0, 16)); int len = keyBytes.Length; if (len > ivBytes.Length) len = ivBytes.Length; Array.Copy(keyBytes, ivBytes, len); objrij.Key = keyBytes; objrij.IV = ivBytes; ICryptoTransform objtransform = objrij.CreateEncryptor(); byte[] textDataByte = Encoding.UTF8.GetBytes(imageBytesBase64); return Convert.ToBase64String(objtransform.TransformFinalBlock(textDataByte, 0, textDataByte.Length)); } Descrypt in TypeScript var decryptedTxt = CryptoJS.AES.decrypt(encryptedText, key, { keySize: 128 / 8, iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); this.decryptedText = decryptedTxt.toString(CryptoJS.enc.Utf8) this.ImageSrc = 'data:image/jpg;base64,' + this.decryptedText; Here Encryptionkey in c# and key in typescript are same
Hello you can use any Crypto engine in both side. For exemple you can use: RSA (Public / Private Key) For TypeScript side : RSA library with angular For C# Side : C# RSA encryption/decryption with transmission AES (Password) : For typescript side : use https://github.com/ricmoo/aes-js and just do : import 'aes-js'; declare var aesjs: any; For C# side : More information here Using AES encryption in C# Because all crypto algo have many configuration parameter, be careful to have matching configuration in C# and Typescript side.
Java equivalent of .NET RSACryptoServiceProvider with SHA-1
I have the following data signing code in C# RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); string PrivateKeyText = "<RSAKeyValue><Modulus>....</D></RSAKeyValue>"; rsa.FromXmlString(PrivateKeyText); string data = "my data"; byte[] SignedByteData = rsa.SignData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider()); and I want reproduce the same code in Java (Android): String modulusElem = "..."; String expElem = "..."; byte[] expBytes = Base64.decode(expElem, Base64.DEFAULT); byte[] modulusBytes = Base64.decode(modulusElem, Base64.DEFAULT); BigInteger modulus = new BigInteger(1, modulusBytes); BigInteger exponent = new BigInteger(1, expBytes); try { KeyFactory factory = KeyFactory.getInstance("RSA"); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); String data = "my data"; MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] hashedData = md.digest(data.getBytes("UTF-8")); RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modulus, exponent); PublicKey publicKey = factory.generatePublic(pubSpec); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] SignedByteData = cipher.doFinal(hashedData); } catch (Exception e){ } But I get mismatched output byte arrays. Where am I wrong and What should be the transformation used in Cipher.getInstance(...) ?
Use Signature.getInstance("SHA1withRSA"). Encryption is not the same as signature generation. Different padding mechanisms for one. Update by Afshin Complete solution. Note the use of the private exponent, ie <D>, rather the public <Exponent> String modulusElem = "..."; String dElem = "..."; byte[] modulusBytes = Base64.decode(modulusElem, Base64.DEFAULT); byte[] dBytes = Base64.decode(dElem, Base64.DEFAULT); BigInteger modulus = new BigInteger(1, modulusBytes); BigInteger d = new BigInteger(1, dBytes); String data = "my data"; try { Signature signature = Signature.getInstance("SHA1withRSA"); KeyFactory factory = KeyFactory.getInstance("RSA"); RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, d); PrivateKey privateKey = factory.generatePrivate(privateKeySpec); signature.initSign(privateKey); signature.update(data.getBytes("UTF-8")); byte[] SignedByteData = signature.sign(); } catch(Exception e) { e.printStackTrace(); }
WinRT RSA encryption from public key exponent/modulus
I'm trying to port this method from .NET 4.5 desktop app to a WinRT app: static byte[] DotNetRsaEncrypt(string modulus, string exponent, byte[] data) { var modulusBytes = Convert.FromBase64String(modulus); var exponentBytes = Convert.FromBase64String(exponent); var rsaParameters = new RSAParameters { Modulus = modulusBytes, Exponent = exponentBytes }; var rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaParameters); var encrypted = rsa.Encrypt(data, true); return encrypted; } After reading this RSA Encryption in metro style Application I tried the following: static byte[] WinRtRsaEncrypt(string modulus, string exponent, byte[] data) { var modulusBytes = Convert.FromBase64String(modulus); var exponentBytes = Convert.FromBase64String(exponent); var keyBlob = modulusBytes.Concat(exponentBytes).ToArray().AsBuffer(); var rsa = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaOaepSha1); var key = rsa.ImportPublicKey(keyBlob, CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey); var encrypted = CryptographicEngine.Encrypt(key, data.AsBuffer(), null); return encrypted; } But it does not work. In order to get the same functionality as my desktop app... What AsymmetricAlgorithmNames should I pass to OpenAlgorithm()? What CryptographicPublicKeyBlobType should I pass to ImportPublicKey()?
Following up on user1968335's hint, this worked for me. First, in a C# application, use the following code to obtain a CspBlob from your modulus/exponent: var exponent = Encoding.Default.GetBytes(exponentStr); var modulus = Encoding.Default.GetBytes(modulusStr); var rsaParameters = new RSAParameters { Modulus = modulus, Exponent = exponent }; var rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaParameters); var cspBlobString = Convert.ToBase64String(rsa.ExportCspBlob(false)); Then, in a WinRT application you can use that CspBlob to sign a piece of data like this: private static string SignString(string data) { string cspBlobString = //cspBlob var keyBlob = CryptographicBuffer.DecodeFromBase64String(cspBlobString); AsymmetricKeyAlgorithmProvider rsa = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); CryptographicKey key = rsa.ImportPublicKey(keyBlob, CryptographicPublicKeyBlobType.Capi1PublicKey); IBuffer plainBuffer = CryptographicBuffer.ConvertStringToBinary(data, BinaryStringEncoding.Utf8); IBuffer encryptedBuffer = CryptographicEngine.Encrypt(key, plainBuffer, null); byte[] encryptedBytes; CryptographicBuffer.CopyToByteArray(encryptedBuffer, out encryptedBytes); return Convert.ToBase64String(encryptedBytes); } If it matters, this is how I generated my asymmetric keys: http://43n141e.blogspot.co.uk/2008/08/rsa-encryption-openssl-to-ruby-to-c-and_27.html
According to CryptoWinRT sample, OpenAlgorithm(...) method takes these values. RSA_PKCS1 RSA_OAEP_SHA1 RSA_OAEP_SHA256 RSA_OAEP_SHA384 See also : RSA cryptography between a WinRT and a .Net app
C# RSA public Modulus/Exponent? (Bad Data)
I have tried and tried but I continue to get "Bad Data". How do you decrypt data using the RSACryptoServiceProvider with the public key's Exponent/Modulus? public static byte[] Encrypt(byte[] b, byte[] mod, byte[] exp) { CspParameters csp = new CspParameters(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); RSACryptoServiceProvider.UseMachineKeyStore = false; RSAParameters par = new RSAParameters(); par.Exponent = exp; par.Modulus = mod; rsa.ImportParameters(par); return rsa.Encrypt(b, false); } public static byte[] Decrypt(byte[] b, byte[] pubexp, byte[] mod, byte[] priexp) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); RSACryptoServiceProvider.UseMachineKeyStore = false; RSAParameters rp = new RSAParameters(); rp.Exponent = pubexp; rp.D = priexp; rp.Modulus = mod; rsa.ImportParameters(rp); return rsa.Decrypt(b, false); } static List<byte[]> Base2Array(string str) { byte[] b = Convert.FromBase64String(str); List<byte[]> Bytes = new List<byte[]>(); int i = 0; while (i < b.Length) { int size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(b, i)); i += 4; byte[] b2 = new byte[size]; Array.Copy(b, i, b2, 0, size); Bytes.Add(b2); i += size; } return Bytes; } static void Main(string[] args) { List<byte[]> pub = Base2Array("AAAAB3NzaC1yc2EAAAABJQAAAIBMW4HxU1glv+CcZpJnvUKEyeNfFoKkyLOVLOOb/vNXQkrkGsNdpYAZkKKizij8fD3u3/iYT8UI+xkFoyonRYVipgCslirJB1VdvLivXs69Ht4vf7VAv2yJSUni3XsIHauMlfOkjJ7DpUW75ZkrxsGieICFWlXvRnAyDdqQrkZRZQ=="); List<byte[]> pri = Base2Array("AAAAgBSjHDNiojO3UXZg6Ux4VyrOx9SCn9mCWgykWTEUeR6Anp6DxhlPUw3UEEetVy97hlw8iGCEQxcvG4T7qocni9UtUTLdpuQzvr6718y2CP0ouKt/1hVKD9QssT08XUvJEBQnnl2yVZAbIqT/DGnUH36L0BnQE/2ombPakwHscfFFAAAAQQCSfQy2cP8Oa0IR0u0whxqGmuuXY/3tCD8NaaSCYm31ly0QBdxFdf2WkC51DNVaf5/1ErHceMapFN9Z3j+/6lA7AAAAQQCFcMoSA32f240nFBmMv/nn/mL1uSdAXOxjUHViJc6M8ntZvW2ZuP2qTvfA3mh1AK5K69piX/4T72xxqTA2tmrfAAAAQFxX1JunFI+fpobdienVCZcjibwbpDPf1MVTbwQhAXHqVBL3XXgkysS/67X/aWnv/+SdBDaXa1SnDpphSWOkxAQ="); //pub[0] 7 //pub[1] 1 //pub[2] 128 //pri[0] 128 //pri[1] 65 //pri[2] 65 //pri[3] 64 byte[] pubmod = null; byte[] primod = null; byte[] pubexp = null; byte[] priexp = null; pubexp = pub[0]; pubmod = pub[2]; priexp = pri[0]; primod = pri[2]; byte[] bstr = Encoding.ASCII.GetBytes("Test"); bstr = Encrypt(bstr, pubmod, pubexp); bstr = Decrypt(bstr, pubexp, pubmod, null); string str = Encoding.ASCII.GetString(bstr); }
i do something like that: public byte[] PublicDecryption(byte[] encryptedData) { var encData = new BigInteger(encryptedData); BigInteger bnData = encData.modPow(_exponent, _modulus); return bnData.getBytes(); } public byte[] PrivateDecryption(byte[] encryptedData) { var encData = new BigInteger(encryptedData); d = new BigInteger(rsaParams.D); BigInteger bnData = encData.modPow(d, _modulus); return bnData.getBytes(); } where BigInteger is this: http://www.codeproject.com/KB/cs/biginteger.aspx because microsoft implementation is partial and buggy. I've never had a problem with this. Hope this help
Few month ago I have tried to implement scenario with private key encryption and public key decryption. I spent a week trying doing this with RSACryptoServiceProvider and.. nothing. They support only two use cases: Public key encryption , private (full) key decryption. Signing with private key, verifying with public. And they have done everything to not allow you do something else with their API. Please, check out msdn forums: I have found many answers like that one msdn, including answers from support development team. All they said: that this is prohibit by design. So my suggestion is don't even try to do that with RSACryptoServiceProvider, better use another implementation.