文字列のバイナリ化

[戻る]
GG 2007/07/12(木) 08:39:28
いつもお世話になっています。GGです。

データをfwrite(...)で保存しています。
データの一部は文字列があります。
例:
123,3334,QQQ,RRRR,4444
...
というデータです。

保存結果は文字部分がバイナリ化していない。
(テキストファイルとして開くと文字列がそのままで表示されています)

文字列のバイナリ化したいのですが、
いい方法があるのでしょうか。
(ファイルの暗号化以外の方法)

よろしくお願いします。

環境:.Net(2002) MFC使用、Win2000

tetrapod 2007/07/12(木) 09:04:48
テキストファイルってのは「可視な文字だけでなるバイナリファイル」なんだから
(可視)文字コードをそのまま fwrite したらエディタで見えるのは当然の話。

暗号化で無くバイナリ化とは何を意図しているのか?
本当にしたいのは暗号化なのでは?

GG 2007/07/12(木) 10:01:43
tetrapodさん、
ご返事ありがとう.

>テキストファイルってのは「可視な文字だけでなるバイナリファイル」なんだから
>(可視)文字コードをそのまま fwrite したらエディタで見えるのは当然の話。

そうですか、わかりました。

>暗号化で無くバイナリ化とは何を意図しているのか?
自分で決まったフォマットを公開したくないことです。

>本当にしたいのは暗号化なのでは?
本当にはファイルを暗号化にしたいのですが、時間がなくて、
(暗号化について知識がないため)
一応簡単にバイナリして、(フォマットを公開したくないことです)
データを他人に渡すこと。

そういう目的のですが、何か簡単な方法があれば教えてください。

よろしくお願いします。

επιστημη [HomePage] 2007/07/12(木) 10:19:26
ぱっと見なにがなんだかわかんなくするだけなら、
たとえば各ビットの1/0をひっくり返して書き/読みます。

momo 2007/07/12(木) 10:30:44
>本当にはファイルを暗号化にしたいのですが、時間がなくて

BlowFishを使えば簡単に暗号化できますよ。
検索すれば、簡単に解説サイトに辿り着けます。

オレンジフィッシュ 2007/07/12(木) 17:57:56
擬似乱数を使って XOR をとるのはどう?

char str[] = "123,3334,QQQ,RRRR,4444";
int i, len = strlen(str);

// 乱数で暗号化
RandInit( 初期値 );
for ( i = 0 ; i < len ; i++ ){
 str[ i ] = (char)(str[i] ^ Rand());
}
fwrite( str, len, 1, fp );

Rnad() は自作の擬似乱数で適当な数式より 0〜255 が発生するようにしておく。
復元は同じ Rand() を使って暗号化と同じ処理を文字列の長さ分だけ行えばよい。
なお Rand() の乱数が暗号化したときと同じ数から乱数を発生できるように
RandInit() も用意して初期値を設定できるようにしておくこと。
そうしないと正常に復元できない。

// 同じ乱数で復元
char buff[文字列長 + 1];

fread( buff, 文字列長, 1, fp );
RandInit( 初期値 );
for ( i = 0 ; i < 文字列長 ; i++ ){
 buff[ i ] = (char)(buff[i] ^ Rand());
}
buff[i] = '\0';
printf( "復元:[%s]\n", buff );

yoh2 [E-Mail] 2007/07/13(金) 23:40:17
望みの暗号化のレベルは以下のどちらでしょうか?

1. ぱっと見、分かりにくくしたいが、解読されてしまっても別に構わない。(スタンドアローンゲームの
セーブデータとか)
2. 解読されることは可能な限り避けたい。

1なら既出のビット反転等の方法で十分事足りると思います。

2の場合は難しいですね。そういった必要性に迫られたこともないため、よい方法を思い付きません。
既出の例だとBlowfish、他の有名所ではAESや3DESのような本格的な暗号化アルゴリズムを利用すること
になると思いますが、秘密鍵の管理が難しいです。
下手にプログラム中でハードコーディングでもしようものなら、並レベルのクラッカーにあっさり解析され
て1と同じレベルに堕ちてしまいますので。

