Laden...

CryptIt

Erstellt von marsgk vor 16 Jahren Letzter Beitrag vor 14 Jahren 18.251 Views
M
marsgk Themenstarter:in
1.439 Beiträge seit 2005
vor 16 Jahren
CryptIt

Da des öfteren Fragen zu Verschlüsselung und C# gestellt werden, habe ich mich entschlossen mal ein kleines Kommandozeilen Tool - CryptIt - zu schreiben.
CryptIt soll zeigen, wie man beliebige Dateien verschlüsseln und auch wieder entschlüsseln kann.
Der Großteil des Sourcecodes beschäftigt sich mit Kommandozeilenargumente Parsen und kann getrost übersprungen werden.
Einfach mal

CryptIt /help

eingeben um eine Liste aller Optionen anzuzeigen.

Zum verschlüsseln einer Datei

CryptIt /mode:Encrypt /IVFile:myIVFile /KeyFile:myKeyFile /inFile:myFile.txt /outFile:myFile.secret

eingeben und zum entschlüsseln

CryptIt /mode:Decrypt /IVFile:myIVFile /KeyFile:myKeyFile /inFile:myFile.secret

using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;

public class CryptIt {
	
	public enum Mode {
		Encrypt,
		Decrypt,
		GenerateIV,
		GenerateKey
	}
	
	private static string inFile;
	private static string outFile;
	private static string algorithmName = "RijnDael";
	private static CipherMode cipherMode = CipherMode.CBC;
	private static PaddingMode paddingMode = PaddingMode.PKCS7;
	private static int blockSize = -1;
	private static int keySize = -1;
	private static byte[] iv;
	private static byte[] key;
	private static Mode mode = Mode.Encrypt;
	private static bool showHelp;
	
	public static void Main(string[] args) {
		try {
			ParseArgs(args);
			if (showHelp) {
				PrintUsage();
				return;
			}
		
			switch (mode) {
				case Mode.Encrypt:
					Encrypt();
					break;
			
				case Mode.Decrypt:
					Decrypt();
					break;
				
				case Mode.GenerateIV:
					Console.WriteLine(ByteArrayToHexString(GenerateIV()));
					break;
			
				case Mode.GenerateKey:
					Console.WriteLine(ByteArrayToHexString(GenerateKey()));
					break;
			}
		} catch (Exception e) {
			Console.Error.WriteLine("An exception occurred. {0}", e.Message);
			Console.Error.WriteLine("Write CryptIt /help for more information.");
			Environment.Exit(1);
		}
	}
	
	private static byte[] GenerateIV() {
		byte[] retVal;
		SymmetricAlgorithm alg;
		
		alg = CreateAndInitCipher();
		alg.GenerateIV();
		retVal = alg.IV;
		alg.Clear();
		
		return retVal;
	}
	
	private static byte[] GenerateKey() {
		byte[] retVal;
		SymmetricAlgorithm alg;
		
		alg = CreateAndInitCipher();
		alg.GenerateKey();
		retVal = alg.Key;
		alg.Clear();
		
		return retVal;
	}
	
