DATA ENCRYPTION 2048 RSA Algorithm using public key in mvc - asp.net

i want to encrypt a json data
{
"urc": "7718313198",
"umc": "101871",
"ak": "asdfgh123456",
"fname": "Biswajit",
"lname": "Dolui",
"email": "retailer001#giblvirtualmail.com",
"phno": "7718313198",
"pin": "712410"
}

i could not encrypt long string in asp.net using rsa algorithm 2048
var csp = new RSACryptoServiceProvider(2048);
//how to get the private key
var privKey = csp.ExportParameters(true);
//and the public key ...
var pubKey = csp.ExportParameters(false);
//converting the public key into a string representation
string pubKeyString;
{
//we need some buffer
var sw = new System.IO.StringWriter();
//we need a serializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//serialize the key into the stream
xs.Serialize(sw, pubKey);
//get the string from the stream
pubKeyString = sw.ToString();
}
//converting it back
{
//get a stream from the string
var sr = new System.IO.StringReader(pubKeyString);
//we need a deserializer
var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
//get the object back from the stream
pubKey = (RSAParameters)xs.Deserialize(sr);
}
//conversion for the private key is no black magic either ... omitted
//we have a public key ... let's get a new csp and load that key
csp = new RSACryptoServiceProvider();
csp.ImportParameters(pubKey);
//we need some data to encrypt
var plainTextData = "{urc: 7718313198,umc: 101871,ak: asdfgh123456,fname: Biswajit,lname: Dolui,email: biswajitdoluicse#gmail.com,phno: 7718313198}";
//for encryption, always handle bytes...
var bytesPlainTextData = System.Text.Encoding.Unicode.GetBytes(plainTextData);
//apply pkcs#1.5 padding and encrypt our data
var bytesCypherText = csp.Encrypt(bytesPlainTextData, false);
//we might want a string representation of our cypher text... base64 will do
var cypherText = Convert.ToBase64String(bytesCypherText);

Related

Decrypt RSA encrypted value generated from .net in Android [duplicate]

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();

How to achieve Xamarin.Android Asymmetric Encryption of RSA key?

Here's the code that i have implemented. Click here for errors. Do i have to import any nuget? Help
public string EncryptRSA(string plainText, string publicKeyString)
{
byte[] cipherText = null;
String strEncryInfoData = "";
try
{
KeyFactory keyFac = KeyFactory.getInstance("RSA");
KeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKeyString.trim().getBytes(), Base64.DEFAULT));
Key publicKey = keyFac.generatePublic(keySpec);
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance("RSA");
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
cipherText = cipher.doFinal(text.getBytes());
strEncryInfoData = new String(Base64.encode(cipherText, Base64.DEFAULT));
}
catch (Exception e)
{
}
return strEncryInfoData.replaceAll("(\\r|\\n)", "");
}
Your codes is in java , however, Xamarin using c#
Please use C# way to do RSA encryption.
If you dont mind, use mine
public class RSA {
public RSA() => Provider = new RSACryptoServiceProvider(2048);
public RSA(string key) {
Provider = new RSACryptoServiceProvider(2048);
Provider.FromXmlString(Encoding.UTF8.GetString(Convert.FromBase64String(key)));
}
public RSACryptoServiceProvider Provider;
public string PublicKey() => Convert.ToBase64String(Encoding.UTF8.GetBytes(Provider.ToXmlString(false)));
public string PrivateKey() => Convert.ToBase64String(Encoding.UTF8.GetBytes(Provider.ToXmlString(true)));
public string Encrypt(string meta) => Convert.ToBase64String(Provider.Encrypt(Encoding.UTF8.GetBytes(meta), RSAEncryptionPadding.Pkcs1));
public string Decrypt(string meta) => Encoding.UTF8.GetString(Provider.Decrypt(Convert.FromBase64String(meta), RSAEncryptionPadding.Pkcs1));
}
Usage:
var rsa = new RSA();
var generatePrivateKey = rsa.PrivateKey();
var generatePublicKey = rsa.PublicKey();
var encryted = new RSA(yourKey).Encrypt(yourText);
var decrypted = new RSA(yourKey).Decrypt(yourText);
Note, this class use 2048 bits and Pkcs1 padding as default, you can change it according to your flavor.

Java TripleDES PKCS5Padding decryption to C# - bad data / padding error