GG 2007/07/14(土) 05:55:07
επιστημηさん、momoさん、オレンジフィッシュさん、yoh2さん
コメントありがとう。

(επιστημηさんから)
>たとえば各ビットの1/0をひっくり返して書き/読みます。

(オレンジフィッシュさんから)提示した例と同じことですね。

(momoさんから)
>BlowFishを使えば簡単に暗号化できますよ。
>検索すれば、簡単に解説サイトに辿り着けます

ざっと見ました、時間があったら、やろうと思っています。
(BlowFishということが知らなかった。情報ありがとう。)

(オレンジフィッシュさんから)
提示した例、ほんとにありがとうございました。

その例を見ながら、やってみました。
問題がなくうまくできました。

でも、構造体の場合もやってみました。
一つの問題があります。
例:
    struct DFMData {
        int  DfmLaye;            // 文字のLaye
        int  DfmBcode;            // 文字のBcode
        int  DfmType;            // 文字のType
        char DfmName[STR_NAME2];        // 文字のName
        int  DfmSize;            // 文字のSize
        int  DfmWide;            // 文字のWide
        long DfmColor;            // 文字のColor
        int  DfmArrange;        // 文字の配置
        int  TextDfmDraw_flag;    // 文字の表示非表示
    };
       DFMData DFMData_Savedata;

GG 2007/07/14(土) 05:55:06
επιστημηさん、momoさん、オレンジフィッシュさん、yoh2さん
コメントありがとう。

(επιστημηさんから)
>たとえば各ビットの1/0をひっくり返して書き/読みます。

(オレンジフィッシュさんから)提示した例と同じことですね。

(momoさんから)
>BlowFishを使えば簡単に暗号化できますよ。
>検索すれば、簡単に解説サイトに辿り着けます

ざっと見ました、時間があったら、やろうと思っています。
(BlowFishということが知らなかった。情報ありがとう。)

(オレンジフィッシュさんから)
提示した例、ほんとにありがとうございました。

その例を見ながら、やってみました。
問題がなくうまくできました。

でも、構造体の場合もやってみました。
一つの問題があります。
例:
    struct DFMData {
        int  DfmLaye;            // 文字のLaye
        int  DfmBcode;            // 文字のBcode
        int  DfmType;            // 文字のType
        char DfmName[STR_NAME2];        // 文字のName
        int  DfmSize;            // 文字のSize
        int  DfmWide;            // 文字のWide
        long DfmColor;            // 文字のColor
        int  DfmArrange;        // 文字の配置
        int  TextDfmDraw_flag;    // 文字の表示非表示
    };
       DFMData DFMData_Savedata;

GG 2007/07/14(土) 06:32:40
επιστημηさん、momoさん、オレンジフィッシュさん、yoh2さん
コメントありがとう。

(επιστημηさんから)
>たとえば各ビットの1/0をひっくり返して書き/読みます。

(オレンジフィッシュさんから)提示した例と同じことですね。

(momoさんから)
>BlowFishを使えば簡単に暗号化できますよ。
>検索すれば、簡単に解説サイトに辿り着けます

ざっと見ました、時間があったら、やろうと思っています。
(BlowFishということが知らなかった。情報ありがとう。)

(オレンジフィッシュさんから)
提示した例、ほんとにありがとうございました。

その例を見ながら、やってみました。
問題がなくうまくできました。

でも、構造体の場合もやってみました。
一つの問題があります。
例:

#define STR_NAME2     65        //Name

    struct DFMData {
        int  DfmLaye;            // 文字のLaye
        int  DfmBcode;            // 文字のBcode
        int  DfmType;            // 文字のType
        char DfmName[STR_NAME2];        // 文字のName
        int  DfmSize;            // 文字のSize
        int  DfmWide;            // 文字のWide
        long DfmColor;            // 文字のColor
        int  DfmArrange;        // 文字の配置
        int  TextDfmDraw_flag;    // 文字の表示非表示
    };
    DFMData DFMData_Savedata;

for(int j=0; j<30; j++){
 DFMData_Savedata.DfmLaye    = mp_TextDfmSct[j].DfmLaye; 
 FMData_Savedata.DfmBcode    = mp_TextDfmSct[j].DfmBcode;
…
 strcpy(DFMData_Savedata.DfmName, mp_TextDfmSct[j].DfmName);    //名称

 DFMData_Savedata.DfmSize    = mp_TextDfmSct[j].DfmSize;
 DFMData_Savedata.DfmWide    = mp_TextDfmSct[j].DfmWide;
…

                                   //mp_TextDfmSct[j].DfmLayeは配列です

//問題ここから
 int len = strlen(DFMData_Savedata.DfmName);
  for (int ik=0; ik<len; ik++){
   DFMData_Savedata.DfmName[ik] = 
         (char)(DFMData_Savedata.DfmName[ik] ^ randValue[ra_i]);
   ra_i++;
 }
  fwrite(&DFMData_Savedata, sizeof(DFMData_Savedata), 1, fp9);
}
...

問題:
以上のコードですが、一回目(全体)を実行すると、ちゃんと正しく変換できました。
2回目以降、一部変換ができませんでした。
変換できない部分を見つかりました。

   DFMData_Savedata.DfmName[ik] = 
         (char)(DFMData_Savedata.DfmName[ik] ^ randValue[ra_i]);
の前後の文字列が調べた、
変換前 文字列の長さ=22です。
変換後 文字列の長さ=13です。

文字列が変わったということです。
(randValue[ra_i]);は暗号と複号するとき同じ数値を使っています。)
mp_TextDfmSct[j].DfmNameは可変長文字列です。

一体問題はどこでしょう。

説明を理解できるのでしょうか。

よろしくお願いします。

GG 2007/07/14(土) 06:39:35
追記

>   DFMData_Savedata.DfmName[ik] = 
         (char)(DFMData_Savedata.DfmName[ik] ^ randValue[ra_i]);
>の前後の文字列が調べた、
>変換前 文字列の長さ=22です。
>変換後 文字列の長さ=13です。
 int len = strlen(DFMData_Savedata.DfmName);
  for (int ik=0; ik<len; ik++){
   DFMData_Savedata.DfmName[ik] = 
         (char)(DFMData_Savedata.DfmName[ik] ^ randValue[ra_i]);
   ra_i++;
 }
 int len2 = strlen(DFMData_Savedata.DfmName);

len =22
len2 =13
len とlen2は一致していないです。

よろしくお願いします。

yoh2 [E-Mail] 2007/07/14(土) 13:10:47
暗号化部分だけでなく、復号部分のコードも見ないと確実なことが言えません。

以下推測。
暗号化部分のrandValueと復号部分のrandValue(相当の物)が異なっていたりしませんか?
暗号化部分では、ra_iの値は増えっぱなしですが、復号部分では構造体ひとつの復号が完了する度に0にリ
セットしているとか。

>  int len = strlen(DFMData_Savedata.DfmName);
>   for (int ik=0; ik<len; ik++){
>    DFMData_Savedata.DfmName[ik] = 
>          (char)(DFMData_Savedata.DfmName[ik] ^ randValue[ra_i]);
>    ra_i++;
>  }
>  int len2 = strlen(DFMData_Savedata.DfmName);
>
> len =22
> len2 =13
> len とlen2は一致していないです。

これは当たり前。'&#92;0'が暗号化によって'&#92;0'でなくなっていますから。
下手すりゃlen2の算出時にプログラムが落ちます。

# ところで、文字列部分しか暗号化していないようですが、その程度のものでよいのですか?

yoh2 [E-Mail] 2007/07/14(土) 13:12:11
またやっちゃった。いい加減学習せねば……

前回の投稿で、&#92; は '¥'または'\'と読み替えて下さい。

yoh2 [E-Mail] 2007/07/14(土) 13:18:15
ひとつ補足。

前投稿の最後の部分の説明は、len > len2となってしまう場合の説明になっていました。
GGさんの、len < len2となっているパターンは、途中(GGさんの例では14文字目)で
変換前のDFMData_Savedata.DfName[ik] == randValue[ra_i]がとなっていて、変換後にゼロにな
るからでしょう。

GG 2007/07/14(土) 15:23:21
yoh2さん、
ご返事ありがとう。

