Skip to content

Instantly share code, notes, and snippets.

@ateruimashin
Created December 10, 2019 07:14
Show Gist options
  • Save ateruimashin/cddf1633ef7651515741daa5c8837e2a to your computer and use it in GitHub Desktop.
Save ateruimashin/cddf1633ef7651515741daa5c8837e2a to your computer and use it in GitHub Desktop.
#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