C言語関係掲示板

過去ログ

No.945 初歩的な暗号化プログラムについて

[戻る] [ホームページ]
No.12032

初歩的な暗号化プログラムについて
投稿者---Kazu(2004/01/22 13:54:06)


セキュリティについて勉強するための準備として、簡単な暗号化プログラムを作ることになったので自力でどうにか書き上げたのですが、思うように動作してくれないので、助言をしていただけるとありがたいです。

作るプログラムとしては「キーボードから入力された文章をファイルに保存する。しかし、保存したファイルをエディタなどで開いたときに元の文章が人間の目で直接読み取られないように暗号化すること。」と言うものです。

下のプログラムのアルゴリズムとしては、入力された文字をバッファに読み込んで、バッファの中身を0x01ずつずらしてファイルに出力しようとしたものです。実行すると確かに、文字化けして読めなくはなっているのですが、予想した文字のずれ方と違い、元の文章に再生することができないくらいの変な文字になってしまいます。環境としてはWindowsXP proです。
予想ではアスキーコードの文字が0x01分ずれるので、B→A、n→mのようになると思っていたのですが…


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define OUT "output.txt"    //通常出力ファイル
#define SOUT "secret.txt"  //暗号化出力ファイル
#define BUF 1024              //バッファ長

int main(void) {
  FILE *fp, *sfp;
  char buf[BUF];
  int i;

  /* 出力用ファイルをモードa+でオープンする */
  if((fp = fopen(OUT, "a+")) == NULL) {
    printf("file open error!");
    exit(1);
  }
  if((sfp = fopen(SOUT, "a+")) == NULL) {
    printf("file open error!");
    exit(1);
  }

  /* 入力を求める */
  printf(">If you'd like to finish, Press only Return-key.\n");
  while(1) {
    fgets(buf, sizeof(buf), stdin);    //入力された文字を1行ずつバッファに読み込む
    if(!strcmp(buf, "\n")) break;     //\nのみが入力された場合はループを抜け実行を終える
    fputs(buf, fp);      //バッファの値をそのままファイルに出力する
    for(i = 0; i < BUF; i++) buf[i] -= '0x01';  //バッファの中身を全て0x01分だけ値をずらす
    fputs(buf, sfp);          //ずらした値をファイルに出力する
  }
  fclose(fp);
  fclose(sfp);
  return 0;
}


No.12033

Re:初歩的な暗号化プログラムについて
投稿者---NykR(2004/01/22 15:09:15)


for(i = 0; i < BUF; i++) buf[i] -= '0x01'; //バッファの中身を全て0x01分だけ値をずらす

buf配列の中身を全てずらすのはまずいです。入力文字列末尾のナル文字が消えるので。

それから、0x01分ずらすのと'0x01'分ずらすのとは違います。っていうか警告がでると思うんですが?



No.12055

ありがとうございました
投稿者---Kazu(2004/01/22 23:48:04)


ありがとうございました。皆さんのご指摘のおかげでうまく動作してくれました。
ついでにお聞きしたいのですが、

>それから、0x01分ずらすのと'0x01'分ずらすのとは違います。っていうか警告がでると思うんですが?

この違いとは何なんですか??  ちなみに警告は出ないんですけど…



No.12065

Re:ありがとうございました
投稿者---YuO(2004/01/23 09:27:09)


>>それから、0x01分ずらすのと'0x01'分ずらすのとは違います。っていうか警告がでると思うんですが?
>この違いとは何なんですか??  ちなみに警告は出ないんですけど…

整数定数と文字定数の違いはわかっていますか?
0x01は値1を持ちますが,'0x01'は処理系定義の値を持ちます。

私の手持ちの処理系で試すと,
Borland C++ 5.5.1 for Win32
0x31307830
Digital Mars Compiler Version 8.35n
0x30783031
Microsoft(R) 32-bit C/C++ Standard Compiler Version 13.00.9466 for 80x86 (.Net Framework SDK / VC++.Net 2002)
0x30783031
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 11.00.7022 for 80x86 (Visual C++ 5)
0x30783031
Open Watcom C/C++32 Compile and Link Utility Version 1.1
0x30783031

のような値が得られました。

たまたまBCC以外は一致しましたが,処理系定義の値ですからどちらが正解ということはなく,
さらに'0'に一致した値(これらの処理系では0x30)や'1'に一致した値(同じく0x31)などでも正しいことになります。


No.12084

Re:ありがとうございました
投稿者---Kazu(2004/01/23 20:42:36)


>たまたまBCC以外は一致しましたが,処理系定義の値ですからどちらが正解ということはなく,
>さらに'0'に一致した値(これらの処理系では0x30)や'1'に一致した値(同じく0x31)などでも正しいことになります。

丁寧に説明していただいてありがとうございました。
なんとなくですが理解しました。せっかく説明していただいたのに私の知識不足のために、すみません…

No.12034

Re:初歩的な暗号化プログラムについて
投稿者---おでん(2004/01/22 15:12:18)


for(i = 0; i < BUF; i++) buf[i] -= '0x01'; //バッファの中身を全て0x01分だけ値をずらす

これでは、ずれませんね?
同じことをするなら、単純に1を引けばいいだけかと思いますが?
=> buf[i]-- ;


No.12035

Re:初歩的な暗号化プログラムについて
投稿者---namani(2004/01/22 15:25:30)


ついでですが、

>for(i = 0; i < BUF; i++)
だと文字列の終端や後半のゴミもいじって出力してしまうような。
あとfgetsでとった改行も1引いてしまいますね。
ほかにスペースとか入ってると怪しげですね。

int length=0;
(略)
length = strlen(buf); // 改行も残すなら-1する
for(i = 0; i < length; i++)
buf[i]--;

#strlenの戻り値はunsigned intかintか・・・忘れました
#キャストする必要まではないかな?


No.12036

Re:初歩的な暗号化プログラムについて
投稿者---NykR(2004/01/22 15:45:44)


for (i = 0; buf[i] != '\0'; i++)
でよいのでは?

読めない文字に変換されるのがいやなら
1引いた後isgraphか何かで判定して問題があれば戻す。と。


>#strlenの戻り値はunsigned intかintか・・・忘れました

size_t型ですね。



No.12037

Re:初歩的な暗号化プログラムについて
投稿者---NykR(2004/01/22 15:50:20)


>size_t型ですね。

typedefする前の型が分からないので、lengthは最初からsize_tで宣言しておくのが良いと思います



No.12062

Re:初歩的な暗号化プログラムについて
投稿者---RAPT(2004/01/23 01:35:31)


>>size_t型
size_t型は、sizeof演算子が返す型であったと記憶していますが、
strlen()の型は、size_t でしたっけ?

No.12064

Re:初歩的な暗号化プログラムについて
投稿者---YuO(2004/01/23 09:14:38)


>>>size_t型
>size_t型は、sizeof演算子が返す型であったと記憶していますが、
>strlen()の型は、size_t でしたっけ?

size_tです。

strlenは
#include <string.h>
size_t strlen (const char * s);

という形式を持ちます。


No.12088

Re:初歩的な暗号化プログラムについて
投稿者---RAPT(2004/01/23 21:46:39)


YuOさん、ありがとうございます。
そういえば、そうですね。
VC++の、CString::GetLength()とで、混乱したようです。