	private static void Encrypt() {
		SymmetricAlgorithm alg;
		Stream inStream = null;
		Stream outStream = null;
		CryptoStream cryptoStream = null;
		byte[] buffer = new byte[4096];
		int bytesRead;
		
		alg = CreateAndInitCipher();		
		if (iv == null) {
			Console.WriteLine("IV: {0}", ByteArrayToHexString(alg.IV));
		}
		if (key == null) {
			Console.WriteLine("Key: {0}", ByteArrayToHexString(alg.Key));
		}
		
		try {
			// Open input stream
			if (inFile == null) {
				inStream = Console.OpenStandardInput();
			} else {
				inStream = new FileStream(inFile, FileMode.Open, FileAccess.Read, FileShare.Read);
			}
			// Open output stream
			if (outFile == null) {
				outStream = Console.OpenStandardOutput();
			} else {
				outStream = new FileStream(outFile, FileMode.Create, FileAccess.Write, FileShare.Read);
			}
			// Create crypto stream
			cryptoStream = new CryptoStream(outStream, alg.CreateEncryptor(), CryptoStreamMode.Write);
			
			// Encrypt bytes
			while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0) {
				cryptoStream.Write(buffer, 0, bytesRead);
			}
			cryptoStream.FlushFinalBlock();
			
		} finally {
			if (inStream != null) inStream.Close();
			if (cryptoStream != null) cryptoStream.Close();
			if (outStream != null) outStream.Close();
			alg.Clear();
		}
	}
	
	private static void Decrypt() {
		SymmetricAlgorithm alg;
		Stream inStream = null;
		Stream outStream = null;
		CryptoStream cryptoStream = null;
		byte[] buffer = new byte[4096];
		int bytesRead;
		
		alg = CreateAndInitCipher();
		if (iv == null) {
			throw new ApplicationException("Cannot decrypt because no IV set.");
		}
		if (key == null) {
			throw new ApplicationException("Cannot decrypt because no Key set.");
		}
		
		try {
			// Open input stream
			if (inFile == null) {
				inStream = Console.OpenStandardInput();
			} else {
				inStream = new FileStream(inFile, FileMode.Open, FileAccess.Read, FileShare.Read);
			}
			// Open output stream
			if (outFile == null) {
				outStream = Console.OpenStandardOutput();
			} else {
				outStream = new FileStream(outFile, FileMode.Create, FileAccess.Write, FileShare.Read);
			}
			// Create crypto stream
			cryptoStream = new CryptoStream(inStream, alg.CreateDecryptor(), CryptoStreamMode.Read);
			
			// Decrypt bytes
			while ((bytesRead = cryptoStream.Read(buffer, 0, buffer.Length)) > 0) {
				outStream.Write(buffer, 0, bytesRead);
			}
			
		} finally {
			if (cryptoStream != null) cryptoStream.Close();
			if (inStream != null) inStream.Close();
			if (outStream != null) outStream.Close();
			alg.Clear();
		}
	}
	
	private static void PrintUsage() {
		Console.WriteLine("CryptIt");
		Console.WriteLine();
		Console.WriteLine("                 CryptIt options");
		Console.WriteLine();
		Console.WriteLine("/help                          Shows this message");
		Console.WriteLine("/mode:Encrypt                  Encrypts a file (default)");
		Console.WriteLine("/mode:Decrypt                  Decrypts a file");
		Console.WriteLine("/mode:GenerateIV               Generates an IV.");
		Console.WriteLine("/mode:GenerateKey              Generates a secret key.");
		Console.WriteLine("/infile:<file>                 Specify input file name; stdin if omitted");
		Console.WriteLine("/outfile:<file>                Specify output file name; stdout if omitted");
		Console.WriteLine("/algorithm:RijnDael            AES used as cipher (default)");
		Console.WriteLine("/algorithm:DES                 DES used as cipher");
		Console.WriteLine("/algorithm:TripleDES           TripleDES used as cipher");
		Console.WriteLine("/algorithm:RC2                 RC2 used as cipher");
		Console.WriteLine("/ciphermode:CBC                Cipher Block Chaining mode used (default)");
		Console.WriteLine("/ciphermode:CFB                Cipher Feedback mode used");
		Console.WriteLine("/ciphermode:CTS                Cipher Text Stealing mode used");
		Console.WriteLine("/ciphermode:ECB                Electronic Codebook mode used");
		Console.WriteLine("/ciphermode:thumbsup:FB                Output Feedback mode used");
		Console.WriteLine("/paddingmode:ANSIX923          The ANSIX923 padding string consists of a sequence of bytes filled with zeros before the length");
		Console.WriteLine("/paddingmode:ISO10126          The ISO10126 padding string consists of random data before the length");
		Console.WriteLine("/paddingmode:None              No padding is done");
		Console.WriteLine("/paddingmode:PKCS7             The PKCS #7 padding string consists of a sequence of bytes, each of which is equal to the total number of padding bytes added (default)");
		Console.WriteLine("/paddingmode:Zeros             The padding string consists of bytes set to zero");
		Console.WriteLine("/iv:<string>                   The initialization vector as a hex string; valid delimeter characters are ' ', ':', '-'");
		Console.WriteLine("/ivfile:<file>                 Specify initialization vector file name used to load IV");
		Console.WriteLine("/key:<string>                  The secret key as a hex string; valid delimeter characters are ' ', ':', '-'");
		Console.WriteLine("/keyfile:<file>                Specify key file name used to load secret key");
		Console.WriteLine("/keysize:<size>                The size, in bits, of the secret key");
		Console.WriteLine("/blocksize:<size>              The block size, in bits");
	}
	
	private static void ParseArgs(string[] args) {
		foreach (string s in args) {
			if (String.Equals(s, "/help", StringComparison.CurrentCultureIgnoreCase)) {
				showHelp = true;
				return;
			}
			
			// Split into '/<command>' and 'value'
			string[] parts = s.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
			if (parts.Length != 2) {
				string msg = String.Format("Could not parse command line at '{0}'.", s);
				throw new ApplicationException(msg);
			}
			
			switch (parts[0].ToLower()) {
				case "/infile":
					inFile = parts[1];
					break;
				
				case "/outfile":
					outFile = parts[1];
					break;
				
				case "/algorithm":
					algorithmName = parts[1];
					break;
				
				case "/ciphermode":
					cipherMode = (CipherMode)Enum.Parse(typeof(CipherMode), parts[1], true);
					break;
				
				case "/paddingmode":
					paddingMode = (PaddingMode)Enum.Parse(typeof(PaddingMode), parts[1], true);
					break;
				
				case "/iv":
					iv = HexStringToByteArray(parts[1]);
					break;
				
				case "/ivfile":
					iv = HexStringToByteArray(File.ReadAllText(parts[1]).Trim());
					break;
					
				case "/key":
					key = HexStringToByteArray(parts[1]);
					break;
				
				case "/keyfile":
					key = HexStringToByteArray(File.ReadAllText(parts[1]).Trim());
					break;
				
				case "/keysize":
					keySize = Int32.Parse(parts[1]);
					break;
				
				case "/blocksize":
					blockSize = Int32.Parse(parts[1]);
					break;
				
				case "/mode":
					mode = (Mode)Enum.Parse(typeof(Mode), parts[1], true);
					break;
					
				default:
					string msg = String.Format("'{0}' - unknown command.", s);
					throw new ApplicationException(msg);
			}
		}
	}
	
	private static byte[] HexStringToByteArray(string s) {
		string[] parts = s.Split(new char[] { ' ', ':', '-' }, StringSplitOptions.RemoveEmptyEntries);
		byte[] val = new byte[parts.Length];
		
		for(int i = 0; i < parts.Length; i++) {
			val[i] = Convert.ToByte(parts[i], 16);
		}
		
		return val;
	}
	
	private static string ByteArrayToHexString(byte[] val) {
		StringBuilder sBuild = new StringBuilder();
		
		for (int i = 0; i < val.Length; i++) {
			sBuild.AppendFormat("{0:X2}", val[i]);
			if (i < val.Length - 1) {
				sBuild.Append('-');
			}
		}
		
		return sBuild.ToString();
	}
	
	private static SymmetricAlgorithm CreateAndInitCipher() {
		SymmetricAlgorithm alg;
		
		alg = SymmetricAlgorithm.Create(algorithmName);
		alg.Mode = cipherMode;
		alg.Padding = paddingMode;
		if (keySize != -1) {
			// Use user defined key size
			alg.KeySize = keySize;
		}
		if (blockSize != -1) {
			// Use user defined block size
			alg.BlockSize = blockSize;
		}
		if (iv != null) {
			// user entered an IV
			alg.IV = iv;
		} else {
			alg.GenerateIV();
		}
		if (key != null) {
			// user entered a secret key
			alg.Key= key;
		} else {
			alg.GenerateKey();
		}
		
		return alg;
	}
}

