vignere-chiffre

mephisto_x

Grünschnabel
Halli hallo, bin neu hier und bin auf der Suche nach Tricks schon des Öfteren hier gelandet, deshalb dachte ich mir, ich könnte hier mal meine sozusagen programmiertechnische Jungfernfahrt zelebrieren ;). Ich wollte einfach mal Anregungen haben, was ich noch so einfügen könnte und wie ich eventuell etwas verbessern könnte, da hier ja Einige kompetente User angemeldet sind.

also lange Rede kurzer Sinn ;) hier ist der Code

Code:
//
// decodehlpr.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//


#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;


char keycrypt(char, char);
char keydecrypt(char, char);

bool isAllowed(char Alphat)
{
	for(int count=97; count<=122; count++)
	{
		if (Alphat == char(count))
		{
			return true;
		}
	}
	cout << "Please enter a letter! ";
	return false;
}

char keycrypt(char PresentChar, char entered) //97-122 ASCII-Symbols a-z
{
	char CryptedChar;
	int UsedAlphabet=0;
	if(entered!='z')
	{
		UsedAlphabet = (int(entered)-97);
	}
	if ((int(PresentChar)+UsedAlphabet)<=122)
	{
		CryptedChar=char(int(PresentChar)+UsedAlphabet);		
	}
	else
	{
		CryptedChar=char(int(PresentChar)+UsedAlphabet-26);
	}
	return CryptedChar;
}

char keydecrypt(char PresentChar, char entered) //97-122 ASCII-Symbols a-x
{
	char DecryptedChar;
	int UsedAlphabet=0;
	if(entered!='z')
	{
		UsedAlphabet = (int(entered)-97);
	}
	if ((int(PresentChar)-UsedAlphabet)>=97)
	{
		DecryptedChar=char(int(PresentChar)-UsedAlphabet);		
	}
	else
	{
		DecryptedChar=char(int(PresentChar)-UsedAlphabet+26);
	}
	return DecryptedChar;
}

int main()
{
	cout << "Welcome!" << endl;
	cout << "Please chose either code [d]ecryption or code [e]ncryption\n";
	string Text;
	string KeyWord;
	string Crypted;
	string DeCrypted;
	ofstream file("Test.txt", ios::app);
	string buffer;
	char chosen;
	cin >> chosen;
	switch(chosen)
	{
	case 'd':
		cout << "Please enter the crypted code, which has to be decrypted!";
		cin >> Text;
		DeCrypted=Text;
		cout << endl << "Now please enter the used keyword! (consisting of letters a to z)" << endl;
		cin >> KeyWord;
		DeCrypted = Text;
		if(Text.size()>KeyWord.size())
		{
		int i=0;
		do
		{
			KeyWord+=KeyWord[i];
			i++;
		}
		while(KeyWord.size()!=Text.size());
		}
		for(int i=0; i<=Text.size()-1; i++)
		{
			DeCrypted[i]=keydecrypt(Text[i],KeyWord[i]);
		}
		if(file.is_open())
		{
			while(!file.eof())
			{
				file << DeCrypted << endl;
				file << "naechster Teil: " << endl;
				file.close();		
			}
		}
		else cout << "Unable to open the file";
		break;
	case 'e':
		cout << "Please enter the clear text, which you want to encrypt with CAESAR 1 alphabet!" << endl;
		cin >> Text;
		Crypted=Text;
		cout << endl << "Now please enter your favourite keyword! (consisting of letters a to z)" << endl;
		cin >> KeyWord;
		Crypted = Text;
		if(Text.size()>KeyWord.size())
		{
			int i=0;
			do
			{
				KeyWord+=KeyWord[i];
				i++;
			}
			while(KeyWord.size()!=Text.size());
		}
		for(int i=0; i<=Text.size()-1; i++)
		{
			Crypted[i]=keycrypt(Text[i],KeyWord[i]);
		}
		cout << Crypted;
		while(!file.eof())
		{
			file << Crypted << endl;
			file.close();
		}
		
		
		break;
	default:
		cout << "Please either enter d or e!";
	}
	system("pause");
	return 0;
}
 
