-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrypto.h
executable file
·221 lines (180 loc) · 7.57 KB
/
crypto.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <string>
#include <memory>
#include <cstddef>
#include <immintrin.h>
#include <cassert>
#include <cpuid.h>
#ifndef _CRYPTO_H
#define _CRYPTO_H
namespace crypto {
using buffer_t = std::vector<uint8_t>;
using block_t = __m128i;
using uint128_t = unsigned __int128;
bool read_file(std::string filename,buffer_t &buffer);
bool write_file(std::string filename,const buffer_t &buffer);
bool rand_rdrand(size_t bytes,buffer_t &buffer);
void encode_base64(const buffer_t &plain,std::string &encoded);
void decode_base64(const std::string &encoded,buffer_t &buffer);
bool encode_aes_ecb(const buffer_t &clear,block_t key,buffer_t &cipher);
bool decode_aes_ecb(const buffer_t &cipher,block_t key,buffer_t &clear);
bool encode_aes_cbc(const buffer_t &clear,block_t key,block_t iv,buffer_t &cipher);
bool decode_aes_cbc(const buffer_t &cipher,block_t key,block_t iv,buffer_t &clear);
bool hash_sha256(const buffer_t &clear,buffer_t &hash);
bool hash_sha512(const buffer_t &clear,buffer_t &hash);
bool hash_sha512_256(const buffer_t &clear,buffer_t &hash);
bool is_prime(uint64_t x);
uint64_t next_prime(uint64_t x);
uint64_t pow_mod(uint64_t x,uint64_t e,uint64_t m);
uint64_t inv_mod(uint64_t e,uint64_t m);
struct srsa_private_t {
uint64_t p,q;
uint64_t e,d;
};
struct srsa_public_t {
uint64_t e,n;
};
bool srsa_generate(srsa_private_t &key);
bool srsa_publish(const srsa_private_t &key, srsa_public_t &pub);
bool srsa_encode(uint64_t plain,const srsa_public_t &pub,uint64_t &encoded);
bool srsa_decode(uint64_t encoded,const srsa_private_t &key,uint64_t &plain);
class NNI {
public:
using digit_t = uint64_t;
using long_t = uint128_t;
NNI() { }
NNI(digit_t n);
NNI(const std::string &str);
NNI(const buffer_t &bytes);
void print() const;
std::string format() const;
int size() const { return static_cast<int>(digits.size()); }
digit_t digit(int i) const {
return (i>=0 && i<size()) ? digits.at(i) : 0;
}
int bottom_zeros();
int top_zeros();
NNI & operator<<=(int n);
NNI & operator>>=(int n);
friend NNI operator+(const NNI &u,const NNI &v);
friend NNI operator-(const NNI &u,const NNI &v);
friend NNI operator*(const NNI &u,const NNI &v);
friend NNI operator/(const NNI &u,const NNI &v);
friend NNI operator%(const NNI &u,const NNI &v);
friend void divide(NNI &q,NNI &r,const NNI &u,const NNI &v);
friend NNI expmod(const NNI &a,const NNI &e,const NNI &b);
friend NNI invmod(const NNI &e,const NNI &m);
friend bool operator<(const NNI &u,const NNI &v);
friend bool operator==(const NNI &u,const NNI &v);
protected:
digit_t & operator[](int i) { return digits.at(static_cast<size_t>(i)); }
void canonicalize();
static digit_t find_qhat(digit_t un,digit_t un1,digit_t un2,digit_t vn1,digit_t vn2);
std::vector<digit_t> digits;
};
struct rsa_private_t {
NNI p,q;
NNI e,d;
};
struct rsa_public_t {
NNI e,n;
};
bool rsa_generate(rsa_private_t &key);
bool rsa_publish(const rsa_private_t &key, rsa_public_t &pub);
bool rsa_encode(const NNI &plain,const rsa_public_t &pub,NNI &encoded);
bool rsa_decode(const NNI &encoded,const rsa_private_t &key,NNI &plain);
bool is_miller_rabin_prime(int k,const NNI &n);
bool random_miller_rabin_prime(int k,NNI &p);
struct dh_secret_t {
NNI p; // prime
NNI g; // base, usually 2
NNI a; // my half of the secret, any random number
};
struct dh_exchange_t {
NNI p; // prime
NNI g; // base, usually 2
NNI half; // encoded half secret; g^a mod p
NNI sig; // authentication; hash(half)^priv.d mod priv.n
};
// Alice: s = generate()
// Alice: e = encode(s,A's private key)
// Alice --e--> Bob
// Bob: t = generate(e)
// Bob: f = encode(t,B's private key)
// Alice <--f-- Bob
// Bob: k = combine(e,t,A's public key)
// Alice: k = combine(f,s,B's public key)
bool dh_generate(dh_secret_t &secret,const dh_exchange_t *e=nullptr);
bool dh_encode(dh_exchange_t &e,const dh_secret_t &secret,const rsa_private_t &key);
bool dh_combine(NNI &shared_secret,const dh_exchange_t &e,const dh_secret_t &secret,const rsa_public_t &pub);
class VNNI {
public:
using digit_t = NNI::digit_t;
using long_t = NNI::long_t;
static digit_t woop_base;
private:
VNNI(const NNI &n,digit_t w) : nni(n), woop(w) { }
digit_t compute_woop() const;
NNI nni;
digit_t woop;
public:
VNNI() : woop(0) { }
VNNI(digit_t n) : nni(n), woop(n % woop_base) { }
VNNI(const std::string &str) : nni(str) { woop=compute_woop(); }
~VNNI() { verify(); }
void print() const;
std::string format() const { return nni.format(); };
int size() const { return nni.size(); }
digit_t digit(int i) const { return nni.digit(i); }
void verify() const;
VNNI & operator<<=(int n);
VNNI & operator>>=(int n);
friend VNNI operator+(const VNNI &u,const VNNI &v);
friend VNNI operator-(const VNNI &u,const VNNI &v);
friend VNNI operator*(const VNNI &u,const VNNI &v);
friend VNNI operator/(const VNNI &u,const VNNI &v);
friend VNNI operator%(const VNNI &u,const VNNI &v);
friend void divide(VNNI &q,VNNI &r,const VNNI &u,const VNNI &v);
friend VNNI expmod(const VNNI &a,const VNNI &e,const VNNI &b);
friend bool operator<(const VNNI &u,const VNNI &v) { return u.nni<v.nni; }
friend bool operator==(const VNNI &u,const VNNI &v) { return u.nni==v.nni; }
};
#if 0
using digit_t = uint64_t;
using long_t = uint128_t;
using nni_t = std::vector<digit_t>;
void set(nni_t &r, digit_t n);
void set(nni_t &r, const std::string & str);
void shiftleft(nni_t &r,size_t n);
void shiftright(nni_t &r,size_t n);
void add(nni_t &r,const nni_t &u,const nni_t &v);
void subtract(nni_t &r,const nni_t &u,const nni_t &v);
void multiply(nni_t &r,const nni_t &u,const nni_t &v);
void divide(nni_t &q,nni_t &r,const nni_t &u,const nni_t &v);
void expmod(nni_t &r,const nni_t &a,const nni_t &e,const nni_t &b);
bool lesser(const nni_t &u,const nni_t &v);
digit_t digit(const nni_t &n,size_t i);
std::string format(const nni_t &u);
size_t top_zeros(const nni_t &u);
void canonicalize(const nni_t &u);
#endif
bool decode_rsakey(const buffer_t &buffer,std::vector<buffer_t> &fields);
/* version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p */
};
std::ostream & operator<<(std::ostream &out,const crypto::buffer_t &buffer);
std::ostream & operator<<(std::ostream &out,const crypto::block_t &block);
//std::ostream & operator<<(std::ostream &out,const crypto::nni_t &n);
std::ostream & operator<<(std::ostream &out,const crypto::NNI &n);
#endif