318 Beiträge seit 2006
vor 16 Jahren

Genau so etwas habe ich gesucht - das werde ich mir auf jeden Fall anschauen.

K
46 Beiträge seit 2007
vor 16 Jahren
Cool

Hi und ich danke dir 😉 Ich habe mir die CryptIT.cs mal angesehen, bloss alles habe ich nicht verstanden, bin ja auch kein porfessioneller Progger g. Also
was mich als erstes interessiert was ist ein IV ? Dann würde mich noch interessieren ob ich das auch in ein Windowsprogramm integrieren kann. Wenn ich das so richg verstanden habe hast du das Pufferproblem so gelöst dass du Filstreams verwendest oder ? Könntest du das mal etwas erläutern, so ganz blicke ich da noch nicht durch.

Danke schonmal im Voraus für die Hilfe und die ganze Arbeit die du dir gemacht hast.

Liebe Grüsse

Kravnos

1.373 Beiträge seit 2004
vor 16 Jahren

Original von Kravnos
Also was mich als erstes interessiert was ist ein IV ? Initialisierungs-Vektor. Sinn und Zweck erläutert die MSDN-Doku:

http://msdn2.microsoft.com/de-de/library/system.security.cryptography.symmetricalgorithm.ivvalue(VS.80).aspx

Im Klartext: Ohne den IV würde ein bestimmter Inhalt bei dem gleichen Passwort immer die gleiche Ausgabe erzeugen. Der Algorithmus sorgt zwar mittels CBC dafür, dass gleiche Daten innerhalb der Datei unterschiedliche Ausgabedaten erzeugen (indem zuvor kodierte Daten für das Kodieren der nächsten Daten mitverwendet werden), aber um das auch Datei übergreifend hinzubekommen, braucht der Algorithmus einen zufälligen Startwert - den IV. Ein bisschen wie der Seed bei einem Zufallsgenerator.

