Secure XOR encryption attempt - c#

This is my first post and I am very sorry if I made errors with the format.
I am trying to write a program to encrypt all kinds of file via XOR in a secure way. I know that XOR isn't the most secure encryption method but I wanted to give it a try.
So please have a look on my methode and tell me if it is complete bullshit or not :)
The password is a String, chosen by the user.
In the beginning I only XORed the file with the password, leading to an easy decryption if parts of the password were guessed correctly.
Here is my procedure:
TmpFile = File XOR (hash of password combined with the pw.length.toString) //to make sure that the password elements are in the right order
TmpFile = TmpFile XOR (XOR byte composed by each byte of the password)//ensure that the password to decode has exactly the right chars.
TmpFile= TmpFile XOR initial_password
Could the encrypted text be decrypted with the self-XOR-shifting technique?
Thanks for your advice! :)
edit: here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.IO;
using System.Windows;
namespace EncodeEverything
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("FileEncrypter v01 \n \n");
//get password
Console.WriteLine("Enter your Password (encryption key)");
string password = getPassword();
Console.WriteLine("");
while (true)
{
Console.WriteLine("");
Console.WriteLine("-----------------------");
Console.WriteLine("");
//get file to encrypt
Console.WriteLine("File to encrypt/decrypt:");
Console.Write(" ");
string path = Console.ReadLine();
//-------------------------------
//load, encrypt & save file
//-------------------------------
try {
Byte[] tmpBArr = encrypt(File.ReadAllBytes(path), getCustomHash(password));
File.WriteAllBytes(path, encrypt(tmpBArr, password));
Console.WriteLine(" done.");
}
catch(System.Exception e)
{
Console.WriteLine("!! Error while processing. Path correct? !!");
}
}
}
private static string getCustomHash(string word)
{
string output = "";
output += word.Length.ToString();
output += word.GetHashCode();
return output;
}
//encrypt bzw decrypt Byte[]
public static Byte[] encrypt(byte[] s, string key)
{
List<Byte> output = new List<byte>();
Byte[] codeword = Encoding.UTF8.GetBytes(key);
Byte keybyte =(Byte)( codeword[0]^ codeword[0]);
foreach(Byte b in codeword)
{
keybyte = (Byte)(b ^ keybyte);
}
for (int i = 0; i < s.Length; i++)
{
output.Add((Byte)(s[i] ^ codeword[i % codeword.Length] ^ keybyte));
}
return output.ToArray();
}
public static string getPassword()
{
Console.Write(" ");
string pwd = "";
while (true)
{
ConsoleKeyInfo i = Console.ReadKey(true);
if (i.Key == ConsoleKey.Enter)
{
break;
}
else if (i.Key == ConsoleKey.Backspace)
{
if (pwd.Length > 0)
{
pwd= pwd.Remove(pwd.Length - 1);
Console.Write("\b \b");
}
}
else
{
pwd+=(i.KeyChar);
Console.Write("*");
}
}
return pwd;
}
}
}

string.GetHashCode doesn't have a well defined return value. So you might not even be able to decrypt the file after you restart the process.
Your key consists of a 32 bit value plus the length of the password. Brute-forced in seconds on a single computer.
Once the file is longer than the hashed key, the key starts repeating, you get a many-time-pad. So even if we ignored the brute-force attack, it'd still be easy to break. It's essentially a xor based vigenere variant.
Ignoring the xor-ed parity byte, which is the same for each byte in the message, the key-stream bytes are ASCII digits, so each key byte has at best 3.3 bits of entropy. Comparing this with the approximately 1.5 bits of entropy per letter in English text, shows you that it's quite weak, even without key-stream repetitions.
=> it's buggy and insecure

