文字列をビットローテーションして暗号化する方法

このQ&Aのポイント
  • 文字列をビットローテーションして暗号化するソフトの作り方を教えてください。
  • 数字のビットローテーションはできるが、文字(char)では上手くいかない場合の対処法はありますか?
  • ビットローテーションによる文字列の暗号化について詳しく教えてください。
回答を見る
  • ベストアンサー

文字列をビットローテーションしたい

文字列をビットローテーションして暗号化するソフトを作りたいのですが上手くいきません。 簡単なやり方があれば教えてください。 ちなみに、数字でのローテーションは出来ました。 文字(char)だと上手くいきません。 //////////////////////////////// // int nKey ずらすビット // char mask nKeyだけ既にずらしてあるマスク // char chWord 元の文字列 temp = chWord & mask; chWord = chWord << ((char)sizeof(char)*8 - nKey); temp = temp >> nKey; chWord = chWord | temp;

  • guuhi
  • お礼率12% (1/8)

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.4

No.3の補足に対する回答 暗号化したファイル(出力ファイル)には 0x00 ~ 0xff まですべての文字コードが出力されるので、バイナリモードで出力しないとなりません。 また、可読文字以外の文字(例えば改行やタブ)になる可能性もある事に注意。 テキストモードで書き出すと変になると思います。 まずは、バイナリモードでファイルを読み込み、そのまま何もせずバイナリモードでファイルを書き出すプログラムを書いてみましょう。 それを動かして jpeg ファイル等のバイナリファイルを読み込ませて「ファイルがそのままコピー」されればOK。 あとは、読み込みと書き出しの間に暗号化の処理を追加するだけです。

guuhi
質問者

お礼

ありがとう御座いました。 がんばってみます。

その他の回答 (3)

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

>しかし、スライドするビット数、または文字によりローテーション結果が0になってしまうことがあります。(もちろん、ビットだけ見るとスライドしています) 回答のコードでは、ずらすビット数(nKey)は0~8の範囲である必要があります。 (0と8では何もせず元のデータと同じ物が生成されます。9以上ではビットシフトにより桁溢れが発生しデータが失われます。負の数では結果は未定義です) ずらすビット数を「直前に暗号化したデータに基づいた可変の値にする」などの処理を行う場合には、nKey を0~8の範囲に制限しなければなりません。 ずらすビット数は0と8では同じ結果になるので、0~7の値を使うのが良いでしょう。 return (char)(((((int)chWord) & 0xff) * 257) >> (nKey & 7)); と修正するのが良いと思います(デコード部分も同じように修正します)

guuhi
質問者

補足

たびたびありがとうございます。 ただ、文章が稚拙で申し訳なかったのですが、以前の補足をさらに、補足しますと・・・ 例えば,「2」という文字を2ビット右にシフトします。 すると、ビット自体は教えて頂いた通りシフトされるのですが、このシフト結果を、いざファイルに書き出そうとしても文字列としては""になってしまい。どうにも出来ませんでした。 こういったことを回避する方法は、あるのでしょうか? すいませんが、教えてください。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

少し訂正。 int にしてから 257 倍する前に、上位バイトをマスクするのを忘れていました。 char mask(char chWord,int nKey) // int nKey ずらすビット数 // char chWord 元の文字 { return (char)(((((int)chWord) & 0xff) * 257) >> nKey); } char unmask(char chWord,int nKey) // int nKey 戻すビット数 // char chWord 暗号化した文字 { return (char)((((((int)chWord) & 0xff) * 257) << nKey) >> 8); } 最初から unsigned char でやっておけば良かった気がします(笑)

guuhi
質問者

補足

ありがとうございます。教えていただいた方法で出来ました。 しかし、スライドするビット数、または文字によりローテーション結果が0になってしまうことがあります。(もちろん、ビットだけ見るとスライドしています) これは、ビットローテーションを行う上では仕方ないのでしょうか? それとも、まだ、何かやり方に問題があるということなのでしょうか?

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

符号付き char を右シフトすると、処理系(C言語の種類やプラットフォームの種類)によっては、予想外の結果になります。 符号付きを右シフトすると符号が保存される為、思った通りの結果になりません。 例えば、2進数で「11011001」を右に2ビットシフトすると「00110110」にはならず「11110110」になります。 7ビットシフトすると「11111111」になってしまいます。 以下のようにするとうまく行くと思います。 char mask(char chWord,int nKey) // int nKey ずらすビット数 // char chWord 元の文字 { return (char)((((int)chWord) * 257) >> nKey); } char unmask(char chWord,int nKey) // int nKey 戻すビット数 // char chWord 暗号化した文字 { return (char)(((((int)chWord) * 257) << nKey) >> 8); } このソースコードのキモは「int にして 257 倍してからシフトする」部分にあります。 どうして「これでうまく動くのか」は省略しますので、考えてみて下さい。

