Write Serialized XML String to XML File - asp.net

I have a decrypted XML string which was sent over the wire to the receiving box where my code resides. Now, I want to write this XML string to an XML file.
Here's the Decrypt method which my code calls to generate this XML string... maybe this needs to be changed?
[Update]: My problem is that I can't see a way to write/create an XML file from a string of XML... I can see samples using a stream, a URL, but that doesn't help me here.
protected string DecryptForm(byte[] encryptedString, byte[] key, byte[] vector)
{
rijndael = new RijndaelManaged();
rijndael.Mode = CipherMode.CBC;
// Create a decryptor to perform the stream transform
ICryptoTransform decryptor = rijndael.CreateDecryptor(key, vector);
string plainText = null;
try
{
//Create the streams used for decryption
using (MemoryStream msStream = new MemoryStream(encryptedString))
{
using (CryptoStream csStream = new CryptoStream(msStream,
decryptor, CryptoStreamMode.Read))
{
using (StreamReader readerStream = new StreamReader(csStream))
{
// Read the decrypted bytes from the decrypting stream
plainText = readerStream.ReadToEnd();
}
}
}
finally
{
// Clear the RijndaelManaged object
if(rijndael != null)
rijndael.Clear();
}
// Return the decrypted string
return plainText;
}
}

xmlDoc = new XmlDocument();
xmlDoc.LoadXML(MyXMLString);
xmlDoc.Save(MyFilePath)

Related

Encryption module uses high memory while running for large data

