つけじょにーのすぱげていコード

主に、競技プログラミング、セキュリティのお勉強の際に書いたすぱげていコードを書き込みます

単一換字暗号

シーザー暗号とちょっと似てますが、文字の対応付けをして、それに基づいて暗号化を行うというものです。

暗号化を行うプログラムを書いてみました。(難しいのは書けないっす(T_T))

//単一換字暗号
#include <bits/stdc++.h>
using namespace std;
char table[] = {'K', 'H', 'U', 'B', 'Y', 'V', 'X', 'W', 'E', 'L', 'G', 'A',
                'C', 'D', 'F', 'J', 'I', 'Q', 'M', 'S', 'T', 'O', 'R'};
map<char, char> hm;

string encrypt(string input) {
    string res = "";
    for(int r = 0; r < input.length(); r++) {
        if(isspace(input[r])) {res += ' '; continue;}
        if(isdigit(input[r])) {res += hm['a' + (input[r] % 26)]; continue;}
        res += hm[input[r]];
    }
    return(res);
}

int main(void) {
    for(int alpha = 'a'; alpha <= 'z'; alpha++) {
        hm[alpha] = table[alpha - 'a'];
    }
    
    string input; getline(cin, input);
    cout << encrypt(input) << endl;
    
    return(0);
}

これを解読するには、文字の頻度を利用した方法を使います。
文字の頻度を割り出し、その文字に基づき、英語でもっともよく使われる単語について考えます。
これを繰り返していくと無理やり複合化できるというものです。
鍵(テーブル)さえ知っていれば対応させることですぐに変換できるんですが、頻度を調べて・・・なんて大変ですね

UNIXコマンド:testコマンド

条件式を書くときなどに利用するらしい

test valueA -option valueB といった形式

よく使いそうなオプションについて説明する

(括弧内の英語は、私個人の推測)

 

-eq (equal)

-ne(not equal)

-gt(greater than)

-ge(greater than & equal)

-lt(less than)

-le(less than & equal) 

 

if文と組み合わせるといい感じになりそう

 

if test $? -eq 0; then

  echo "Hello"

fi

 

論理積(AND)、論理和(OR)はそれぞれ次のオプションで利用するらしい

-a, -o

RSA@C++

試しにRSA暗号化及び複合化を行うプログラムを作成してみました(すっごいチープ。平文は整数値じゃなきゃだめ)。

試しに平文123にしてみて、暗号化、複合化をしてみたのですが、思ったように複合できませんでした

う〜ん、p, qを選ぶところがまずいのかな?

 

//公開鍵暗号

//RSA cipher

#include <iostream>

#include <cstdio>

#include <cstdlib>

using namespace std;

typedef long long ll;

int E, D, N;

 

int gcd(int a, int b) {

    if(b == 0) return(a);

    return(gcd(b, a % b));

}

 

int lcm(int m, int n) {

    if(m == 0 || n == 0) return(0);

    return(m * n / gcd(m, n));

}

 

bool isPrime(int n) {

    if(n < 2) return(false);

    for(int r = 2; r * r <= n; r++) {

        if(n % r == 0) return(false);

    }

    return(true);

}

 

void generate() {

    srand*1;

    int p, q;

    while(true) {

        p = rand() % 100;

        q = rand() % 100;

        if(isPrime(p) && isPrime(q)) break;

    }

    

    N = p * q;

    int L = lcm(p - 1, q - 1); //一時的な値

    for(int r = 1; r <= L; r++) {

        if(gcd(r, L) == 1) E = r;

    }

    for(int r = 1; r <= L; r++) {

        if((E * r) % L == 1) D = r;

    }

    cout << "------------------------------------------" << endl;

    cout << "Your public-key:" << endl;

    cout << "E:" << E << endl;

    cout << "N:" << N << endl;

    

    cout << "Your private-key:" << endl;

    cout << "D:" << D << endl;

    cout << "N:" << N << endl;

    cout << "------------------------------------------" << endl;

}

 

ll mod_pow(ll x, ll n) {

    ll res = 1;

    while(n > 0) {

        if(n & 1) res = res * x;

        

        x = x * x;

        n >>= 1;

    }

    return(res);

}

 

ll encrypt(int plain) {

    return(mod_pow(plain, E) % N);

}

 

ll decode(int cipher) {

    return(mod_pow(cipher, D) % N);

}

 

int main(void) {

    int choice; cin >> choice;//暗号化は1 複合化は2

    

    if(choice == 1) {

        generate();

        int plain; cin >> plain; //平文 ここでは数値

        cout << "cipher is " << encrypt(plain) << endl;

    } else {

        cin >> D >> N; //秘密鍵を入力

        int cipher; cin >> cipher;

        cout << "plain is " << decode(cipher) << endl;

    }

    return(0);

}

*1:unsigned)time(NULL

readコマンド

% while read line; do; echo $line; done < random.txt

readコマンドは標準入力から入力を受け付け、受け付けた値を変数に入れるみたいですが、こんな事もできます。

こうすることで1行1行読む事が出来るんですね。

ちなみに、使った後にunset line;とするのがおすすめです。

 

初めまして!

初めまして、tukeJonnyです。

大学でプログラミングを専攻しているので(実力はまだ全然ありませんが・・・)、その過程で、ブログに書こう!と思った事を主に買いていこうと思っています。