I'm trying to write the C# equivalent for the following Java code:
protected static final String DES_ECB_PKCS5PADDING = "DESede/ECB/PKCS5Padding";
public static String decryptValueDirect(String value, String key)
throws NoSuchAlgorithmException, NoSuchPaddingException,
GeneralSecurityException, IllegalBlockSizeException,
BadPaddingException {
byte[] bytes = Base64.decodeBase64(value);
Cipher cipher = Cipher.getInstance(DES_ECB_PKCS5PADDING);
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey(key.getBytes()));
byte[] decryptedValue = cipher.doFinal(bytes);
String nstr = new String(decryptedValue);
return nstr;
}
protected static SecretKey convertSecretKey(byte[] encryptionKey) throws GeneralSecurityException {
if (encryptionKey == null || encryptionKey.length == 0)
throw new IllegalArgumentException("Encryption key must be specified");
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(TRIPLEDES);
KeySpec keySpec = new DESedeKeySpec(encryptionKey);
return keyFactory.generateSecret(keySpec);
}
The source text is a base64 encoded, then encrypted and then base64 encoded for transport on a rabbit queue. Our vendor who handles the encryption provided the above for decryption in Java, but has no idea about C#.
The only input on the encryption side is a key, a random string. We use the same string for encryption/decryption 012345678901234567890123456789 in our dev env. That is the only input, no salt, hashing (that i see) or pw iterations. The only requirement is that it is at least 24 chars long.
My C# code is below and a fiddle of my attempt is here.
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main()
{
//Message Data value
//We are using encrypted multibyte.
string myData = #"ROE8oYeV7B6faUsvfIx0Xe55vSs9IR5DlWGRbSM+lmKmLcaJsA13VudwWlAEYtLUD8+nMXShky0grSxsk0Z9cQe5V45XnAIfUhnyzI9a0jtMFC8XnIZ5dbclPO/V73QnieIZDkbNV5cPo3BM+l79ai96KB/gkF3xuerFPxvWejtPyWbOyO+FfNyFps4gAYDITsYIAEH39VP4eipmQ5zc18BA39lajQ3UaVewSxz7H+x3Ooe2SzJT/TQWRkioJSEFwexqzkHiLOQ0MOCIVD9xTWpLYnsL3LMwyF6H8f0PY4Fc57LVGhvUZ7dsB9NWUAnmG3uqbsonNFVhuXyvJTWNyFOHwFzOMx6XDLJJFHGZhaHg2VrescfnpUtonQY08RgojBngyJNRqK8URAvI3bqKq8Y7F/9HmEtMIIQe6KuuTmU=";
string myKey = "012345678901234567890123456789";//Development Env Key.
Console.WriteLine("Decrypt1:");
string s = Decrypt1(myData, myKey);
Console.ReadLine();
}
public static string Decrypt1(string value, string decryptionKey)
{
string decryptString = "";
TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider hashMD5Provider = new MD5CryptoServiceProvider();
try
{
byte[] decodedData = Convert.FromBase64String(value);
tDESalg.Mode = CipherMode.ECB;
tDESalg.Padding = PaddingMode.PKCS7;//According to MS, same as PKCS5PADDING
byte[] Key = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(decryptionKey));
//byte[] IV = tDESalg.IV;
byte[] IV = new byte[tDESalg.BlockSize / 8]; //The size of the IV property must be the same as the BlockSize property divided by 8
var memoryStream = new MemoryStream(decodedData);
var cryptoStream = new CryptoStream(memoryStream, tDESalg.CreateDecryptor(Key, IV), CryptoStreamMode.Read);
var reader = new StreamReader(cryptoStream);
decryptString = reader.ReadToEnd();
byte[] decryptData = Convert.FromBase64String(decryptString);
}
catch (Exception e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message + e.StackTrace);
return null;
}
return decryptString;
}
}
Searching seems to point to the same answer, the key, encoding, ... all must be the same. I just don't know what that would be the equivalent for the Java source provided. :) Any suggestions will be helpful.
MD5 has a 16-byte output, Triple DES (3DES) requires a 24-byte key. There is a key size mis-match.
The C# and Java key derivations are substantially different:
C#:
byte[] Key = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(decryptionKey));
returns 16-bytes.
Java:
SecretKeyFactory.getInstance(TRIPLEDES)
returns 24-bytes.
There is a key option (2TDEA) where a 16-byte key is used and the first 8-bytes will be duplicated to create the last 8-bytes. NIST has deprecated this option.
Some implementations will accept a 16-byte key and extend the key to 24-bytes and some will not. You should provide all 24-bytes to 3DES, do not rely on an implementation to create the 24-byte key.
Note: The question was updated so it is not clear that the the actual encrytpion key is derived.

Node js: How to encrypt and decrypt using public-private key pair using crypto module?