We are trying to encrypt huge table data (3 million ), When we use the below encryption method it constantly makes a memory issue. When use 'using' keyword memory stream object should be disposed some period of time, What could be the other reason? When I disable the line***(var encryptor = cryptoProvider.CreateEncryptor(key, initializationVector)***; // Does it make any problem ), memory becomes stable .
.NET 5
internal class EncryptionServiceBase
{
protected byte[] Encrypt(byte[] decryptedData, byte[] key, byte[] initializationVector, Action<AesCryptoServiceProvider> setupDelegate)
{
Guard.IsNotNullOrEmpty(decryptedData, nameof(decryptedData));
Guard.IsNotNullOrEmpty(key, nameof(key));
Guard.IsNotNullOrEmpty(initializationVector, nameof(initializationVector));
**using (var cryptoProvider = new AesCryptoServiceProvider())
{
setupDelegate(cryptoProvider);
var encryptor = cryptoProvider.CreateEncryptor(key, initializationVector);** // Does it make any problem
return GetCryptoTransformedData(decryptedData, encryptor);
}
}
protected byte[] Decrypt(byte[] encryptedData, byte[] key, byte[] initializationVector, Action<AesCryptoServiceProvider> setupDelegate)
{
Guard.IsNotNullOrEmpty(encryptedData, nameof(encryptedData));
Guard.IsNotNullOrEmpty(key, nameof(key));
Guard.IsNotNullOrEmpty(initializationVector, nameof(initializationVector));
using (var cryptoProvider = new AesCryptoServiceProvider())
{
setupDelegate(cryptoProvider);
var decryptor = cryptoProvider.CreateDecryptor(key, initializationVector);
return GetCryptoTransformedData(encryptedData, decryptor);
}
}
private byte[] GetCryptoTransformedData(byte[] data, ICryptoTransform cryptoTransform)
{
using (var memoryStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
return memoryStream.ToArray();
}
}
}

AesManaged - Padding is Invalid and Cannot Be Removed - Reading from .Txt File

I am trying to save encrypted data to a Text file and then open and decrypt it. When I try to Decrypt it I receive the error "Padding is Invalid and Cannot Be Removed." I am using example code directly from Microsoft for encryption and decryption.
Here is MY code to encrypt and save file:
string json = JsonConvert.SerializeObject(credentials);
using (AesManaged myAes = new AesManaged())
{
byte[] encrypted = ControlHelperscs.EncryptStringToBytes_Aes(json, myAes.Key, myAes.IV);
File.WriteAllBytes(subPath, encrypted);
}
Here is my code to Retrieve and Decrypt file:
using (AesManaged myAes = new AesManaged())
{
byte[] file = File.ReadAllBytes(subPath);
string decrypt = ControlHelperscs.DecryptStringFromBytes_Aes(file, myAes.Key, myAes.IV);
credentials = JsonConvert.DeserializeObject<LoginModel>(decrypt);
}
Here are Encrypt and Decrypt methods:
public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
public static string DecryptStringFromBytes_Aes(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("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an AesManaged object
// with the specified key and IV.
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.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'm sorry I deleted my comment (it was wrong in that context), but I reworked your example to have a little less boilerplate and be able to encrypt and decrypt properly. The problem is that you're generating a new and different Key/IV pair to decrypt from the one you used to encrypt. Of course it won't be able to decrypt. So, here is the part to make it work:
byte[] key;
byte[] iv;
string json = JsonConvert.SerializeObject(credentials);
using (AesManaged myAes = new AesManaged())
{
key = myAes.Key;
iv = myAes.IV;
byte[] encrypted = ControlHelperscs.EncryptStringToBytes_Aes(json, key, iv);
File.WriteAllBytes(subPath, encrypted);
}
byte[] file = File.ReadAllBytes(subPath);
string decrypt = ControlHelperscs.DecryptStringFromBytes_Aes(file, key, iv);
credentials = JsonConvert.DeserializeObject<LoginModel>(decrypt);
and here are the slightly reworked heavy-lifting methods to be a bit more compact:
public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] iv)
{
// Check arguments.
if (plainText is null)
{
throw new ArgumentNullException(nameof(plainText));
}
if (plainText.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(plainText), plainText, "length cannot be zero");
}
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
if (key.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(key), key, "length cannot be zero");
}
if (iv is null)
{
throw new ArgumentNullException(nameof(iv));
}
if (iv.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(iv), iv, "length cannot be zero");
}
// Create an AesManaged object
// with the specified key and IV.
// Create an encryptor to perform the stream transform.
// Create the streams used for encryption.
using (SymmetricAlgorithm aesAlg = new AesManaged { Key = key, IV = iv })
using (ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV))
using (MemoryStream msEncrypt = new MemoryStream())
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (TextWriter swEncrypt = new StreamWriter(csEncrypt))
{
// Write all data to the stream.
swEncrypt.Write(plainText);
swEncrypt.Flush();
csEncrypt.FlushFinalBlock();
// Return the encrypted bytes from the memory stream.
return msEncrypt.ToArray();
}
}
public static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] key, byte[] iv)
{
// Check arguments.
if (cipherText is null)
{
throw new ArgumentNullException(nameof(cipherText));
}
if (cipherText.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(cipherText), cipherText, "length cannot be zero");
}
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
if (key.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(key), key, "length cannot be zero");
}
if (iv is null)
{
throw new ArgumentNullException(nameof(iv));
}
if (iv.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(iv), iv, "length cannot be zero");
}
// Create an AesManaged object
// with the specified key and IV.
// Create a decryptor to perform the stream transform.
// Create the streams used for decryption.
using (SymmetricAlgorithm aesAlg = new AesManaged { Key = key, IV = iv })
using (ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
using (Stream msDecrypt = new MemoryStream(cipherText))
using (Stream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (TextReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
return srDecrypt.ReadToEnd();
}
}

GDI+ Error - loading image in Asp.net. Student [duplicate]

I create an asp.net 4.0 web application which has a web service for uploading images. I am uploading images by sending the image in form of Base64 string from my mobile app to the web service.
Following is my code:
public string Authenticate(string username, string password, string fileID, string imageData)
{
Dictionary<string, string> responseDictionary = new Dictionary<string, string>();
bool isAuthenticated = true; // Set this value based on the authentication logic
try
{
if (isAuthenticated)
{
UploadImage(imageData);
string result = "success";
var message = "Login successful";
responseDictionary["status"] = result;
responseDictionary["message"] = message;
}
}
catch (Exception ex)
{
responseDictionary["status"] = ex.Message;
responseDictionary["message"] = ex.StackTrace;
}
return new JavaScriptSerializer().Serialize(responseDictionary);
}
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)Image.FromStream(ms);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
ms.Close();
bitmap.Save(uploadPath, System.Drawing.Imaging.ImageFormat.Jpeg);
bitmap.Dispose();
}
This code was working fine on my local ASP.NET development server and I was able to see the uploaded image in my "uploads" directory. However, after transferring the code to the FTP directory, I am now getting the following error:
A generic error occurred in GDI+
I have checked that the upload directory has proper permission by creating a dummy .aspx page and creating a text file on page_load, and it works fine.
Even after doing google search, I was not able to solve this problem. Can anybody help me fixing this?
Thanks a lot in advance.
Instead of writing directly to files, save your bitmap to a MemoryStream and then save the contents of the stream to disk. This is an old, known issue and, frankly, I don't remember all the details why this is so.
MemoryStream mOutput = new MemoryStream();
bmp.Save( mOutput, ImageFormat.Png );
byte[] array = mOutput.ToArray();
// do whatever you want with the byte[]
In your case it could be either
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
// store the byte[] directly, without converting to Bitmap first
using ( FileStream fs = File.Create( uploadPath ) )
using ( BinaryWriter bw = new BinaryWriter( fs ) )
bw.Write( imageBytes );
}
or
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)Image.FromStream(ms);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
ms.Close();
// convert to image first and store it to disk
using ( MemoryStream mOutput = new MemoryStream() )
{
bitmap.Save( mOutput, System.Drawing.Imaging.ImageFormat.Jpeg);
using ( FileStream fs = File.Create( uploadPath ) )
using ( BinaryWriter bw = new BinaryWriter( fs ) )
bw.Write( mOutput.ToArray() );
}
}
Furthermore I think it's worth pointing out that when MemoryStream is used, stream must always be closed and save method MUST be called before the stream closure
byte[] byteBuffer = Convert.FromBase64String(Base64String);
MemoryStream memoryStream = new MemoryStream(byteBuffer);
memoryStream.Position = 0;
Bitmap bmpReturn = (Bitmap)Bitmap.FromStream(memoryStream);
bmpReturn.Save(PicPath, ImageFormat.Jpeg);
memoryStream.Close();