>これは当たり前。'&#92;0'が暗号化によって'¥\;0'でなくなっていますから。
>下手すりゃlen2の算出時にプログラムが落ちます。

暗号前のLenと暗号後のLen2は
1.Len=Len2
2.Len>Len2
3.Len<Len2
という三つの結果ですか、
1.Len=Len2は、最初一回目の結果です。
2.Len>Len2は、2回目以後の結果です。

必ずLen=Len2と思っていますが、これが間違っていますか?
もし間違っているなら、理由を教えてください。
('&#92;0'が暗号化によって'¥\;0'という理由ですか、
でも、私の場合、エラーの部分ですが、22個文字列ですが、13個目以前は
正常ですが、13目以後、変換していないようです。)


>暗号化部分のrandValueと復号部分のrandValue(相当の物)が異なっていたりしません
>か?
>暗号化部分では、ra_iの値は増えっぱなしですが、復号部分では構造体ひとつの復号が
>完了する度に0にリ
>セットしているとか。

一回目の暗号化部分と復号部分は正常に変換できました。
2回目は同じ関数でもう一度実行するということです。

># ところで、文字列部分しか暗号化していないようですが、その程度のものでよいので
>すか?
いいえ、一行の場合(構造体)どうやるのでしょうか。

よろしくお願いします。



よろしくお願いします。

GG 2007/07/14(土) 15:49:24
追記;
>22個文字列ですが、13個目以前は正常ですが
>13目以後、変換していないようです

22個文字列は暗号するとき、randValue[ra_i]は22個を使っています。
暗号後13個文字列になっています。
例
j=11 len=22
j=11 ik=0 randValue[55]=243
j=11 ik=1 randValue[56]=190
j=11 ik=2 randValue[57]=203
j=11 ik=3 randValue[58]=82
j=11 ik=4 randValue[59]=180
j=11 ik=5 randValue[60]=211
j=11 ik=6 randValue[61]=162
j=11 ik=7 randValue[62]=70
j=11 ik=8 randValue[63]=253
j=11 ik=9 randValue[64]=103
j=11 ik=10 randValue[65]=110
j=11 ik=11 randValue[66]=197
j=11 ik=12 randValue[67]=65    //[67]まで、正常です
j=11 ik=13 randValue[68]=188
j=11 ik=14 randValue[69]=103
j=11 ik=15 randValue[70]=77
j=11 ik=16 randValue[71]=16
j=11 ik=17 randValue[72]=202
j=11 ik=18 randValue[73]=172
j=11 ik=19 randValue[74]=221
j=11 ik=20 randValue[75]=104
j=11 ik=21 randValue[76]=129

j=11 len=13  //文字列13になっています。[68]〜[76]までは変換していないようで
す。

複号部分に13個文字列はrandValue[ra_i]の13個しか使っていないですが、
13個目以降randValue[ra_i]は次ぎの文字列を使っています。
暗号後と複号部のrandValue[ra_i]は一致していない。
例
i=11 len2=13
i=11 ik=0 randValue[55]=243
i=11 ik=1 randValue[56]=190
i=11 ik=2 randValue[57]=203
i=11 ik=3 randValue[58]=82
i=11 ik=4 randValue[59]=180
i=11 ik=5 randValue[60]=211
i=11 ik=6 randValue[61]=162
i=11 ik=7 randValue[62]=70
i=11 ik=8 randValue[63]=253
i=11 ik=9 randValue[64]=103
i=11 ik=10 randValue[65]=110
i=11 ik=11 randValue[66]=197
i=11 ik=12 randValue[67]=65  //[67]まで、正常です
               //次ぎの文字列(i=12)を使っています
i=12 ik=0 randValue[68]=188
i=12 ik=1 randValue[69]=103
i=12 ik=2 randValue[70]=77
i=12 ik=3 randValue[71]=16
i=12 ik=4 randValue[72]=202
i=12 ik=5 randValue[73]=172
i=12 ik=6 randValue[74]=221
i=12 ik=7 randValue[75]=104
i=12 ik=8 randValue[76]=129

よろしくお願いします。

yoh2 [E-Mail] 2007/07/14(土) 18:06:03
とりあえず目先の問題について。(後で根こそぎひっくり返しますが)