Grüße,
Andre

318 Beiträge seit 2006
vor 16 Jahren

Super, ich habs getestet - funktioniert sehr sehr gut und ist dabei noch super einfach zu bedienen.

K
46 Beiträge seit 2007
vor 16 Jahren
Danke nochmal

Vielen Danke!!! Das Porgramm ist supersauber geschreiben. Der einzige Nachteil ist dass man keine kompletten Pfadangaben übergeben kann, aber ich habe es etwas modifiziert g und das ist nun auch kein Porblem mehr. Ohne dein Beispiel wäre ich sicherlich nicht so weit gekommen 😉 Ich muss ja neidlos gestehen deine Langeweile iss ja echt krass, ich blicke da selbst nach stundenlangen auseinanderklamüsern des Codes immernochnicht voll durch, aber es funzt und das rasend schnell g Ich habe mir vorgenommen das mal als Klasse umzuschreiben dan kann man es leichter in andere sachen einbinden, aber jetzt bin ich erstmal froh dass es läuft g. Wenn ich das fertig habe dann poste ich die Klasse hier.

Aber sagtmal RijnDeal wird ja im mom als eines der sichersten Verfahren bei einem schlüssel von 256 Bit angesehen, macht es da überhaupt noch Sinn ein 2. Verfahren (BlowFish) drüberlaufen zu lassen oder haltet ihr das für Zeitverschwendung? Ich möchte mal Eure Meinung dazu hören.

Liebe Grüsse

Kravnos

M
marsgk Themenstarter:in
1.439 Beiträge seit 2005
vor 16 Jahren

Also komplette Pfadangaben sollten eigentlich funktionieren. Versuch mal den Pfad unter Anführungszeichen(/infile:"C:\bla...") anzugeben.
Das als Komponente umzuschreiben habe ich mir auch schon überlegt. Werde ich demnächst mal machen. Eventuell auch mit mehr Kommentaren.

Bezüglich doppelt verschlüsseln:
3DES arbeitet so, allerdings mit verschiedenen Schlüsseln und jeweils verschlüsseln/entschlüsseln/verschlüsseln.
Ich denke nicht, dass doppelt verschlüsseln generell sicherer ist, dafür allerdings wesentlich aufwendiger(Rechenzeit).