Invalid Key Exception

I am retrieving a text password as input from a file and applying AES encryption over that and later on, decrypting that.
When I did it for the first time, every 4 out of 5 times it was running correctly (encryption decryption successful) but 1 time, it was throwing BadPaddingException. Following is what I wrote :
//ABCD is class name
public static void enc(String fileName, String pwd) {
try {
Properties prop = new Properties();
InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
prop.load(input);
input.close();
URL url = ABCD.class.getClassLoader().getResource(fileName);
FileOutputStream outputStream = new FileOutputStream(url.getPath());
KeyGenerator key = KeyGenerator.getInstance("AES");
key.init(128);
SecretKey aesKey = key.generateKey();
String newkey = new String(Base64.encode(aesKey.getEncoded()).getBytes("UTF-8"));
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] clear = pwd.getBytes("UTF-8");
byte[] cipher = aesCipher.doFinal(clear);
String encPwd = new String(cipher);
prop.setProperty("password", encPwd);
prop.setProperty("secKey", newkey);
prop.store(outputStream, null);
outputStream.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static String dec(Properties prop, String fileName) {
String decPwd = ABCD.map.get(fileName);
try {
String newkey = prop.getProperty("secKey");
StringBuilder pwd;
byte[] newkeybuff = Base64.decode(newkey.getBytes("UTF-8"));
SecretKey key = new SecretKeySpec(newkeyuff, "AES");
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.DECRYPT_MODE, key);
pwd = new StringBuilder(prop.getProperty("password"));
byte[] cipher = aesCipher.doFinal(pwd.toString().getBytes());
decPwd = new String(cipher);
} catch (Exception e) {
System.out.println(e);
}
ABCD.map.put(fileName, decPwd);
return decPwd;
}
I needed to fix this. Somewhere, I read that BadPaddingExcpetion occurs since of the operations done with String, in place of where actually byte should be used. Hence, I changed my code to the following :
public static void enc(String fileName, String pwd) {
try {
Properties prop = new Properties();
InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
prop.load(input);
input.close();
URL url = ABCD.class.getClassLoader().getResource(fileName);
FileOutputStream outputStream = new FileOutputStream(url.getPath());
KeyGenerator key = KeyGenerator.getInstance("AES");
key.init(128);
SecretKey aesKey = key.generateKey();
byte[] newkey=(Base64.encode(aesKey.getEncoded())).getBytes("UTF-8");
Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey,new IvParameterSpec(new byte[16]));
byte[] clear = pwd.getBytes("UTF-8");
byte[] cipher = aesCipher.doFinal(clear);
prop.setProperty("password", Arrays.toString(cipher));
prop.setProperty("secKey", Arrays.toString(newkey));
prop.store(outputStream, null);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static String dec(Properties prop, String fileName) {
String decPwd = ABCD.map.get(fileName);
try {
byte[] newkey=prop.getProperty("secKey").getBytes("UTF-8");
byte[] pwd;
byte[] newkeybuff = Base64.decode(newkey);
SecretKeySpec key = new SecretKeySpec(newkeybuff, "AES");
Cipher aesCipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(new byte[16]));
pwd = prop.getProperty("password").getBytes();
byte[] cipher = aesCipher.doFinal(pwd);
decPwd=new String(cipher);
System.out.println("Decrypted pwd " + decPwd);
}
catch (Exception e) {
System.out.println(e);
}
ABCD.map.put(fileName, decPwd);
return decPwd;
}
Now, I am getting InvalidKeyException. This time, I read that the size of the key should be 16 bytes. But I don't know how to apply this. Need a fix for this!
You should check your IV (Initialization Vector) which must be the same for encryption and decryption.
A padding error usually means the decryption failed.
Check that the key is a full length (16, 24 or 32 bytes), the IV is full length (16-bytes). If the key or IV is to short it will be padded with "something"and that man not be consistent, there is no standard for such padding.
getBytes("UTF-8") may return different length of bytes depending on the characters used.
Using new IvParameterSpec(new byte[16]) for the IV is incorrect, the IV should be a random bytes. A usual method of handling the IV is to create a random IV on encryption and prepend it to the encrypted data, it does not need to be secret and by prepending it will be available for decryption.