> 必ずLen=Len2と思っていますが、これが間違っていますか?
> もし間違っているなら、理由を教えてください。

あ、ごめん。最後の'\0'は変換しないから、len < len2となることはありませんね。
ただし、len > len2となることはあり得ます。理由はこれ。

> 変換前のDFMData_Savedata.DfName[ik] == randValue[ra_i]がとなっていて、
> 変換後にゼロになるからでしょう。

つまり、変換前に、j = 11のときのDFMData_Savedata.DfmName[13]がrandvaluel[68]と同じ183 
(charなら-68かな? Shift_JISと仮定すると半角の'シ')だったりするのではありませんか?

そういう訳なので、復号時にstrlen(暗号化済文字列)で復号すべき長さを求めるのは間違い。
変換前の文字列長の分だけを暗号化するなら、元々の長さ情報をどこか別のところに保存しておく必要があ
ります。

しかし、方針を変えて、変換前の文字列長の分だけを暗号化するのではなく、STR_NAME2分全部暗号化して
しまう方が簡単でしょう。


さて。以下に対する回答が、前半部分のあれこれをすべて無に帰してしまいます。

> ># ところで、文字列部分しか暗号化していないようですが、その程度のものでよいので
> >すか?
> いいえ、一行の場合(構造体)どうやるのでしょうか。

DFMData構造体のインスタンスを単なるバイト列と見做して、sizeof(DFMData)バイト分暗号化する。
元のコードに変数名や構成等を合わせて書くならこんな感じ。(動作未検証)
元のコードに較べて、ra_iが大きくなるので、randValueの長さに注意。

# 一から書くとしたら、任意のバイト数のデータを暗号化する関数を
# 作って、そこにDFMData構造体のインスタンス(何なら構造体配列全体)
# を放り込むようにするけどね。

// 変数宣言は元コードと同じなので略。

for(int j=0; j<30; j++){
  DFMData_Savedata = mp_TextDfmSct[j].DfmLaye;
  char *p = (char *)&DFMData_Savedata; // DFMData_Savedata をバイト列とみなして

  // そのバイト列を構造体の長さ分だけ暗号化
  for (int ik=0; ik<sizeof(DFMData_Savedata); ik++){
    p[ik] ^= randValue[ra_i++];
 }
  fwrite(&DFMData_Savedata, sizeof(DFMData_Savedata), 1, fp9);
}

GG 2007/07/14(土) 20:07:27
yoh2さん、
ご返事ありがとう。

>そういう訳なので、復号時にstrlen(暗号化済文字列)で復号すべき長さを求めるのは間
>違い。

なるほど、わかりました。

>変換前の文字列長の分だけを暗号化するなら、元々の長さ情報をどこか別のところに保
>存しておく必要があります。

そうですね、面倒になります。

>char *p = (char *)&DFMData_Savedata; // DFMData_Savedata をバイト列とみなして

複号時に、以下のように書きました。
for(int i=0; i<30; i++){
 fread(&DFMData_Readdata, sizeof(DFMData_Readdata), 1, fp8);
 char *p = (char *)&DFMData_Readdata; // DFMData_Savedata をバイト列とみなして
 for(ik=0; ik<sizeof(DFMData_Readdata); ik++ ){
  p[ik] = (char)(p[ik] ^ randValue[ra_i]);
  ra_i++;
 }
 p[ik] = '\0';

  //構造体に戻す
 DFMData_Readdata=(DFMData)p; //ここで、どう書けばいいでしょうか
                //今は、エラーです。
  
  //検証するため
  st2.Format("%d,%d,%d,%s,%d,%d,%d,%d,%d\n",
            DFMData_Readdata.DfmLaye,
            DFMData_Readdata.DfmBcode,
            DFMData_Readdata.DfmType,
            DFMData_Readdata.DfmName,            
            DFMData_Readdata.DfmSize,
            DFMData_Readdata.DfmWide,
            DFMData_Readdata.DfmColor,
            DFMData_Readdata.DfmArrange,
            DFMData_Readdata.TextDfmDraw_flag);
  fputs(st2, fp7);
 }

ここで、DFMData_ReaddataとDFMData_Savedataは同じ構造体です。