Respekt das ist die längste Lösung die ich für das Problem bisher gesehen habe :D:D Und langsamste ...

C++:
bool isAllowed(char Alphat)
{
	for(int count=97; count<=122; count++)
	{
		if (Alphat == char(count))
		{
			return true;
		}
	}
	cout << "Please enter a letter! ";
	return false;
}
... ähh kennst du >= und <= ? :D
C++:
const bool is_alpha(const char c) { return c >= 'a' && c <= 'z'; }
Die Funktion gibt es aber auch schon vom std. ;)
=>
C++:
#include <cctype>
const bool isloweralpha(int c) { return std::isalpha(c) && std::islower(c); }

ähh deine beiden de u. encrypt-funktionen kann man komplett verändern ^^ beschreib einfach mal was du da haben willst ^^

C++:
if(Text.size()>KeyWord.size())
		{
		int i=0;
		do
		{
			KeyWord+=KeyWord[i];
			i++;
		}
		while(KeyWord.size()!=Text.size());
		}
...
C++:
for (std::size_t i(0); KeyWord.size() < Text.size(); ++i) KeyWord.append(KeyWord[i]);
Aber du benutzt diesen Teil ja später nochmal und solltest deswegen evtl. einfach hingehen und ne Funktion drauß machen ;)
C++:
void copy_fill(std::string& str, const std::size_t size)
{
    for (std::size_t i(0); str.length() < size; ++i) str.append(str[i]);
}

C++:
if(file.is_open())
		{
			while(!file.eof())
			{
				file << DeCrypted << endl;
				file << "naechster Teil: " << endl;
				file.close();		
			}
		}
eh warum sollte nen eof-Flag gesetz werden?!
C++:
{
    std::ofstream file_stream("file.dat");
    if (!file_stream) return false;
    file_stream << DeCrypted << "\nnächster Teil: "<< std::endl;
}

C++:
std::system("pause");
return 0;
Beides weglassen ;) ggf. durch std::cin.ignore(); ersetzen.
 
Zuletzt bearbeitet:
Hi.

Zu dem was devDevil bereits sagte, ist mir nur noch folgendes aufgefallen:
Code:
		cout << "Please enter the crypted code, which has to be decrypted!";
		cin >> Text;
		DeCrypted=Text;
		cout << endl << "Now please enter the used keyword! (consisting of letters a to z)" << endl;
		cin >> KeyWord;
		DeCrypted = Text;
Hier liest du die Eingabe in die Variable Text ein. Den String kopierst du dann von Text nach DeCrypted. Nachdem du KeyWord eingelesen hast, kopierst du dann nochmal den String von Text nach DeCrypted. Gibt es dafür einen Grund nicht einfach gleich
C++:
cin >> DeCrypted;
zu schreiben?

Code:
if(Text.size()>KeyWord.size())
		{
		int i=0;
		do
		{
			KeyWord+=KeyWord[i];
			i++;
		}
		while(KeyWord.size()!=Text.size());
Warum verwendest du hier nicht einfach eine kopfgesteuerte Schleife?

Außerdem prüfst du keine deiner Eingaben ob diese überhaupt erfolgreich waren. Das könntest du noch verbessern.

Gruß
 
eh warum sollte nen eof-Flag gesetz werden?!
C++:
{
    std::ofstream file_stream("file.dat");
    if (!file_stream) return false;
    file_stream << DeCrypted << "\nnächster Teil: "<< std::endl;
}

also mit eof dass das sinnlos war ist mir auch klar, ich hatte nur vergessen es später wegzumachen ^^

So dann noch wegen der De-und Encrypt-Funktion. Ich wollte es eigentlich nicht mit char-Eingaben und Ausgaben machen, da es wenn es mit Strings arbeiten würde natürlich schneller wäre (weil man ja nicht so oft wie der String lang ist, eine Funktion aufrufen müsste, was denke ich mal schon enorm Zeit kostet). Ein weiterer Punkt war, De- und Encrypt anfangs komplett anders gearbeitet hatten, aber es einfach nicht funktionieren wollte. Irgendwann ist mir dann diese int(char(int)-/+Verschiebung)-Sache eingefallen. Der erste Weg war aber anders. Ich beschreib das hier mal kurz in Codeschreibweise :D anhand von der Funktion Encrypt.

C++:
string encrypt(string EnteredText, char ChosenAlphabet)
{
int Alphabet = int(ChosenAlphabet)-97;
string Encrypted;
Encrypted=EnteredText; // zwecks gleicher Länge

for (int i=0; i<EingabeStringlänge; i++) //hab jetzt mal die Funktion weggelassen zur Stringlänge
{
	for(int k=97; k<=122; k++)
	{
		if (EnteredText[i]==(char(k))
		{
			if(Alphabet+k)>122)
			{
				Encrypted[i]=char(97+(k+Alphabet)-122))
			}
			else
			{
				Encrypted[i]=char(k+Alphabet)
			}
		}

	}
        return Encrypted;
}

natürlich hat das hier nicht funktioniert, bzw. nur halb, weil der Übertrag mir Probleme bereitet hat. Auch die Version, dass Alphabet mit 1 beginnt hat nicht funktioniert (natürlich mit angepassten Bedingungen und allem).

Dann noch zu dem mit Decrypted = Text: dass die Anweisung da 2 mal steht war mein Fehler, ich hatte da was probiert, wo ich den gesamten Code ausgeschnitten hatte und verschoben an eine andere Stelle und da ist wohl diese Anweisung ausversehen kopiert worden. :D. Natürlich gibt es keinen Grund nicht einfach gleich cin >> Crypted zu schreiben ^^, außer dass ich denke es ist blöd, wenn der entschlüsselte Text mit Variablennamen Crypted eingegeben wird, was ich ziemlich unlogisch finde ^^

@devDevil So nun hab ich mich noch über size_t informiert, weil ich es nicht kannte. Du nimmst das immer als Typ wenn du weißt, dass deine Zählvariable nicht größer als die Daten eines unsigned Int werden in Zählschleifen oder was ist der Grund dafür? Und das Initialisieren mit der Klammer i(0) würde mich auch mal interessieren, gibt es da nen bestimmten Grund für oder ist das einfach Gewohnheit ?

Und ich hab bei dir denk ich nen Fehler entdeckt, denn str.append(str[ i ]) funktioniert nicht, weil append keinen Konstruktor besitzt, der Char verarbeiten kann, ich hab mit der Referenz herausgefunden, dass es einen Konstruktor gibt, der mit Char arbeitet, allerdings muss man da die Anzahl angeben wie oft der Char angehangen wird, also hab ich den Aufruf verändert in: str.append(1,str[ i ]). Ich hoffe, dass dieser Weg der richtige war ^^

Grüße und vielen Dank für das Stück-für-Stück-Auseinandernehmen von diesem "tollen" Programm ;)
 
Zuletzt bearbeitet:
Jetzt weiß ich was du da machen wolltest :D Du könntest der einfachheit halber dir mal Module angucken ;)

Nja std::size_t ist eh http://www.cplusplus.com/reference/clibrary/cstddef/size_t.html ...

C++:
std::string encrypt(std::string const& string, const char key)
{
    std::string tmp(string.length(), 0);
    std::string::iterator step(tmp.begin());
    for (std::string::const_iterator it(string.begin()); it != string.end(); ++it)
    {
        if (std::isalpha(*it) && std::islower(*it)) *step = 'a' + (*it - 'a' + key) % ('z' - 'a' + 1);
        ++step;
    }
    return tmp;
}
so eh das Prinzip ist dabei einfach, dass man hingeht und 'a' -> 0 setzt, dann um key verschiebt, guckt ob man außerhalb des Alphabets ist (Module-Operator | 26 Zeichen des Alphabets) und zu letzt schiebt man alles wieder bis zum 'a' ;)

Eh und nu erweitern wir das ganze mal auf groß u. klein buchstaben:
C++:
std::string encrypt(std::string const& string, const char key)
{
    std::string tmp(string.length(), 0);
    std::string::iterator step(tmp.begin());
    const char* alpha("aA");
    for (std::string::const_iterator it(string.begin()); it != string.end(); ++it)
    {
        if (std::isalpha(*it)) *step = alpha[std::isupper(*it)] + (*it - alpha[std::isupper(*it)] + key) % 26;
        ++step;
    }
    return tmp;
}
und weiter geht's mit Zahlen!
C++:
std::string encrypt(std::string const& string, const char key)
{
    std::string tmp(string.length(), 0);
    std::string::iterator step(tmp.begin());
    const char* begin("aA0");
    const char* end("zZ9");
    const char* current(NULL);

    for (std::string::const_iterator it(string.begin()); it != string.end(); ++it)
    {
        if (!std::isalpha(*it) && !std::isdigit(*it)) { ++step; continue; }
        
        const unsigned char type(!std::isalpha(*it) ? 2 : std::isupper(*it)); 
        *step++ = begin[type] + (*it - begin[type] + key) % (end[type] - begin[type] + 1);
    }
    return tmp;
}
:P sooo den rest machse selber ;)
 
Der lustige Vigenere. Als weiter Übung kannst du dich dann mit Entschlüsselungsalgorithmen beschäftigen. Kasiski hat noch eine schöne Substringsuche zu bieten, sowie die Sortierung von Arrays und der Friedmann-Test eine nette Formel zum Implementieren. Ist auf jeden Fall eine gute zusätzliche Übung...nur für den Fall dass du dein kleines Programm weiter ausbauen magst ;)
 
Der lustige Vigenere. Als weiter Übung kannst du dich dann mit Entschlüsselungsalgorithmen beschäftigen. Kasiski hat noch eine schöne Substringsuche zu bieten, sowie die Sortierung von Arrays und der Friedmann-Test eine nette Formel zum Implementieren. Ist auf jeden Fall eine gute zusätzliche Übung...nur für den Fall dass du dein kleines Programm weiter ausbauen magst ;)

auf jeden Fall, da hab ich wenigstens mal was Handfestes, worüber ich mich freuen kann, ich bin doch jetzt nicht so blöd und fang nen neues Programm an, wo ich mich wieder dumm und dämlich ärgere, außerdem find ich Ver-und Entschlüsselung ziemlich interessant, und ich möchte mich hier in aller Öffentlichkeit für die Verunglimpfung von Vignere's Namen entschuldigen, wie man am Thread-titel leicht erkennen kann. Ich war in Eile, tut mir Leid Monsieur Vigenère ;)
 
So is recht...Respekt denen Respekt gebührt.