K
46 Beiträge seit 2007
vor 16 Jahren

Hallo 😉

Ja ich habe mich auch nochmal weiter schlau gelesen, die Sicherheit wird dadurch wircklich nicht soo gesteigert. Es seie denn wir bekommen es hin dass er einen block mit RijnDeal verschlüsselt dann mit Blowfish und so weiter also blockweise das machen und dann auchnoch in einem scheinbar zufälligen Reihenfolge gg Aber man kann es ja auch übertreiben 😉
Das Porbem mit der Pfadangabe habe ich so gelöst dass ich den Pfad in deine Textdatei schreibe und er es sich da rausliest und fertig g Bei mir ist Porggen eben auch immer Basteln 😉 Die Argumente /infile und /outfile werden zwar übergeben aber sie werden nicht verwendet so dass in /infile x steht und in /outfile xx. Eine Zeile drunter werden die werte dann mit der Textdatei ne gesetzt g. Zwar gebastelt aber funzt g. Das einzige Problem was ich jetzt noch habe ist dass ich dein Prog ja mit nem anderen mit Process.Start() ausführe und das braucht scheinbar ne totale Pfadangabe. Da muss ich mir noch was überlegen denn sonnst müsste der User ja das Programm immer an einer bestimmten Stelle auf der Platte haben, aber dafür fällt mir auchnoch was ein, wenn nicht dann schreibei ch halt nochmal nen Post g.

Liebe Grüsse und nochmal vielen Dank an dich marsgk

Kravnos

M
marsgk Themenstarter:in
1.439 Beiträge seit 2005
vor 16 Jahren

Wie gesagt absolute Pfadangaben gehen auch, allerdings musst du den Pfad-String in "" setzten.
Du musst auch das WorkingDirectory(Process.WorkingDirectory) anpassen, dann funktionieren auch relative Pfadangaben.

M
marsgk Themenstarter:in
1.439 Beiträge seit 2005
vor 16 Jahren

Ich habe jetzt das Programm umgeschrieben, sodass es auch als Komponente verwendet werden kann. Einfach den untenstehenden Code ins Projekt einfügen, oder die Dll nutzen.

Zur Verwendung:


void Main() {
   CryptItComponent crypter = new CryptItComponent();//Verwendet AES; für andere Verfahren einfach den Names im Konstruktor als String übergeben.
   Im einfachsten Fall müssen nur Key und IV gesetzt werden, damit gearbeitet werden kann.
  string hexCodedIV = Console.ReadLine();
  crypter.IV = CryptItComponent.HexStringToByteArray(hexCodedIV);
  
  string hexCodedKey = Console.ReadLine();
  crypter.Key= CryptItComponent.HexStringToByteArray(hexCodedKey);

  //-----------------
 
  // Erzeugt einen neuen Schlüssel + IV und gibt diesen aus.
  crypter.GenerateIV();
  hexCodedIV = CryptItComponent.ByteArrayToHexString(crypter.IV);
  Console.WriteLine("IV: {0}", hexCodedIV);
  
  crypter.GenerateKey();
  hexCodedKey = CryptItComponent.ByteArrayToHexString(crypter.Key);
  Console.WriteLine("Key: {0}", hexCodedKey);
}

Sobald zumindest Key und IV gesetzt sind, kann die Klasse wie folgt verwendet werden:
Zum verschlüsseln von Strings gibt es die Methode EncryptString(string text).


byte[] encryptedString = crypter.EncryptString("Hello world!");
string hexString = CryptItComponent.ByteArrayToHexString(encryptedString );
Console.WriteLine("Encrypted string: {0}", hexString);

string decryptedString = crypter.DecryptString(encryptedString);
Console.WriteLine("Decrypted string: {0}", decryptedString);

//oder

string decryptedString = crypter.DecryptString(CryptItComponent.HexStringToByteArray(encryptedString));
Console.WriteLine("Decrypted string: {0}", decryptedString);