You can ignore this answer if you're just trying to encrypt files as a learning exercise in cryptography, but if you're looking for a real-world solution to securing your file data, read on.
I'd really recommend that you use File encryption built into the .NET framework for this sort of thing if you're looking for a real-world solution to keeping your file data secure.
From Microsoft # https://msdn.microsoft.com/en-us/library/system.io.file.encrypt(v=vs.110).aspx
using System;
using System.IO;
using System.Security.AccessControl;
namespace FileSystemExample
{
class FileExample
{
public static void Main()
{
try
{
string FileName = "test.xml";
Console.WriteLine("Encrypt " + FileName);
// Encrypt the file.
AddEncryption(FileName);
Console.WriteLine("Decrypt " + FileName);
// Decrypt the file.
RemoveEncryption(FileName);
Console.WriteLine("Done");
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
// Encrypt a file.
public static void AddEncryption(string FileName)
{
File.Encrypt(FileName);
}
// Decrypt a file.
public static void RemoveEncryption(string FileName)
{
File.Decrypt(FileName);
}
}
}
It is hard to say for sure that this is what you need, because other things may need to be taken into consideration such as whether you need to pass the file between different clients/servers etc, as well as how much data you're encrypting in each file.
Again, if you're looking for real-world cryptography using C#, I can't stress enough that you should be looking to built-in .NET encryption rather than trying to roll your own- especially if you don't have any formal training in the subject matter. I recommend you pore through Microsoft documentation on .NET framework encryption if you're interested in securing data in production:
https://msdn.microsoft.com/en-us/library/0ss79b2x(v=vs.110).aspx
Here is a nice walkthrough for creating an example file encrypting windows form application:
https://msdn.microsoft.com/en-us/library/bb397867(v=vs.110).aspx

Related

RSA Encryption and Decryption with X509certificate2

So, what I need is next:
Create certifiactes for development, get one for the client and one for server
Retrieve password through API that is encoded from client and decode it on server
Now, I managed to create certifiactes following this link. The girl there gave step by step instructions on how to get self signed certifiactes, put them in store, etc... Now, the part I'm having problem with:
I've managed to encrypt my data using this code:
public static string Encrypt(string stringForEncription, string PathToPrivateKey)
{
X509Certificate2 myCertificate;
try
{
myCertificate = new X509Certificate2(PathToPrivateKey, "Test123");
}
catch (Exception e)
{
throw new CryptographicException("Unable to open key file.");
}
RSACryptoServiceProvider rsaObj;
if (myCertificate.HasPrivateKey)
{
rsaObj = (RSACryptoServiceProvider)myCertificate.PrivateKey;
}
else
throw new CryptographicException("Private key not contained within certificate.");
if (rsaObj == null)
return String.Empty;
byte[] decryptedBytes;
byte[] array = Encoding.UTF8.GetBytes(stringForEncription);
try
{
decryptedBytes = rsaObj.Encrypt(array, false);
//decryptedBytes = rsaObj.Encrypt(Convert.FromBase64String(Base64EncryptedData), false);
}
catch (Exception e)
{
throw new CryptographicException("Unable to encrypt data.");
}
// Check to make sure we decrpyted the string
if (decryptedBytes.Length == 0)
return String.Empty;
else
return System.Text.Encoding.UTF8.GetString(decryptedBytes);
}
For PathToPrivate key variable I am using the path to my client ClientCert.pfx. I don't know if I should use any other, but here is the snap of the folder with all the certificates that I made:
Now, for the decryption, I'm using next code:
public static string DecryptEncryptedData(string Base64EncryptedData, string PathToPrivateKey)
{
X509Certificate2 myCertificate;
try
{
myCertificate = new X509Certificate2(PathToPrivateKey, "Test123");
}
catch (Exception e)
{
throw new CryptographicException("Unable to open key file.");
}
RSACryptoServiceProvider rsaObj;
if (myCertificate.HasPrivateKey)
{
rsaObj = (RSACryptoServiceProvider)myCertificate.PrivateKey;
}
else
throw new CryptographicException("Private key not contained within certificate.");
if (rsaObj == null)
return String.Empty;
byte[] decryptedBytes;
try
{
decryptedBytes = rsaObj.Decrypt(Convert.FromBase64String(Base64EncryptedData), false);
}
catch (Exception e)
{
throw new CryptographicException("Unable to decrypt data.");
}
// Check to make sure we decrpyted the string
if (decryptedBytes.Length == 0)
return String.Empty;
else
return System.Text.Encoding.UTF8.GetString(decryptedBytes);
}
And whatever I try to do, it gives me exception:
{"The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. "}
Would really apreciate somebody helping me out.
The reason you are getting the error is the string you are trying to Convert.FromBase64String from a value that is not actually a base-64 string.
After encrypting your data, you should convert the byte array to a base-64 string.
Use Convert.ToBase64String for this.
return Convert.ToBase64String(decryptedBytes);
Then your decrypt line will work:
decryptedBytes =
rsaObj.Decrypt(Convert.FromBase64String(Base64EncryptedData), false);
This is not the exact answer which you might expected but I write here as it's too long as a comment.
I think the decryption itself has no problem at all (I've found the example blog of your code with php encryption) That's why I commented I was curious on the encryptedstring which is the target of decryption.
I also struggled in understanding Security for months and now I use symmetric(AES) and asymmetric(RSA) together. Understanding is really important and everybody takes time..
RSA is asymmetric and one-way which means the Encryption can be done only by public key and the Decryption can be done only by private key.
You're using private key in Encryption method and it seems just copied from Decryption.
The answer by Zesty is right only in terms of formatting. You're also needed to understand the formatting. We need Convert.ToBase64String and Convert.FromBase64String in Encryption and Decryption from byte to base64string and vice versa. However this base64string is not just plain like 'hello' but
'SABlAGwAbABvACAAVwBvAHIAbABkAA==' as you see here
And I kindly recommend to use complete solution(not half one like php encryption) like this blog so that Encryption and Decryption and all are in harmony.
And as last as I commented also, you're needed to think about how to prevent the black users if encryption is done from client side and you don't have only good users.
I hope my experience helps to understand Security which is of most importance.

BouncyCastle C# PublicKey different than GnuPG

I am trying to get a public PGP key from a keyring created by GnuPG using the BouncyCastle C# library. I've gotten it to semi-work by using the following code. The problem is that the public key it outputs is about half the length of the real one and the last few bytes are also different. I'm just trying to get the real key.
UPDATE: Something interesting to note is that the keyring I generated only had one public key, yet I'm getting two out of bouncycastle. I also found that if you insert the second key into the first a few characters from the end, it produces almost the original key. Only a few chars at the end are different. So why are there two keys and why does this occur? What am I missing?
Is the GnuPG keyring not compatible?
Also note that the code shown here only gets the last key. I'm now adding each to a list.
Here is my code:
public static string ReadKey(string pubkeyFile)
{
string theKey;
Stream fs = File.OpenRead(pubkeyFile);
//
// Read the public key rings
//
PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(fs));
fs.Close();
foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings())
{
pgpPub.GetPublicKey();
foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys())
{
//AsymmetricKeyParameter pubKey = pgpKey.GetKey();
//SubjectPublicKeyInfo k = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey);
//byte[] keyData = k.ToAsn1Object().GetDerEncoded();
//byte[] keyData = k.GetEncoded();
byte[] keyData = pgpKey.GetEncoded();
theKey = Convert.ToBase64String(keyData);
}
}
return theKey;
}
Here is the actual public key:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.20 (MingW32)
mQENBFP2z94BCADKfQT9DGHm4y/VEAYGL7XiUavbv+aE7D2OZ2jCbwnx7BYzQBu8
63v5qYe7oH0oBOiw67VaQSjS58fSBAE8vlTkKjvRAscHJNUX9qZrQoRtpMSnrK7N
Ca9N2ptvof7ykF1TAgbxDSSnhwysVznYc7mx76BO6Qx8KChqEd0Yp3w2U89YkUqN
qdzjB7ZIhj5hDM9f4eyHwsz0uZgyqLKK5VgNj6dHVmOHZt6+RIydRC2lGfocWKM8
loPkk6GiSX9sdEm6GXxi7gV/Q3Jr0G099AFg57cWyj1eO6NC8YHLgBHwrB1IkFwi
J0x5IHZssy/XleQ1i1izc3ntWiiH24powuAhABEBAAG0H3N5bmFwczMgPHN5bmFw
czNAc2FmZS1tYWlsLm5ldD6JATkEEwECACMFAlP2z94CGwMHCwkIBwMCAQYVCAIJ
CgsEFgIDAQIeAQIXgAAKCRD944Hz1MHUYP+AB/4roauazFR5lDrJBFB0YoH4VFKM
28IJtuy6OThg3cxhqI/N74sZoxtB90QQk4lcshdpwD7CIe9TCKrnhWokIdm4N91m
TGDmW7iIeM3kcPp3mj9/7hGOetESuz9JxhBQ0aHAXYk5LdHeDKyRg1KL3JvWrJ27
fioDoLLpxxdudSd2nJLhi0hAaHKnkLVl98r37AwxTigGj+J2rN47D+UepJraf8je
eZrY/RfwKJVleF1KYPIgduwX3jdiABrI4EsZP/CdbEWTvmmkFFtD4clSMsmqaXPT
a3VeaL/saScBPL93tDsjqCddcgW28hsnhzoJ7TM78j2zNcTXZjK8/tNCDnShuQEN
BFP2z94BCADmCAMIpOp518ywUlG5Pze5HdpgGiQF26XzwxUt3mPAMXBUQ7vqRMD/
zNagPXKthp/p4t0jRoFwFwF+7CqRrxkv2Rrj5OqDD7JqETY5nfRZ0Hvfi4cPkf2g
S17SVI4LSFQ/v/sISNNiI3Bo/xvpOeK+Af087j4BEe8vjFuyzf08HCglKoL6WAp8
5+Wc2vj+7EbH61YloKKNugq34AyuNh1QYml6LI04b2KR0b/qXTW8UqLvrh4YGaOp
k80l7DpBmKgGtXn8JFfU9V3sGCscSnfzDvKjqpmtKXiJFxO2pyPCN5jRKfGMOSyA
fZ21NIrBJER/WvuIAls8Tikk+wKRKXrpABEBAAGJAR8EGAECAAkFAlP2z94CGwwA
CgkQ/eOB89TB1GDDEAf+OA9hgb3FLbEtcNvkUl9wTtLaxr9nAsBowofNEITH96hV
w4i6em9Rjg29/+4JrnDhibuhsFr/F8uKoj+iZGFw2NpXHYI6yS+BLbuVj8jOkYAy
Gq34HMNWXuS1Nr4VHOxKbKmmLu8YhdYRk2KF9fPI2Qj376C69W90R/LHByCrcCg7
xmqAvO9a8Eac7Rk+Fc+5NKVw9D1rP7MqZGgIQQoh8jLiI2MblvEEahwNxA9AYs8U
PpMD0pdo93wxXIYuKc40MF4yFL9LfpPxDnf373dbYQjk3pNThQ5RagIgLNEhRow4
5x/1wcO6FMx5a/irQXnJ2o1XYRvznBeCsoyOAYbikA==
=r3Qj
-----END PGP PUBLIC KEY BLOCK-----
Here is NEW KEY produced by BouncyCastle (sorry can't help formatting):
mQENBFP2z94BCADKfQT9DGHm4y/VEAYGL7XiUavbv+aE7D2OZ2jCbwnx7BYzQBu863v5qYe7oH0oBOiw67VaQSjS58fSBAE8vlTkKjvRAscHJNUX9qZrQoRtpMSnrK7NCa9N2ptvof7ykF1TAgbxDSSnhwysVznYc7mx76BO6Qx8KChqEd0Yp3w2U89YkUqNqdzjB7ZIhj5hDM9f4eyHwsz0uZgyqLKK5VgNj6dHVmOHZt6+RIydRC2lGfocWKM8loPkk6GiSX9sdEm6GXxi7gV/Q3Jr0G099AFg57cWyj1eO6NC8YHLgBHwrB1IkFwiJ0x5IHZssy/XleQ1i1izc3ntWiiH24powuAhABEBAAG0H3N5bmFwczMgPHN5bmFwczNAc2FmZS1tYWlsLm5ldD6JATkEEwECACMFAlP2z94CGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRD944Hz1MHUYP+AB/4roauazFR5lDrJBFB0YoH4VFKM28IJtuy6OThg3cxhqI/N74sZoxtB90QQk4lcshdpwD7CIe9TCKrnhWokIdm4N91mTGDmW7iIeM3kcPp3mj9/7hGOetESuz9JxhBQ0aHAXYk5LdHeDKyRg1KL3JvWrJ27fioDoLLpxxdudSd2nJLhi0hAaHKnkLVl98r37AwxTigGj+J2rN47D+UepJraf8jeeZrY/RfwKJVleF1KYPIgduwX3jdiABrI4EsZP/CdbEWTvmmkFFtD4clSMsmqaXPTa3VeaL/saScBPL93tDsjqCddcgW28hsnhzoJ7TM78j2zNcTXZjK8/tNCDnShsAIAA7kBDQRT9s/eAQgA5ggDCKTqedfMsFJRuT83uR3aYBokBdul88MVLd5jwDFwVEO76kTA/8zWoD1yrYaf6eLdI0aBcBcBfuwqka8ZL9ka4+Tqgw+yahE2OZ30WdB734uHD5H9oEte0lSOC0hUP7/7CEjTYiNwaP8b6TnivgH9PO4+ARHvL4xbss39PBwoJSqC+lgKfOflnNr4/uxGx+tWJaCijboKt+AMrjYdUGJpeiyNOG9ikdG/6l01vFKi764eGBmjqZPNJew6QZioBrV5/CRX1PVd7BgrHEp38w7yo6qZrSl4iRcTtqcjwjeY0SnxjDksgH2dtTSKwSREf1r7iAJbPE4pJPsCkSl66QARAQABiQEfBBgBAgAJBQJT9s/eAhsMAAoJEP3jgfPUwdRgwxAH/jgPYYG9xS2xLXDb5FJfcE7S2sa/ZwLAaMKHzRCEx/eoVcOIunpvUY4Nvf/uCa5w4Ym7obBa/xfLiqI/omRhcNjaVx2COskvgS27lY/IzpGAMhqt+BzDVl7ktTa+FRzsSmyppi7vGIXWEZNihfXzyNkI9++guvVvdEfyxwcgq3AoO8ZqgLzvWvBGnO0ZPhXPuTSlcPQ9az+zKmRoCEEKIfIy4iNjG5bxBGocDcQPQGLPFD6TA9KXaPd8MVyGLinONDBeMhS/S36T8Q539+93W2EI5N6TU4UOUWoCICzRIUaMOOcf9cHDuhTMeWv4q0F5ydqNV2Eb85wXgrKMjgGG4pCwAgAD
Still not the same. Put both keys in notepad and search the "tNCDnS", after that is where they change.
Thanks for sticking with me. I've gotten far enough with this that I don't want to scrap the whole code for some shitty encryption.
You may have been a victim of BouncyCastle's somewhat uncommon usage of the term "keyring". Here is BouncyCastle's usage of three related terms:
PgpPublicKey: This is the public part of a single mathematical key, in PGP format. It does not contain any subkeys.
PgpPublicKeyRing: This is a cryptographic key with its subkeys. Other programs usually refer to this as a PGP Key.
PgpPublicKeyRingBundle: This is any number of PgpPublicKeyRings (as defined in BouncyCastle). Other programs usually refer to this as a Public Key Ring (without bundle).
You iterated through the keyring to find all PgpPublicKey objects. You decoded them and return the last and only the last of them as a string. If you paste the input and output strings to pgpdump.net (you have to add the BEGIN and END headers to the output), you see that you lose the subkey in this procedure. Use the PgpPublicKeyRing's GetEncoded() method instead. This should retain all information and is also easier :-).
Additionally, PGP's Radix-encoding is a little bit more than just Base64-encoding. A lot of programs and libraries, including BC, ignores whether there are PGP headers and footers and also the CRC checksum that Radix-encoding includes as opposed to simple Base64. However, GPG is more strict and seems not to accept ASCII armors without CRC checksum. Therefore, you have to use the binary key (which is the byte[] keyData in your problem code) or create a proper PGP ASCII armor. I have edited the following code based on your code to implement the latter using BC's ArmoredOutputStream:
public static string ReadKey(string pubkeyFile)
{
Stream fs = File.OpenRead(pubkeyFile);
//
// Read the public key rings
//
PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(fs));
fs.Close();
foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings())
{
using (MemoryStream ms = new MemoryStream())
{
using (ArmoredOutputStream aos = new ArmoredOutputStream(ms))
pgpPub.Encode(aos);
return System.Text.Encoding.ASCII.GetString(ms.ToArray());
}
}
return null;
}
EDIT: The following is a complete program with no external dependencies. It works for me, i.e. outputs "Same!". Please run that exact program and check whether it outputs "Same!" or "Difference!". If it outputs "Same!", then you can use it to correct your own program code:
using System;
using System.IO;
using Org.BouncyCastle.Bcpg.OpenPgp;
class Program
{
private const string PGP_OVERFLOW_KEYBODY =
"mQENBFP2z94BCADKfQT9DGHm4y/VEAYGL7XiUavbv+aE7D2OZ2jCbwnx7BYzQBu8\r\n" +
"63v5qYe7oH0oBOiw67VaQSjS58fSBAE8vlTkKjvRAscHJNUX9qZrQoRtpMSnrK7N\r\n" +
"Ca9N2ptvof7ykF1TAgbxDSSnhwysVznYc7mx76BO6Qx8KChqEd0Yp3w2U89YkUqN\r\n" +
"qdzjB7ZIhj5hDM9f4eyHwsz0uZgyqLKK5VgNj6dHVmOHZt6+RIydRC2lGfocWKM8\r\n" +
"loPkk6GiSX9sdEm6GXxi7gV/Q3Jr0G099AFg57cWyj1eO6NC8YHLgBHwrB1IkFwi\r\n" +
"J0x5IHZssy/XleQ1i1izc3ntWiiH24powuAhABEBAAG0H3N5bmFwczMgPHN5bmFw\r\n" +
"czNAc2FmZS1tYWlsLm5ldD6JATkEEwECACMFAlP2z94CGwMHCwkIBwMCAQYVCAIJ\r\n" +
"CgsEFgIDAQIeAQIXgAAKCRD944Hz1MHUYP+AB/4roauazFR5lDrJBFB0YoH4VFKM\r\n" +
"28IJtuy6OThg3cxhqI/N74sZoxtB90QQk4lcshdpwD7CIe9TCKrnhWokIdm4N91m\r\n" +
"TGDmW7iIeM3kcPp3mj9/7hGOetESuz9JxhBQ0aHAXYk5LdHeDKyRg1KL3JvWrJ27\r\n" +
"fioDoLLpxxdudSd2nJLhi0hAaHKnkLVl98r37AwxTigGj+J2rN47D+UepJraf8je\r\n" +
"eZrY/RfwKJVleF1KYPIgduwX3jdiABrI4EsZP/CdbEWTvmmkFFtD4clSMsmqaXPT\r\n" +
"a3VeaL/saScBPL93tDsjqCddcgW28hsnhzoJ7TM78j2zNcTXZjK8/tNCDnShuQEN\r\n" +
"BFP2z94BCADmCAMIpOp518ywUlG5Pze5HdpgGiQF26XzwxUt3mPAMXBUQ7vqRMD/\r\n" +
"zNagPXKthp/p4t0jRoFwFwF+7CqRrxkv2Rrj5OqDD7JqETY5nfRZ0Hvfi4cPkf2g\r\n" +
"S17SVI4LSFQ/v/sISNNiI3Bo/xvpOeK+Af087j4BEe8vjFuyzf08HCglKoL6WAp8\r\n" +
"5+Wc2vj+7EbH61YloKKNugq34AyuNh1QYml6LI04b2KR0b/qXTW8UqLvrh4YGaOp\r\n" +
"k80l7DpBmKgGtXn8JFfU9V3sGCscSnfzDvKjqpmtKXiJFxO2pyPCN5jRKfGMOSyA\r\n" +
"fZ21NIrBJER/WvuIAls8Tikk+wKRKXrpABEBAAGJAR8EGAECAAkFAlP2z94CGwwA\r\n" +
"CgkQ/eOB89TB1GDDEAf+OA9hgb3FLbEtcNvkUl9wTtLaxr9nAsBowofNEITH96hV\r\n" +
"w4i6em9Rjg29/+4JrnDhibuhsFr/F8uKoj+iZGFw2NpXHYI6yS+BLbuVj8jOkYAy\r\n" +
"Gq34HMNWXuS1Nr4VHOxKbKmmLu8YhdYRk2KF9fPI2Qj376C69W90R/LHByCrcCg7\r\n" +
"xmqAvO9a8Eac7Rk+Fc+5NKVw9D1rP7MqZGgIQQoh8jLiI2MblvEEahwNxA9AYs8U\r\n" +
"PpMD0pdo93wxXIYuKc40MF4yFL9LfpPxDnf373dbYQjk3pNThQ5RagIgLNEhRow4\r\n" +
"5x/1wcO6FMx5a/irQXnJ2o1XYRvznBeCsoyOAYbikA==";
static void Main(string[] args)
{
string parsedKey = ReadKeyDirectly(PGP_OVERFLOW_KEYBODY);
if (parsedKey != PGP_OVERFLOW_KEYBODY.Replace("\r\n",""))
Console.WriteLine("Difference!");
else
Console.WriteLine("Same!");
}
public static string ReadKeyDirectly(string stringKeyData)
{
Stream fs = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(stringKeyData));
fs.Seek(0, SeekOrigin.Begin);
PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(fs));
foreach (PgpPublicKeyRing pubRing in pubRings.GetKeyRings())
return Convert.ToBase64String(pubRing.GetEncoded());
return null;
}
}