関連するQ&A

  • int型の文字列について

    文字列を扱う場合はchar型をつかいますが、int型がchar型より大きいメモリ領域を確保しているとすると、int型で文字列を扱っても問題はないのではと思いました。 実際にやってみると、処理系によって問題なく作動するものとそうでないものが有りますが、基本的な考え方として文字列をint型で扱うことは問題があるのでしょうか? ご存知の方よろしくお願いいたします。 <補足> 要は、255以下の数字を扱うときに、char型でないといけないという制約はなく当然int型を使えるように、文字列においてint型を使うことは、基本的な考え方として問題なのかをお聞きしたい。 当然、処理系において、ルール的に禁じている場合は使えないということは理解できますが。

  • int型での文字列の扱いについて

    整数はint型、文字はchar型を使うのが原則のようですが、 文字はコンピュータの中で数字で扱われていることと、 char型が0~255、int型がそれ以上の範囲の数字を扱えることを考えると 文字を扱う時もint型でかまわないのでは?と思いました。 実際、int型で1文字出力できました。具体的には下です。 int a; a=getchar(); printf("%c\n",a); return 0; しかし、文字列をint型で扱おうとすると、コンパイル時にエラーとなります。 int a[50]="Hello"; printf("%s\n",a); return 0; なぜ、int型では文字列が扱えないのか理解できません。

  • 数値を2進数文字列に変換するものなんですが・・・

    数値を2進数の文字列に変換するプログラムを関数として作成しているんですが、わからないことがあるのでお願いします。 char *itob(int value, int size, char binary[]) { int count = 0; /* binaryの添え字 */ int bit = size * 8; /* ビットになおす */ int mask = 1 << bit - 1; /* 先頭ビットに1を立てる */ /* 数値を2進数の文字列に変換する処理 */ do { if(value & mask) { /* valueとmaskのAND(論理積) */ binary[count] = '1';/* '1'を代入 */ }else { binary[count] = '0';/* '0'を代入 */ } value <<= 1; /* valueを左へ1ビットシフト */ count++; /* countを1たす */ }while(count < bit); /* 繰り返しを行う条件 */ binary[count] = '\0'; /* 最後に'\0'を入れる */ return binary; /* 変換した値を戻り値として返す */ } この前にもプログラムがありますが、コンパイルして実行する際に 10001 1110 と入力したら、 11111 という答えを出したいのですが、 これを実行すると、 00000000000000000000000000011111 となってしまいます。 これを11111とするためにはプログラムにどのような処理をすればよいのかわかりませんのでどなたかおわかりのかた解説をお願いします。

  • javaというか文字列について少し質問です><

    javaというか文字列について少し質問です>< javaというか文字列について少し質問です>< お願いします。 シーザー暗号で文字列をずらすためのクラスのメソッドをつくったのですが・・・ String decrypt(String str,int key) { StringBuffer sb = new StringBuffer(); // もしくはStringBuilder for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c-key); sb.append( c ); } こんな感じなのですがアルファベットの小文字26文字のみとしたいので暗号化や復号化の際に越えてしまう場合はアルファベット内でループさせたいのですがいまいちやり方が浮かびません><越えてしまう場合はzからひいたものを表現させれば良いかと思いやってみたのですが全然違う文字が出てきてしまいました。何かいい方法を教えてください。お願いします><

    • ベストアンサー
    • Java
  • avaというか文字列について少し質問です><

    avaというか文字列について少し質問です>< お願いします。 シーザー暗号で文字列をずらすためのクラスのメソッドをつくったのですが・・・ String decrypt(String str,int key) { StringBuffer sb = new StringBuffer(); // もしくはStringBuilder for(int i=0;i<str.length();i++){ char c=str.charAt(i); c=(char)((int)c-key); sb.append( c ); } こんな感じなのですがアルファベットの小文字26文字のみとしたいので暗号化や復号化の際に越えてしまう場合はアルファベット内でループさせたいのですがいまいちやり方が浮かびません><越えてしまう場合はzからひいたものを表現させれば良いかと思いやってみたのですが全然違う文字が出てきてしまいました。何かいい方法を教えてください。お願いします><

    • ベストアンサー
    • Java
  • 文字列をうまく返してくれない

    数値を文字列として呼び出し元に渡し、呼び出し元で文字列を数値に変えようとしたのですがatoi関数(strtolを使うと最初の文字のみ帰ってくるため2桁以上の数値に対応できない)を使うとうまく行きませんでした。 どのように変更したらatoiが使える文字列になりますか? #include <stdio.h> #include <stdlib.h> static struct{   char *name; }kuda[5]={   { "もも" , "りんご" , "みかん" , "バナナ" , "パイナップル" } } char *re_3( void ){   int a = 3;   char str_h[100];   char *str;   sprintf_s( str_h , 100 , "%d" , a );   *str = *str_h; //原因はおそらくここ   return str; } void main( void ){   printf( "%s" , kuda[ atoi( re_3() ) ].name ); }

  • 構造体の文字列データをファイルへ書き込む方法は?

    構造体の文字列データをファイルへ書き込む方法として、構造体のデータを一気に書き込まずに、データ毎に書き込むことを勉強としてやってみようとしました。 数字の場合はうまくいったのですが、文字列の場合が分かりません。 ご存知の方、よろしくお願いいたします。 <数字の場合> typedef struct { int m1, m2; } Data; fwrite(&data[i].m1, sizeof(int), 1, fp); fwrite(&data[i].m2, sizeof(int), 1, fp); <文字列の場合> #include <stdio.h> typedef struct { char m1[10], m2[10]; } Data; int main() { static Data data[3] = { { "a1", "b1"}, { "c1", "d1"}, { "e1", "f1"}, }; Data data2[10]; FILE *fp; int i, n; fp = fopen("file.dat", "wb"); if (fp == NULL) return 1; for (i = 0; i < 3; i++) { fwrite(&data[i].m1, sizeof(Data.m1[10]), 1, fp); ← sizeofでエラーが出る fwrite(&data[i].m2, sizeof(Data.m2[10]), 1, fp); } fclose(fp); 以下省略

  • 文字列

    ・文字列をキーボードから入力する関数を作成する。 書式:char *StrInp(char *pDefStr, int nLen); 引数:char *pDefStf; 初期文字列 int nLen; 入力可能文字数(1~79) 戻り値:正常ならば、入力した文字列の先頭ポインタ、エラー時はNULL。 処理:pDefStrに与えた文字列を初期値とする文字入力を行う。    nLenで指定した文字数まで入力可能とし、その範囲は1~79    までする。入力時の初期カーソル位置は与えた文字列の最後    になります。初期文字列が必要ない場合はヌル文字を与えます。    初期文字列を与えられた場合は、その文字列も更新可能とする。   ・入力の終了は「リターン」キーとする。   ・「BS」キーを押すと、カーソルの1文字前の文字前の文字を    消去する。 という、問いです。難しくてわかりません。どなたかたすけてください。        

  • C言語の文字列について

    C言語で文字列のヌルについて、理解があいまいな点があり、教えて欲しいのですが、以下のようにsprintfで書式し代入した際に最後は0(ヌル文字)をセットしてくれるのでしょうか?4バイト目の文字が何か知りたいです。 char temp[100];時では0で初期化されていることは保障されていませんが、大抵は0で埋まっていますが、sprintfの仕様が知りたいです。 char temp[100]; sprintf(temp, "test");とした時に 01234バイト目 test?????????????.... 話は変わりますが、以下のようにするとエラーになりましたが、 特定の位置の値をセットする方法はどのようなものがあるのでしょうか? temp[10] = (temp[10] == '0') ? (char)'1' : (char)'0';

  • 文字列検索について

    下記のようなC++プログラムにおいて、Good Morning! の「r」以後が、 検索にひっかからないで、-1を返します。 何故なのか、どうぞよろしくお願いします。 -------------------------------------------------------- #include <iostream> #include <cstring> using namespace std; int flag = 0; // 該当文字があったかどうかのフラグ int strch_idx(const char* s, char c){ int temp; cout << strlen(s) << endl; for(int i=0; i<(signed)strlen(s); i++){ if(*s == c){ temp=i+1; // 配列のインデックスは0オリジンだが、インデックスは1からだから1+する flag = 1; break; } s++; } if(flag == 1) return temp; else return -1; } int main(){ const char* s = "Good Morning!"; int idx = strch_idx(s, 'i'); cout << "検索文字のインデックス:" << idx << endl; return 0; }

専門家に質問してみよう