I have to write a code in Node js using crypto module (as I am not allowed to use any module apart from MIT licensed). I need to generate a key pair and encrypt some message with the pulic key and decrypt it with private key. The first part i.e generation of key pair is done. I am not getting any clue how to use crypto modue to encrypt and decrypt some message using the same key pair.
This should do what you want:
const { generateKeyPairSync, publicEncrypt, privateDecrypt } = require('crypto');
//generate a key pair RSA type encryption with a .pem format
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
}
});
// print out the generated keys
console.log(`PublicKey: ${publicKey}`);
console.log(`PrivateKey: ${privateKey}`);
//message to be encrypted
var toEncrypt = "my secret text to be encrypted";
var encryptBuffer = Buffer.from(toEncrypt);
//encrypt using public key
var encrypted = publicEncrypt(publicKey,encryptBuffer);
//print out the text and cyphertext
console.log("Text to be encrypted:");
console.log(toEncrypt);
console.log("cipherText:");
console.log(encrypted.toString());
//decrypt the cyphertext using the private key
var decryptBuffer = Buffer.from(encrypted.toString("base64"), "base64");
var decrypted = privateDecrypt(privateKey,decryptBuffer);
//print out the decrypted text
console.log("decripted Text:");
console.log(decrypted.toString());
It generates a key pair that can be used to encrypt and decrypt a message.
In the Node Documentation for the Crypto lib is the following example:
var crypto = require('crypto');
var alice = crypto.getDiffieHellman('modp5');
var bob = crypto.getDiffieHellman('modp5');
alice.generateKeys();
bob.generateKeys();
var alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
var bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex');
/* alice_secret and bob_secret should be the same */
console.log(alice_secret == bob_secret);
This example shows how to compute a shared secret which can then be used with .createCipher() and .createDecipher() as shown below:
var encrypt64 = function(aMsg, aSecret) {
var cipher, tRet;
cipher = crypto.createCipher('aes-256-cbc', aSecret);
tRet = cipher.update(aMsg, 'utf8', 'base64');
tRet += cipher.final('base64');
return tRet;
};
var decrypt64 = function(aMsg, aSecret) {
var decipher, tRet;
decipher = crypto.createDecipher('aes-256-cbc', aSecret);
tRet = decipher.update(aMsg.replace(/\s/g, "+"), 'base64', 'utf8');
tRet += decipher.final('utf8');
return tRet;
};

Crypto-Js with c#

I am learning about encryption and using crypto-js I have made a Js & c# version.
What I am trying to accomplish is that the JS or c# version will be able to decode each other messages.
For testing I have kept the IV and KEY , paddding and mode the same in both the JS and C# instance.
I have them both decrypting and encrypting data respectivly but what I have yet to accomplish is providing an encrypted from JS be able to decode using c#.
JS
var key = CryptoJS.enc.Base64.parse('7061737323313233');
var iv = CryptoJS.enc.Base64.parse('7061737323313233');
var encrypted = CryptoJS.AES.encrypt("It works", key,
{ keySize: 128 / 8, iv: iv, mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7 });
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
keySize: 128 / 8, iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
document.write('Encrypted :' + encrypted + '<br>');
document.write('Key :' + encrypted.key + '<br>');
document.write('Salt :' + encrypted.salt + '<br>');
document.write('iv :' + encrypted.iv + '<br>');
document.write('Decrypted : ' + decrypted + '<br>');
document.write('utf8 = ' + decrypted.toString(CryptoJS.enc.Utf8) + '<br>');
C#
public void startEncryption(string original )
{
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
//Settings
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
myRijndael.FeedbackSize = 128;
keybytes = Encoding.UTF8.GetBytes("7061737323313233");
//Should be made unique for each message!. TODO
iv = Encoding.UTF8.GetBytes("7061737323313233");
// Encrypt the string to an array of bytes.
encrypted = EncryptStringToBytes(original, keybytes, iv);
//Show Encrypted data
txt_Output.Text = Convert.ToBase64String(encrypted);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes(encrypted, keybytes, iv);
//Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round Trip: {0}", roundtrip);
}
}
Where the problem arises in decryption.
private void btn_Decrypt_Click(object sender, EventArgs e)
{
Console.WriteLine("Decrypting..");
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
//Settings
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
myRijndael.FeedbackSize = 128;
keybytes = Encoding.UTF8.GetBytes("7061737323313233");
//Should be made unique for each message!. TODO
iv = Encoding.UTF8.GetBytes("7061737323313233");
// Decrypt the bytes to a string.
string roundtrip = DecryptToString(txt_Output.Text);
txt_Output.Text = roundtrip;
//Display the original data and the decrypted data.
}
}
public string DecryptToString(string TextValue)
{
return DecryptStringFromBytes(Convert.FromBase64String(TextValue), keybytes, iv);
}
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
rijAlg.Padding = PaddingMode.PKCS7;
rijAlg.Mode = CipherMode.CBC;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt =
new CryptoStream(msDecrypt,decryptor,CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
I am producing different encrypted size strings:
JS:MhAP11fHa+fUfRzSw2UHVQ==
C#:+Ijpt1GDVgM4MqMAQUwf0Q==
I get Padding is invalid and cannot be removed, when trying to decrypt the JS string in c#
Where have I got wrong?.
Basically you run into encoding issues. First of all, you parse your IV using Base64 decoding in one implementation and one using direct character encoding in the other. Your Base64 strings don't look like Base64 strings either.
Furthermore, many libraries (incorrectly) allow that incorrect key and IV sizes are used. This is however confusing as there is no generic way for key or IV expansion. So you should make sure that the binary representations of the key and IV are correct for the specific algorithm.
For AES you should use a key size of 128, 192 or 256 bits and an IV size identical to the block size, 128 bits. The IV should be randomly generated and communicated to the other side, e.g. by prefixing the IV to the ciphertext.

Resources