Created
December 10, 2019 07:14
-
-
Save ateruimashin/cddf1633ef7651515741daa5c8837e2a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<string> //keyとnonceをstringで取るため、苦肉の策。いい方法あったら教えて下さい。 | |
##include <stdexcept> //例外処理用 | |
using namespace std; | |
//chachaのquaterrroundの実装 | |
#define ROTL(a,b) ((a)<<(b)) | ((a)) >> (32 - (b)))) | |
#define QR(a,b,c,d) ( | |
a += b, d ^= a, d = ROTL(d,16), | |
c += d, b ^= c, b = ROTL(b,12), | |
a += d, d ^= a, d = ROTL(d, 8), | |
c += d, b ^= c, b = ROTL(b,7)) | |
) | |
//2^32を法とする加算 | |
uint32_t plus(uint32_t x, uint32_t y){ | |
return (x + y) & 0xffffffff | |
} | |
//round数を20に指定 | |
#dedine ROUNDS 20 | |
//const値をdefine | |
#defune const0 0x61707865 | |
#define const1 0x3320646e | |
#define const2 0x79622d32 | |
#define const3 0x6b206574 | |
/*chacha暗号機実装部分。最初はretuenしようと思ったけど、 | |
よく考えたらそんなことしなくてもいいことに気がついた。*/ | |
void cahca(string key, string nonce){ | |
//Inital Stateを作成。めんどくさいので最初から1*16にしている。 | |
uint32_t x[16]; | |
//const値とblock_countを定義。今回はblock_count=0で固定。 | |
x[0] = const0; | |
x[1] = const1; | |
x[2] = const2; | |
x[3] = const3; | |
x[12] = 0x0; | |
x[13] = 0x0; | |
//keyとnonceを8wordsごとに分けて、16進数の整数値にする。 | |
//key=64words,nonce=16wordsなので、それ以外は例外処理 | |
if(key.size()!=64||nonce.size()!=16){ | |
if(key.size>64||nonce.size()>16){ | |
cout<<"ERROR:key or nonce size over."<<endl; | |
} | |
if(key.size()<64||nonce.size()<16){ | |
cout<<"ERROR:key or nonce size under."<endl; | |
} | |
throw invalid_argument("invalid_argument"); | |
} | |
//nonceを分割 | |
for(int i=0;i<16;i++){ | |
string nonce1_tmp,nonce2_tmp; | |
for(int i = 0; i < 16; i++){ | |
if(i < 8){ | |
nonce1_tmp.push_back(nonce[i]); | |
}else{ | |
nonce2_tmp.push_back(nonce[i]); | |
} | |
} | |
} | |
//nonceをstring->int(16進数)に変換して代入 | |
x[14] = stoi(nonce1_tmp,nullper,16); //他の人の実装はリトルエンディアンにしてるけど、理由がわからない。 | |
x[15] = stoi(nonce2_tmp,nullper,16); //他の人の実装はリトルエンディアンにしてるけど、理由がわからない。 | |
//keyを分割、代入 | |
for(int i = 0; i < 64; i++){ | |
//keyの分割 | |
string tmp; | |
tmp.push_back(key[i]); | |
//keyの代入 | |
if((i+1) % 8 == 0){ | |
x[4+(i+1)/8] = stoi(tmp, nullper, 16); | |
tmp.clear(); //Initial Stateに代入したので、文字列をclearして次のkeyを受ける。 | |
} | |
} | |
//リトルエンディアンにするらしいけど、理由がわからなくて消した。 | |
// //key値を代入 | |
// for(int i = 0; i < 8; i++){ | |
// x[i + 4] = ROTL(key, i * 4); | |
// } | |
//x[]をコピーするための配列を作成する。 | |
uint32_t cp[16]={}; | |
//arrayのcopyめんどくさいので、普通にfor文でコピーする。 | |
for(int i = 0; i < 16; i++){ | |
cp[i] = x[i]; | |
} | |
//x[]をQRに通す | |
for(int i = 0; i < ROUND; i +=2){ | |
//odd round | |
// Odd round | |
QR(x[0], x[4], x[ 8], x[12]); // column 0 | |
QR(x[1], x[5], x[ 9], x[13]); // column 1 | |
QR(x[2], x[6], x[10], x[14]); // column 2 | |
QR(x[3], x[7], x[11], x[15]); // column 3 | |
// Even round | |
QR(x[0], x[5], x[10], x[15]); // diagonal 1 (main diagonal) | |
QR(x[1], x[6], x[11], x[12]); // diagonal 2 | |
QR(x[2], x[7], x[ 8], x[13]); // diagonal 3 | |
QR(x[3], x[4], x[ 9], x[14]); // diagonal 4 | |
} | |
//出力用の配列を作成する | |
uint32_t out[16]={}; | |
//QR前x[]とQR後x[]を加算する | |
for(int i = 0; i < 16; i++){ | |
out[i] = cp[i] + x[i]; | |
} | |
//key_streamの出力 | |
streing key_stream; | |
for(int i = 0; i < 16; i++){ | |
string tmp; | |
tmp = to_string(x[i]); | |
result += tmp; | |
} | |
cout<<result<<endl; | |
} | |
int main(int argc, char const *argv[]) { | |
string key,nonce; | |
cout<<"key?(key is 64words)"<<endl; | |
cin>>key; | |
cout<<"nonce?(nonce is 16words)"<<endl; | |
cin>>nonce; | |
//chachaを通してkey_streamを作成する | |
try{ | |
chacha(key, nonce); | |
} | |
catch(invalid_argument){ | |
return 0; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment