2016-09-02 45 views
2

文字列をファイルに暗号化して解読して戻す、かなり簡単な方法を実装しました。C++による排他的論理和

string encrypt(string msg, string key) { 
    string tmp(key); 
    while (key.size() < msg.size()) key += tmp; 
    for (std::string::size_type i = 0; i < msg.size(); ++i) msg[i] ^= key[i]; 
    return msg; 
} 

string decrypt(string msg, string key) { 
    return encrypt(msg, key); 
} 

は、しかし、私が使用しているキーの一部は、非常に有用ではありません: 方法は、以下のような外観を使用してイム。文字列は正しく暗号化され、ファイルに書き込まれます。しかし、すべてを解読しようとすると(ファイルを文字列に読み込み、解読し、別のファイルに書き戻す)、新しいファイルはかなり小さくなり、そこに保存されている情報全体を含んでいません。私がこれまで試した

キーは、次のとおりです。私はあなたが私を助け、私に使用可能なキーを選択する方法上の任意のアドバイスを与えることができ

string crypt = "abc";       //works kinda well 
string crypt = "_H84M!-juJHFXGT01X1*G6a$gEv"; //doesnt work 
string crypt = "H84MjuJHFXGT01X1G6agEv";  //doesnt work either 

期待しています。

ファイルの処理のためのコード:あなたが書きたいことがあり

ofstream os(...); 
std::string encrypted = ...; 
os.write(encrypted.data(), encrypted.size()); 

注:あなたが暗号化された文字列内のバイナリデータを持っていたよう

ofstream temp; 
temp.open("temp", ios::in | ios::trunc); 
temp << encrypt(buffer, crypt); 
temp.close(); 


ifstream in(file); 
string content((std::istreambuf_iterator<char>(in))    (std::istreambuf_iterator<char>())); 
ofstream plain; 
plain.open(newfile, ios::in | ios::trunc); 
plain << decrypt(content, crypt); 
plain.close(); 
+3

暗号化された文字列でバイナリ0を取得し、バイナリ0文字で終了する文字列を期待する 'C'文字列関数を使用することを期待します。これにより、暗号化されたデータが切り捨てられます。 –

+1

ファイルに読み書きするためのコードを表示します。 – Nelfeal

+8

キーを増やしてナンセンスの代わりに 'msg [i]^= key [i%key.size()];を使うだけです。 – Slava

答えて

1

あなたの回答とコメントのすべてが正しい方向に私を指摘してくれましたが、私のプログラムで直接働いていませんでした。

まず、Slavaが提案した方法で暗号化アルゴリズムを変更しました。次に、ファイルの取り扱いを変更しました。新しい方法では、暗号化されたファイルの全長が取得され、charの配列を介して各文字が強制的に新しい文字列に変換されます。私はこれはかなり可愛いが、私は文字列型のコード全体を保持することができます知っている。

だから私は、次のを思い付いた:

ifstream in(file, ios::binary); 
in.seekg(0, ios::end);    // go to the end 
int length = in.tellg();   // report location (this is the length) 
in.seekg(0, ios::beg);    // go back to the beginning 
char* content = new char[length]; // allocate memory for a buffer of appropriate dimension 
in.read(content, length);   // read the whole file into the buffer 
string content2 = ""; 
for (int i = 0; i < length; i++) con31 += con3[i]; //append to string character by character 
ofstream plain; 
plain.open(newfile, ios::in | ios::trunc); 
plain << decrypt(content2, crypt); 
plain.close(); 

これは私のためにかなりよく働きます。私は重い間違いを犯してはいけないと思っています。

2

すると、あなたがフォーマットされていないwrite方法の代わりに、operator<<を使用する必要がありますファイルに複数の暗号化された文字列が必要な場合は、実際のデータよりも前のデータサイズ。その後、istream::read()とデータサイズやデータを読み込む:

void write(std::ostream &out, const std::string &encrypted) 
{ 
    size_t length = encrypted.size(); 
    of.write(&length, sizeof(length)); 
    of.write(encryped.data(), length); 
} 

std::string read(std::istream &in) 
{ 
    size_t length = 0; 
    in.read(&length, sizeof(length)); 
    std::string str(length); 
    in.read(&str[0], length); 
    return str; 
} 

注2:代わりにstd::stringstd::vector<char>で暗号化されたデータを保存するために良いアイデアかもしれない、多くの問題を防ぐことができます - あなたは多くを使用することができません暗黙的に文字列がヌル終端であると仮定する関数。

+0

...なぜですか? @ArtjomB。 –

+0

'<<"演算子は '\ 0'で停止するためです。 'std :: cout <<" a \ 0b ";'を試してください。 – Nelfeal

+0

@Nelxiostそうかもしれませんが、これは答えに含める必要があります。それ以外の場合はあまり役に立ちません。 –

2

私はちょうど完全で、最小限の作業例を書いています。

#include <fstream> 
#include <iostream> 
#include <string> 

static std::string str_xor(const std::string &data, const std::string &key) { 
    std::string result(data.size(), '\0'); 

    for (std::size_t i = 0, i < data.size(); i++) { 
    result[i] = data[i]^key[i % key.size()]; 
    } 
    return result; 
} 

int main(int argc, char **argv) { 
    if (argc != 3) { 
    std::cerr << "usage: xor <datafile> <keyfile>\n"; 
    return 1; 
    } 

    std::ifstream data_in(argv[1]); 
    std::string data(
    (std::istreambuf_iterator<char>(data_in)), 
    (std::istreambuf_iterator<char>())); 
    data_in.close(); 

    std::ifstream key_in(argv[2]); 
    std::string key(
    (std::istreambuf_iterator<char>(key_in)), 
    (std::istreambuf_iterator<char>())); 
    key_in.close(); 

    std::string result = str_xor(data, key); 

    std::ofstream data_out(argv[1]); 
    data_out << result; 
    data_out.close(); 

    return 0; 
} 

ファイルが見つからない場合にもエラーチェックが行われません。しかし、既存の2つのファイルの名前を渡すと、2番目のファイルをキーとして最初のファイルを暗号化して魅力的に機能します。

注意:https://codereview.stackexchange.com/a/140366で示された優秀な理由により、このプログラムを実際には使用しないでください。

+0

おそらく、 'std :: string result(a);を使用してください。 ... result [i]^= b [i%b.size()]; ' – chux

+0

なぜですか? 'a'をコピーするとメモリアクセスが増えることになります。確かに、それはソースコードに数バイトを節約しますが、実行時には遅いと思います。 –

関連する問題