Zum verschlüsseln eines byte-Arrays kann die Methode EncryptByteArray verwendet werden.
Dies funktioniert genauso wie bei einem string, nur dass statt string ein byte[] übergeben wird.

Um ganze Objektgraphen zu verschlüsseln, kann die Methode EnryptObject oder EncryptObjectToFile verwendet werden.



[Serializable]
public class Credentials {
   public string url;
   public string password;
   public string userName;
}

[Serializable]
public class PasswordList {
   private Hashtable innerSet = new Hashtable();
   
   public Credentials this[string url] {
       get {
           return (Credentials)innerSet[url];
       }
       
       set{
           innerSet[url] = value;
       }
   }
   ...
}

public class PasswordStorage {
   public static void Main() {
         CryptItComponent crypter = new CryptItComponent();
         //Ask user for master password and IV
        
        PasswordList list = new PasswordList();
        list[@"www.mycsharp.de"] = ...
        ...
        
       crypter.EncryptObjectToFile("passwords.dat", list);
       ...
       list = (PasswordList )crypter.DecryptObjectFromFile("passwords.dat");
   }
}

Zum Verschlüsseln von Dateien gibt es die Methode EncryptFile.


public static void Main() {
   CryptItComponent crypter = new CryptItComponent();
   //Ask user for master password and IV
        
   crypter.EncryptFile("passwords.txt", "enryptedPWDs.dat");
   ...
   crypter.DecryptFile("enryptedPWDs.dat", "passwords.txt");
   
}

Es gibt noch eine allgemeine Methode, EnryptStream, zum verschlüsseln, bei der von einem Stream gelesen wird und in einen Stream geschrieben wird.


using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Runtime.Serialization.Formatters.Binary;

public class CryptItComponent: IDisposable {
	
	private SymmetricAlgorithm alg;
	
	public CryptItComponent() {
		alg = SymmetricAlgorithm.Create();
	}
	
	public CryptItComponent(string algName) {
		alg = SymmetricAlgorithm.Create(algName);
	}
	
	public int BlockSize {
		get {
			return alg.BlockSize;
		}
		
		set {
			alg.BlockSize = value;
		}
	}
	
	public int FeedbackSize {
		get {
			return alg.FeedbackSize;
		}
		
		set {
			alg.FeedbackSize = value;
		}
	}
	
	public byte[] IV {
		get {
			return alg.IV;
		}
		
		set {
			alg.IV = value;
		}
	}
	
	public byte[] Key {
		get {
			return alg.Key;
		}
		
		set {
			alg.Key = value;
		}
	}
	
	public int KeySize {
		get {
			return alg.KeySize;
		}
		
		set {
			alg.KeySize = value;
		}
	}
	
	public KeySizes[] LegalBlockSizes {
		get {
			return alg.LegalBlockSizes;
		}
	}
	
	public KeySizes[] LegalKeySizes {
		get {
			return alg.LegalKeySizes;
		}
	}
	
	public CipherMode Mode {
		get {
			return alg.Mode;
		}
		
		set {
			alg.Mode = value;
		}
	}
	
	public PaddingMode Padding {
		get {
			return alg.Padding;
		}
		
		set {
			alg.Padding = value;
		}
	}
	
	public void GenerateIV() {
		alg.GenerateIV();
	}
	
	public void GenerateKey() {
		alg.GenerateKey();
	}
	
	public void Dispose() {
		alg.Clear();
	}
	
	public byte[] EncryptString(string text) {
		return EncryptString(text, Encoding.UTF8);
	}
	
	public string DecryptString(byte[] encryptedString) {
		return DecryptString(encryptedString, Encoding.UTF8);
	}
	
	public byte[] EncryptString(string text, Encoding encoding) {
		if (text == null) {
			throw new ArgumentNullException("text");
		}
		if (encoding == null) {
			throw new ArgumentNullException("encoding");
		}
		
		return EncryptByteArray(encoding.GetBytes(text));
	}
	