Generating XML file with a Digital Signature Certificate

I am trying to sign an XML file in C# .NET 4.0 with a private RSA Key generated by OpenSSL.
My source code looks like :
public static void SignXml(String filePath, String certificatePath)
{
CspParameters cspParams1 = new CspParameters();
cspParams1.KeyContainerName = certificatePath;
RSACryptoServiceProvider rsakey = new RSACryptoServiceProvider(cspParams1);
XmlDocument xmlDoc = new XmlDocument();
// Load an XML file into the XmlDocument object.
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load(filePath);
SignedXml signedXml = new SignedXml();
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = certificatePath;
// Create a new RSA signing key and save it in the container.
RSACryptoServiceProvider Key = new RSACryptoServiceProvider(cspParams);
// Add the key to the SignedXml document.
signedXml.SigningKey = Key;
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "";
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
// Load the X509 certificate.
X509Certificate MSCert = X509Certificate.CreateFromCertFile(certificatePath);
// Load the certificate into a KeyInfoX509Data object
// and add it to the KeyInfo object.
keyInfo.AddClause(new KeyInfoX509Data(MSCert));
keyInfo.AddClause(new RSAKeyValue((RSA)Key));
// Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyInfo;
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
xmlDoc.Save(filePath);
}
I am calling the class (CPSMSXmlGenerator) in my application as a DLL(named DBTBeneficiariesCPSMS) and code for calling it is :
Dim genXml As String = DBTBeneficiariesCPSMS.CPSMSXmlGenerator.getXmlFile1(xml)
'Dim appPath As String = Request.PhysicalApplicationPath
Dim fullPath As String = Server.MapPath("/XML/") + dataSource + ".xml"
lblMessage.Text = fullPath
Dim SwFromFile As StreamWriter = New StreamWriter(fullPath)
SwFromFile.Write(genXml)
SwFromFile.Flush()
SwFromFile.Close()
CPSMSXmlGenerator.SignXml(fullPath, Server.MapPath("/XML/aua.cer"))
Now, the problem is whenever my application runs, it halts at ' Reference.Uri="" ' and an error as :-
Error: An XmlDocument context is required to resolve the Reference Uri .
is displayed, and XML file without digital signature certificate generates.
xmDoc is not passsed to SignedXml. Passing that as param should fix the problem
SignedXml signedXml = new SignedXml(xmlDoc);

Resources