よろしくお願いします。

オレンジフィッシュ 2007/07/14(土) 21:37:42
オレンジフィッシュです。

構造体で苦戦していますが文字列と同じように扱えば楽ですよ。
こんどは文字列でも構造体でも使えるものを紹介します。

// 暗号化/復元の両用関数(関数名は適当にどうぞ)
void MyPassword( void *buff, size_t size )
{
 char *p = (char *)buff;
 
 RandInit( 初期値 );
 
 while ( size > 0 ){
  *p++ = (char)(*p ^ Rand());
  size--;
 }
}
※RnadInit()、Rand() は自分で用意して下さい。
※標準ライブラリの srand()、rand() でも良いですが処理系を変えてしまうと
 復元出来なくなるかもしれない。バージョンによっても出来なくなるので自作すべ
し。
----------------------------------------
// 文字列の場合(暗号化)
char str[] = "123,3334,QQQ,RRRR,4444";
int len = strlen(str);
MyPassword( str, len );
fwrite( str, len, 1, fp );

// 文字列の場合(復元)
char str[ 32 ] = { 0 };
len = 文字列の長さ(22バイト)
fread( str, len, 1, fp );
MyPassword( str, len );
printf( "復元文字列:%s\n", str );
----------------------------------------
// 構造体,バイナリの場合(暗号化)
struct DFMData DFMData_Savedata = { 初期化 };
MyPassword( &DFMData_Savedata, sizeof(struct DFMData) );
fwrite( &DFMData_Savedata, sizeof(struct DFMData), 1, fp );

// 構造体,バイナリの場合(復元)
struct DFMData DFMData_Readdata;
fread( &DFMData_Readdata, sizeof(struct DFMData), 1, fp );
MyPassword( &DFMData_Readdata, sizeof(struct DFMData) );
printf( "DfmName=[%s]\n", DFMData_Readdata.DfmName );
※文字列は復元後に表示すること。
----------------------------------------
構造体の場合は文字列の部分だけではなく全体をバイナリ扱いして暗号化と復元を
データサイズ分だけ行えば良いです。また、暗号化した文字列はバイナリになります。
文字列の途中で \0 が出るかもしれません。strlen() で長さを数えてはいけません。

また構造体の配列を一度に暗号化、復元するには size に構造体サイズ×配列要素数の
バイト数を与えればよい。
たとえば DFMData_Savedata[ 10 ] なら
MyPassword( &DFMData_Savedata, (sizeof(struct DFMData) * 10) );
fwrite( &DFMData_Savedata, sizeof(struct DFMData), 10, fp );
fread( &DFMData_Readdata, sizeof(struct DFMData), 10, fp );
とすれば良い。
fread、fwrite のように個数 max を MyPassword() 関数に用意しても良いかも。
この辺は自由だ。

yoh2 [E-Mail] 2007/07/14(土) 23:55:58
>   //構造体に戻す
>  DFMData_Readdata=(DFMData)p; //ここで、どう書けばいいでしょうか
>                 //今は、エラーです。

何も書く必要なし。

>  char *p = (char *)&DFMData_Readdata; // DFMData_Savedata をバイト列とみなし
て

の意味を考えれば理由は分かるはずです。

オレンジフィッシュ 2007/07/15(日) 00:27:41
復元時の for 文の後にある
>p[ik] = '\0';
これは必要ない処理です。

前は文字列だったのでその最後に \0 を入れていたのです。
構造体やバイナリデータでは必要ありません。
行うとメモリを破壊する恐れがあります。
注意して下さい。

あと i<30 になっているため 30 個の構造体データを一度に
暗号化や復元しても良さそうです。つまり、復元だけ記述すると

struct DFMData DFMData_Readdata[ 30 ];

fread( DFMData_Readdata, sizeof(DFMData_Readdata), 30, fp );
char *p = (char *)&DFMData_Readdata[0];
char *end = (char *)&DFMData_Readdata[30];

while ( p < end ){
 *p++ = (char)(*p ^ randValue[ra_i]);
 ra_i++;
}
という感じでも良さそうです。

GG 2007/07/15(日) 10:22:36
yoh2さん、オレンジフィッシュさん
ご返事ありがとう。