	public string DecryptString(byte[] encryptedString, Encoding encoding) {
		byte[] decryptedRawString;
		
		if (encryptedString == null) {
			throw new ArgumentNullException("encryptedString");
		}
		if (encoding == null) {
			throw new ArgumentNullException("encoding");
		}
		
		decryptedRawString = DecryptByteArray(encryptedString);
		
		return encoding.GetString(decryptedRawString);
	}
	
	public byte[] EncryptByteArray(byte[] data) {
		CryptoStream cryptoStream;
		MemoryStream ms;
		
		if (data == null) {
			throw new ArgumentNullException("data");
		}
		
		ms = new MemoryStream();
		using (cryptoStream = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write)) {
			cryptoStream.Write(data, 0, data.Length);
			cryptoStream.FlushFinalBlock();
		}
		
		return ms.ToArray();
	}
	
	public byte[] DecryptByteArray(byte[] encryptedData) {
		MemoryStream source, destination;
		
		source = new MemoryStream(encryptedData, false);
		destination = new MemoryStream();
		
		DecryptStream(source, destination);
		
		return destination.ToArray();
	}
	
	public void EncryptObjectToFile(string path, object obj) {
		File.WriteAllBytes(path, EncryptObject(obj));
	}
	
	public byte[] EncryptObject(object obj) {
		BinaryFormatter formatter;
		CryptoStream cryptoStream;
		MemoryStream ms;
		
		if (obj == null) {
			throw new ArgumentNullException("obj");
		}
		
		ms = new MemoryStream();
		formatter = new BinaryFormatter();
		using (cryptoStream = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write)) {
			formatter.Serialize(cryptoStream, obj);
			cryptoStream.FlushFinalBlock();
		}
		
		return ms.ToArray();
	}
	
	public object DecryptObjectFromFile(string path) {
		return DecryptObject(File.ReadAllBytes(path));
	}
	
	public object DecryptObject(byte[] encryptedObj) {
		BinaryFormatter formatter;
		CryptoStream cryptoStream;
		MemoryStream ms;
		
		if (encryptedObj == null) {
			throw new ArgumentNullException("encryptedObj");
		}
		
		ms = new MemoryStream(encryptedObj, false);
		formatter = new BinaryFormatter();
		using (cryptoStream = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Read)) {
			return formatter.Deserialize(cryptoStream);
		}
	}
	
	public void EncryptFile(string source, string destination) {
		Stream sourceStream, destinationStream;
		
		sourceStream = null;
		destinationStream = null;
		
		try {
			sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read);
			destinationStream = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.Read);
			
			EnryptStream(sourceStream, destinationStream);
		} finally {
			if (sourceStream != null) sourceStream.Close();
			if (destinationStream != null) destinationStream.Close();
		}
	}
	
	public void DecryptFile(string enryptedFile, string destination) {
		Stream sourceStream, destinationStream;
		
		sourceStream = null;
		destinationStream = null;
		
		try {
			sourceStream = new FileStream(enryptedFile, FileMode.Open, FileAccess.Read, FileShare.Read);
			destinationStream = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.Read);
			
			DecryptStream(sourceStream, destinationStream);
		} finally {
			if (sourceStream != null) sourceStream.Close();
			if (destinationStream != null) destinationStream.Close();
		}
	}
	
	public void EnryptStream(Stream source, Stream destination) {
		CryptoStream cryptoStream;
		byte[] buffer = new byte[4096];
		int bytesRead;
		
		using (cryptoStream = new CryptoStream(destination, alg.CreateEncryptor(), CryptoStreamMode.Write)) {
			while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) {
				cryptoStream.Write(buffer, 0, bytesRead);
			}
			cryptoStream.FlushFinalBlock();
		}
	}
	
	public void DecryptStream(Stream source, Stream destination) {
		CryptoStream cryptoStream;
		byte[] buffer = new byte[4096];
		int bytesRead;
		
		using (cryptoStream = new CryptoStream(source, alg.CreateDecryptor(), CryptoStreamMode.Read)) {
			while ((bytesRead = cryptoStream.Read(buffer, 0, buffer.Length)) > 0) {
				destination.Write(buffer, 0, bytesRead);
			}
		}
	}
	
	public static byte[] HexStringToByteArray(string s) {
		return HexStringToByteArray(s, " ", "-", ":");
	}
	
	public static byte[] HexStringToByteArray(string s, params string[] separator) {
		string[] parts = s.Split(separator, StringSplitOptions.RemoveEmptyEntries);
		byte[] val = new byte[parts.Length];
		
		for(int i = 0; i < parts.Length; i++) {
			val[i] = Convert.ToByte(parts[i], 16);
		}
		
		return val;
	}
	
	public static string ByteArrayToHexString(byte[] val) {
		return ByteArrayToHexString(val, "-");
	}
	
	public static string ByteArrayToHexString(byte[] val, string separator) {
		StringBuilder sBuild = new StringBuilder();
		
		for (int i = 0; i < val.Length; i++) {
			sBuild.AppendFormat("{0:X2}", val[i]);
			if (i < val.Length - 1) {
				sBuild.Append(separator);
			}
		}
		
		return sBuild.ToString();
	}
}