MD5 hashing in windowsphone 8

Hay there i'm trying to hash a string to MD5 in windows phone ... but when i call the MD5 class i get the following error
The type or namespace name 'MD5' could not be found (are you missing a
using directive or an assembly reference?)
PS: i have used the System.Security.Cryptography name space
so how can i use the MD5 hash in the windows phone ?
here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
namespace FluoraPin
{
class HASHING
{
public static string GetMd5Hash(MD5 md5Hash, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
// t verify md5 hashing
private bool VerifyMd5Hash(MD5 md5Hash, string input, string hash)
{
// Hash the input.
string hashOfInput = GetMd5Hash(md5Hash, input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
if (0 == comparer.Compare(hashOfInput, hash))
{
return true;
}
else
{
return false;
}
}
}
}
I think the answer is right in the error:
The type or namespace name 'MD5' could not be found (are you missing a using directive or an assembly reference?)
MD5 is not a class in the System.Security.Cryptography namespace for Windows Phone. See MSDN's System.Security.Cryptography page for Windows Phone for confirmation.
Contrast this with MSDN's general System.Security.Cryptography page, which lists MD5 as a class in the namespace.
Having said this, you should really use SHA-256 or higher instead of MD5 or SHA-1 hashing.
SHA-256 hashing is available for Windows Phone 7 and 8 through the SHA256Managed class - in the Security.Security.Cryptography namespace you are already using. For an example of how to use SHA256Managed, see an answer to a related SO question.
This person has an implementation of MD5 hashing in C# that can be used for WP8:
http://upadhyayjitesh.blogspot.com/2013/01/windows-phone-md5-hash-conversion.html
You could add Bouncy Castle as a NuGet package to your project. It supports MD5 hashing (and much more encryption algorithms). See its NuGet page for more details. Or its project page "The Legion of the Bouncy Castle"
I haven't tested your solution but I found a solution that works fine for me.
using System.Security.Cryptography;
class MD5Hash
{
public String getHash(String input)
{
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
sb.Append(hash[i].ToString("x2"));
return sb.ToString();
}
public Boolean VerifyHash(String input, String hash)
{
String hashOfInput = getHash(input);
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
if (0 == comparer.Compare(hashOfInput, hash))
return true;
else
return false;
}
}
This will hash your String, no errors at all.
Also, the error you are getting, check that you are not compiling a .Net version that include the text "Client Profile".
I am new to this so If I have got this completely wrong then I'm sorry could you be a bit more specific with you question.

MD5 checks for repeated files in folder?

Let's say I have a folder with five hundred pictures in it, and I want to check for repeats and delete them.
Here's the code I have right now:
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
return md5.ComputeHash(stream);
}
}
Would this be viable to spot repeated MD5s in a specific folder, provided I loop it accordingly?
Creating hashes in order to identify identical files is OK, in any programming language, on any OS. It is slow, though, because you read the whole file even if that is not necessary.
I would recommend several passes for finding duplicates:
get the size of all files
for all files of equal size: get the hash of the first, say, 1k bytes
for all files of equal size and equal hash of first 1k: get the hash of the entire file
There is a risk of hash collisions. You cannot avoid it with hash algorithms. As MD5 uses 128 bits, the risk is 1 : (1 << 128) (roughly 0.0000000000000000000000000000000000000001) for two random files. Your chances of getting the jackpot in your national lottery four times in a row, using only one lottery ticket each week, are much better than getting a hash collision on a random pair of files.
Though the probability of a hash collision raises somewhat, if you compare the hash of many files. The mathematically interested and people implementing hash containers should look up the "birthday problem". Mere mortals trust MD5 hashes when they are not implementing cryptographic algorithms.
using System;
using System.IO;
using System.Collections.Generic;
internal static class FileComparer
{
public static void Compare(string directoryPath)
{
if(!Directory.Exists(directoryPath))
{
return;
}
FileComparer.Compare(new DirectoryInfo(directoryPath));
}
private static void Compare(DirectoryInfo info)
{
List<FileInfo> files = new List<FileInfo>(info.EnumerateFiles());
foreach(FileInfo file in files)
{
if(file.Exists)
{
byte[] array = File.ReadAllBytes(file.FullName);
foreach(FileInfo file2 in files)
{
int length = array.Length;
byte[] array2 = File.ReadAllBytes(file2.FullName);
if(array2.Length == length)
{
bool flag = true;
for(int current = 0; current < length; current++)
{
if(array[current] != array2[current])
{
flag = false;
break;
}
}
if(flag)
{
file2.Delete();
}
}
}
}
}
}
}