>何も書く必要なし。
>  char *p = (char *)&DFMData_Readdata; // DFMData_Savedata をバイト列とみなし
>て
>の意味を考えれば理由は分かるはずです。

ポイントを指しているのですが、すみませんでした。

うまく変換できました。
一つ覚えるのことはsizeof(DFMData_Savedata)です。
sizeof(DFMData_Savedata)より strlen(DFMData_Savedata)精確です。


> 構造体,バイナリの場合(暗号化)>構造体,バイナリの場合(復元)>また構造体の配列を一度に暗号化、復元するには size に構造体サイズ×配列要素数の
>バイト数を与えればよい。

やりました、うまくできました。
簡潔になりました。

>前は文字列だったのでその最後に \0 を入れていたのです。
>構造体やバイナリデータでは必要ありません。
>行うとメモリを破壊する恐れがあります。
>注意して下さい。

わかりました。

最後、もう一つの質問があります、
今回の暗号化複号化したのですが、
できたバイナリファイルを解読できるのでしょうか、
あるいは、専用のフリソフトを使って簡単に解読されました。(推測)
つまり、保護はどの程度でしょうか。

よろしくお願いします。

yoh2 [E-Mail] 2007/07/15(日) 14:36:03
> できたバイナリファイルを解読できるのでしょうか、
> あるいは、専用のフリソフトを使って簡単に解読されました。(推測)
> つまり、保護はどの程度でしょうか。

フィールド位置は一定だし、変換方法が単純なxorでしかないので、内容を少し変えたファイルをいくつか
用意して変更点を比較されると、バイナリエディタのひとつでもあれば割とあっさり解読できそうです。

また、このプログラムの利用形態が直接実行 (CGIのように、実行ファイルが利用者から見えないのではな
く、通常のワープロソフトのように、実行ファイルが利用者の手元に存在する) の場合、プログラムを逆ア
センブルされたらファイルの比較などの手間をかけることなく丸分かりです。

暗号化というよりは難読化というレベルだと思います。

2007/07/15(日) 16:08:21
>できたバイナリファイルを解読できるのでしょうか
この内容だと容易に解析されます。
しかし、暗号処理が復号して欲しくない人の環境下で行われる場合は解読を
防ぐ事は不可能です。

完全な暗号化をする場合は、復号して欲しくない人には全くアクセスできない場
所で暗号化や復号を行う必要があります。
理論上、物理的に閉じたプログラムはソフトウェアの動作を1ステップずつ解析さ
れる事を防ぐ手立てはありません。
分解不能なハードウェアで処理をしたり、ネットワーク上で暗号処理を完全に隠
蔽する必要があります。

大抵はそこまでしないである程度の難読化で終わると思います。


とりあえず、今回の例を変更して簡単なバイナリ比較を防ぐ場合は

1、乱数列を毎回変更する。
乱数列が毎回同じなのでファイル又は構造体先頭に乱数の種を保存する領域
を追加して、ファイル又構造体ごとに違う乱数を使って暗号処理を行う。
乱数の種自体は暗号化しない。
乱数の種はまた別の乱数列から生成する。たとえば保存処理の前に現在時刻
などを元に乱数列を生成しておき、それを利用するなど。

2、構造体の保存順序を毎回乱す。
小手先だが、保存の前に構造体の位置をシャッフルしてから保存する。シャッフ
ルした順番で保存していく。
並び順に意味が無いならそのままで良いし、並び順を復元するのならばシャッフ
ルに使った乱数の種から復元したり、本来の位置を構造体の前後に追加して保
存しておく。

辺りが使えるかと思います。
これもやはり実行ファイル解析には歯が立ちません。
こちらは実行ファイルの難読化なども考慮したほうがいいのかもしれません。

GG 2007/07/15(日) 17:32:21
[[解決]]
yoh2さん、麩さん
ご返事ありがとう。


>暗号化というよりは難読化というレベルだと思います。

>こちらは実行ファイルの難読化なども考慮したほうがいいのかもしれません。

わかりました。

皆さん、いろいろ教えていただき、
ほんとにありがとうございました。

古いスレッドには追加発言できません。