S
201 Beiträge seit 2005
vor 16 Jahren

Hallo zusammen,

ich benutze jetzt auch die CryptItComponent-Klasse, aber habe ein Problem.

Ich verschluessle zuerst eine Datei in einen Programm.
Und danach soll diese Datei in einen andere Programm wieder entschlueselt werden. Aber dabei kommt folgender Fehler:


Padding is invalid and cannot be removed.

Hat jemand dafuer eine loesung.

110 Beiträge seit 2007
vor 16 Jahren

Also ich finde die Komponente echt super! Werd sicher Verwendung dafür finden 😁

J
51 Beiträge seit 2007
vor 16 Jahren

Super komponente, jedoch ein kleiner Fehler drin:

Wenn man der Encrypt/DecryptStream Methode einen MemoryString gibt und den vorher beschrieben hat, setzt er die Poistion nicht wieder auf 0 zurück 🙂

Sollte man vielleicht beachten.

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo juLz,

ich denke andersherum wird ein Schuh draus. Wenn er auf 0 zurücksetzen würde, wäre das ein Fehler. Wenn ich eine Methoden eine Strom gebe, dann erwarte ich, dass sie an der Stelle, wo der Strom gerade steht liest oder schreibt und nicht wo anders. 🙂

herbivore

K
46 Beiträge seit 2007
vor 15 Jahren

Wollte nochmal Danke sagen das Teil ist genial und einfach zu benutzen 😉

Liebe Grüsse

Kravnos

344 Beiträge seit 2007
vor 15 Jahren

Danke, kann ich sicher mal gut gebrauchen 👍

👶-> :]-> 8o-> 🙂

T
574 Beiträge seit 2008
vor 14 Jahren

Ich verschluessle zuerst eine Datei in einen Programm.
Und danach soll diese Datei in einen andere Programm wieder entschlueselt werden. Aber dabei kommt folgender Fehler:

  
Padding is invalid and cannot be removed.  
  

Hab das selbe Problem. Ich hab x.xml nach x.xml.crypt verschlüsselt:


CryptItComponent crypter = new CryptItComponent();
crypter.EncryptFile(file, file + ".crypt");

und dann das selbe wieder zurück:


CryptItComponent crypter = new CryptItComponent();
crypter.DecryptFile(file + ".crypt", file);

funktioniert aber aufgrund der genannten Exception nicht.

Frage noch dazu: Was muss ich alles einstellen, damit jemand nicht einfach mit der selben Komponente die Datei einfach wieder entschlüsseln kann?

@marsgk: Mir ist aufgefallen, dass du relativ oft den Tippfehler Enrypted statt Encrypted hast. Ist dann teils auch in argumenten etc. so.

M
marsgk Themenstarter:in
1.439 Beiträge seit 2005
vor 14 Jahren

@tkrasinger:
Du musst ja auch zuerst den Key und IV setzen.

Mir ist aufgefallen, dass du relativ oft den Tippfehler Enrypted statt Encrypted hast.

Da hat sich wohl ein kleiner Tippfehler per Copy&Paste vervielfältigt.