C# Encrypt an XML File

I need two methods one to encrypt and one to decrypt an xml file with a key= "hello world",the key hello world should be used to encrypt and decrypt the xml file.These methods should work on all machines!!! Any encryption methods will do. XML File contents below:
<root>
<lic>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</lic>
</root>
Can some give me a sample?The issue is the msdn sample encyptions make a xml file encypted but when I decrypt on another machine it doesn't work.For example
I tried this sample:
How to: Encrypt XML Elements with Asymmetric Keys,
but here there is some kinda session and on another machine it says bad data phewf!
If you want the same key for encrypting and decrypting you should use a symmetric method (that's the definition, really). Here's the closest one to your sample (same source).
http://msdn.microsoft.com/en-us/library/sb7w85t6.aspx
The posted sample isn't working because they aren't using the same keys. Not only on different machines: running the program on the same machine twice should not work either (didn't work for me), because they use different random keys every time.
try adding this code after creating your key:
key = new RijndaelManaged();
string password = "Password1234"; //password here
byte[] saltBytes = Encoding.UTF8.GetBytes("Salt"); // salt here (another string)
var p = new Rfc2898DeriveBytes(password, saltBytes); //TODO: think about number of iterations (third parameter)
// sizes are devided by 8 because [ 1 byte = 8 bits ]
key.IV = p.GetBytes(key.BlockSize / 8);
key.Key = p.GetBytes(key.KeySize / 8);
Now the program is using the same key and initial vector, and Encrypt and Decrypt should work on all machines.
Also, consider renaming key to algorithm, otherwise this is very misleading. I'd say it's a bad, not-working-well example from MSDN.
NOTE: PasswordDeriveBytes.GetBytes() has been deprecated because of serious (security) issues within the PasswordDeriveBytes class. The code above has been rewritten to use the safer Rfc2898DeriveBytes class instead (PBKDF2 instead of PBKDF1). Code generated with the above using PasswordDeriveBytes may be compromised.
See also: Recommended # of iterations when using PKBDF2-SHA256?
First of all, if you want to use the same key for encrypting and decrypting, you should look at symmetric cryptography. Asymmetric cryptography is when the keys for encrypting and decrypting are different. Just so that you know - RSA is asymmetric, TripleDES and Rijndael are symmetric. There are others too, but .NET does not have default implementations for them.
I'd advise studying the System.Security.Cryptography namespace. And learning a bit about all that stuff. It has all you need to encrypt and decrypt files, as well as generate a password. In particular, you might be interested in these classes:
CryptoStream
PasswordDeriveBytes
RijndaelManaged
There are also examples for usage in MSDN for each of them. You can use these classes to encrypt any file, not just XML. If however you want to encrypt just a select few elements, you can take a look at System.Security.Cryptography.Xml namespace. I see you've already found one article about it. Keep following the links on that page and you will learn more about those classes.
Would be cooler if you used a private key to sign the <lic> element and added the result to the file (in a <hash> element perhaps). This would make it possibly for everyone to read the xml file in case your support needs to know the license number, or the date of expiry, but they can not change any values without the private key.
The public key needed to verify the signature would be common knowledge.
Clarification
Signing your code will only protect it against changes, it will not keep any information in it hidden. Your original question mentions encryption, but I am not sure that it is a requirement to hide the data, or just protect it from modification.
Example code: (Never publish PrivateKey.key. ServerMethods are only needed when signing the xml file, ClientMethods are only needed when verifying the xml file.)
using System;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
public static class Program {
public static void Main() {
if (!File.Exists("PublicKey.key")) {
// Assume first run, generate keys and sign document.
ServerMethods.GenerateKeyPair();
var input = new XmlDocument();
input.Load("input.xml");
Debug.Assert(input.DocumentElement != null);
var licNode = input.DocumentElement["lic"];
Debug.Assert(licNode != null);
var licNodeXml = licNode.OuterXml;
var signedNode = input.CreateElement("signature");
signedNode.InnerText = ServerMethods.CalculateSignature(licNodeXml);
input.DocumentElement.AppendChild(signedNode);
input.Save("output.xml");
}
if (ClientMethods.IsValidLicense("output.xml")) {
Console.WriteLine("VALID");
} else {
Console.WriteLine("INVALID");
}
}
public static class ServerMethods {
public static void GenerateKeyPair() {
var rsa = SharedInformation.CryptoProvider;
using (var keyWriter = File.CreateText("PublicKey.key"))
keyWriter.Write(rsa.ToXmlString(false));
using (var keyWriter = File.CreateText("PrivateKey.key"))
keyWriter.Write(rsa.ToXmlString(true));
}
public static string CalculateSignature(string data) {
var rsa = SharedInformation.CryptoProvider;
rsa.FromXmlString(File.ReadAllText("PrivateKey.key"));
var dataBytes = Encoding.UTF8.GetBytes(data);
var signatureBytes = rsa.SignData(dataBytes, SharedInformation.HashAlgorithm);
return Convert.ToBase64String(signatureBytes);
}
}
public static class ClientMethods {
public static bool IsValid(string data, string signature) {
var rsa = SharedInformation.CryptoProvider;
rsa.FromXmlString(File.ReadAllText("PublicKey.key"));
var dataBytes = Encoding.UTF8.GetBytes(data);
var signatureBytes = Convert.FromBase64String(signature);
return rsa.VerifyData(dataBytes, SharedInformation.HashAlgorithm, signatureBytes);
}
public static bool IsValidLicense(string filename) {
var doc = new XmlDocument();
doc.Load(filename);
var licNode = doc.SelectSingleNode("/root/lic") as XmlElement;
var signatureNode = doc.SelectSingleNode("/root/signature") as XmlElement;
if (licNode == null || signatureNode == null) return false;
return IsValid(licNode.OuterXml, signatureNode.InnerText);
}
}
public static class SharedInformation {
public static int KeySize {
get { return 1024; }
}
public static string HashAlgorithm {
get { return "SHA512"; }
}
public static RSACryptoServiceProvider CryptoProvider {
get { return new RSACryptoServiceProvider(KeySize, new CspParameters()); }
}
}
}
this is how you digitally sign and verify XML documents Sign XML Documents

Categories