Wenn dich das interessiert, kann ich dir Simon Singhs Buch "Geheime Botschaften" empfehlen. Einer meiner Lieblingsautoren und er erzählt die Geschichte der Kryptografie mit allen Ver- und Entschlüsselungsalgorithmen, die im Laufe der Zeit wichtig und interessant waren.
Oder du schaust dir auf seiner Homepage den Bereich über Verschlüsselung an (CryptoCorner oder so ähnlich). Dort gibt es Contests zur Ver- und Entschlüsselung (gibt's übrigens für Enigma verschlüsselte Texte auch im Netz), Anleitungen, Texte, Algorithmen, Tutorials, (gratis) CDs zum Download, etc.

Noch viel Spass!
 
so das wäre es erstmal, hoffe, dass alles stimmt und würde mich natürlich erneut über Tipps und Tricks freuen..
lg

Code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cctype>


std::string Encrypt(std::string EnteredText,std::string Keyword);
std::string Decrypt(std::string EnteredText,std::string Keyword);
void CopyFill(std::string&,const size_t);
bool IsAlpha(std::string TestString);
bool SaveData(std::string TextToSave);

//tests a whole string with the std::isalpha method (needs "#include cctype" for usage)
bool IsAlpha(std::string TestString)
{
	bool Exit = false;
	for(size_t i(0); i<TestString.size();i++)
	{
		if(std::isalpha(TestString[i]))
		{Exit=true;}else{Exit=false;}
	}
	return Exit;
}

std::string Encrypt(std::string Text, std::string Keyword)
{
	std::string Tmp(Text.begin(),Text.end());
	std::string::iterator Step(Tmp.begin());
	const char* Begin("aA0");
	const char* End("zZ9");
	char KeywordType;
	size_t KeywordPos=0;
	for (std::string::const_iterator It(Text.begin()); It!= Text.end(); ++It)
	{
		if(!std::isalpha(*It) && !std::isdigit(*It)){++Step; continue;} //step over if no alphabetical sign or digit
		const unsigned char Type(!std::isalpha(*It) ? 2 : std::isupper(*It)); //make a difference between upper-and lowercase
		if(Keyword[KeywordPos]>'a')
		{
			KeywordType = Keyword[KeywordPos] - 'a'; //if Keyword was in lowercase letters 
		}else
		{
			KeywordType = Keyword[KeywordPos] - 'A';// if Keyword was in uppercase letters
		}
		*Step++ = Begin[Type] + ((*It - Begin[Type] + KeywordType) % (End[Type] - Begin[Type])); //the current symbol in enteredText is analyzed and converted to the favourite alphabet.
		++KeywordPos; //next symbol in Keyword is prepared for the for-to construct
	}
	return Tmp;
}

std::string Decrypt(std::string Text, std::string Keyword) 
{
	std::string Tmp(Text.begin(),Text.end()); 
	std::string::iterator Step(Tmp.begin());
	const char* Begin("aA0");
	const char* End("zZ9");
	char KeywordType;
	size_t KeywordPos=0;
	for (std::string::const_iterator It(Text.begin()); It!= Text.end(); ++It)
	{
		if(!std::isalpha(*It) && !std::isdigit(*It)){++Step; continue;}
		const unsigned char Type(!std::isalpha(*It) ? 2 : std::isupper(*It));
		if(Keyword[KeywordPos]>='a')
		{
			KeywordType = Keyword[KeywordPos] - 'a';
		}
		else
		{
			KeywordType = Keyword[KeywordPos] - 'A';
		}
		*Step++ = Begin[Type] + ((*It - Begin[Type] - KeywordType) % (End[Type] - Begin[Type])); //only difference between encrypt is the minus before KeywordType.
		++KeywordPos;
	}
	return Tmp;
}

//fills the Keyword when the text is to long, so both strings have the same length
void CopyFill(std::string& Str, const std::size_t Size)
{
	for(std::size_t i(0); Str.length()<Size;i++)Str.append(1,Str[i]);
}

//saves the cipher or the cleartext in a text-file
bool SaveData(std::string TextToSave)
{
	std::ofstream FileStream("file.dat");
	if(!FileStream)return false;
	FileStream << TextToSave << "\nnext part: " << std::endl;
	FileStream.close();
	return true;
}

int main()
{
	std::cout << "Welcome!" << std::endl;
	std::cout << "Please enter text, which has to be decrypted/encrypted!" << std::endl;
	std::string EnteredText;
	std::cin >> EnteredText;
	std::cout << std::endl << "Now please enter the keyword! (consisting of letters a to z/A to Z)" << std::endl;
	std::string Keyword;
	do
	{
		std::cout << "Only letters please!" << std::endl;
		std::cin >> Keyword;
	}
	while(!(IsAlpha(Keyword)));
	std::cout << "Please chose either code [d]ecryption or code [e]ncryption\n";
	char Chosen;
	std::cin >> Chosen;
	while (((Chosen!='d')&&(Chosen!='D'))&&((Chosen!='e')&&(Chosen!='E')))
	{
		std::cout << "only e and d are allowed!" << std::endl; 
		std::cin >> Chosen;
	}
		if(EnteredText.size()>Keyword.size())CopyFill(Keyword,EnteredText.size());
		if(Chosen=='d')
		{
			EnteredText=Decrypt(EnteredText,Keyword);
		}
		else
		{
			EnteredText=Encrypt(EnteredText,Keyword);
		}
		SaveData(EnteredText);
		std::cin.ignore();
}
 
Zuletzt bearbeitet:
Zurück