Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
pke.cpp
Go to the documentation of this file.
1#include <fc/crypto/pke.hpp>
2#include <openssl/rsa.h>
3#include <openssl/rand.h>
4#include <openssl/sha.h>
5#include <openssl/pem.h>
6#include <openssl/err.h>
8#include <fc/io/sstream.hpp>
9#include <fc/io/stdio.hpp>
11#include <fc/variant.hpp>
12
13namespace fc {
14
15 namespace detail {
17 {
18 public:
19 pke_impl():rsa(nullptr){}
21 {
22 if( rsa != nullptr )
23 RSA_free(rsa);
24 }
25 RSA* rsa;
26 };
27 } // detail
28
29 public_key::operator bool()const { return !!my; }
30 private_key::operator bool()const { return !!my; }
31
34
36 :my( std::make_shared<detail::pke_impl>() )
37 {
38 string pem = "-----BEGIN RSA PUBLIC KEY-----\n";
39 auto b64 = fc::base64_encode( (const unsigned char*)d.data(), d.size() );
40 for( size_t i = 0; i < b64.size(); i += 64 )
41 pem += b64.substr( i, 64 ) + "\n";
42 pem += "-----END RSA PUBLIC KEY-----\n";
43 // fc::cerr<<pem;
44
45 BIO* mem = (BIO*)BIO_new_mem_buf( (void*)pem.c_str(), pem.size() );
46 my->rsa = PEM_read_bio_RSAPublicKey(mem, NULL, NULL, NULL );
47 BIO_free(mem);
48 }
50 :my(k.my)
51 {
52 }
53
55 :my(std::move(k.my))
56 {
57 }
58
60
62 {
63 my = p.my; return *this;
64 }
66 {
67 my = std::move(p.my); return *this;
68 }
69 bool public_key::verify( const sha1& digest, const array<char,2048/8>& sig )const
70 {
71 return 0 != RSA_verify( NID_sha1, (const uint8_t*)&digest, 20,
72 (uint8_t*)&sig, 2048/8, my->rsa );
73 }
74
75 bool public_key::verify( const sha1& digest, const signature& sig )const
76 {
77 static_assert( sig.size() == 2048/8, "" );
78 return 0 != RSA_verify( NID_sha1, (const uint8_t*)&digest, 20,
79 (uint8_t*)sig.data(), 2048/8, my->rsa );
80 }
81 bool public_key::verify( const sha256& digest, const signature& sig )const
82 {
83 static_assert( sig.size() == 2048/8, "" );
84 return 0 != RSA_verify( NID_sha256, (const uint8_t*)&digest, 32,
85 (uint8_t*)sig.data(), 2048/8, my->rsa );
86 }
87 bytes public_key::encrypt( const char* b, size_t l )const
88 {
89 FC_ASSERT( my && my->rsa );
90 bytes out( RSA_size(my->rsa) ); //, char(0) );
91 int rtn = RSA_public_encrypt( l,
92 (unsigned char*)b,
93 (unsigned char*)out.data(),
94 my->rsa, RSA_PKCS1_OAEP_PADDING );
95 if( rtn >= 0 ) {
96 out.resize(rtn);
97 return out;
98 }
99 FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
100 }
101
103 {
104 FC_ASSERT( my && my->rsa );
105 bytes out( RSA_size(my->rsa) ); //, char(0) );
106 int rtn = RSA_public_encrypt( in.size(),
107 (unsigned char*)in.data(),
108 (unsigned char*)out.data(),
109 my->rsa, RSA_PKCS1_OAEP_PADDING );
110 fc::cerr<<"rtn: "<<rtn<<"\n";
111 if( rtn >= 0 ) {
112 out.resize(rtn);
113 return out;
114 }
115 FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
116 }
118 {
119 FC_ASSERT( my && my->rsa );
120 bytes out( RSA_size(my->rsa) );//, char(0) );
121 int rtn = RSA_public_decrypt( in.size(),
122 (unsigned char*)in.data(),
123 (unsigned char*)out.data(),
124 my->rsa, RSA_PKCS1_OAEP_PADDING );
125 if( rtn >= 0 ) {
126 out.resize(rtn);
127 return out;
128 }
129 FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
130 }
131
133 {
134 bytes ba;
135 if( !my ) { return ba; }
136
137 BIO *mem = BIO_new(BIO_s_mem());
138 int e = PEM_write_bio_RSAPublicKey( mem, my->rsa );
139 if( e != 1 )
140 {
141 BIO_free(mem);
142 FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
143 }
144 char* dat;
145 uint32_t l = BIO_get_mem_data( mem, &dat );
146
147 fc::stringstream ss( string( dat, l ) );
148 fc::stringstream key;
149 fc::string tmp;
150 fc::getline( ss, tmp );
151 fc::getline( ss, tmp );
152 while( tmp.size() && tmp[0] != '-' )
153 {
154 key << tmp;
155 fc::getline( ss, tmp );
156 }
157 auto str = key.str();
158 str = fc::base64_decode( str );
159 ba = bytes( str.begin(), str.end() );
160
161 BIO_free(mem);
162 return ba;
163 }
164
169 :my( std::make_shared<detail::pke_impl>() )
170 {
171
172 string pem = "-----BEGIN RSA PRIVATE KEY-----\n";
173 auto b64 = fc::base64_encode( (const unsigned char*)d.data(), d.size() );
174 for( size_t i = 0; i < b64.size(); i += 64 )
175 pem += b64.substr( i, 64 ) + "\n";
176 pem += "-----END RSA PRIVATE KEY-----\n";
177 // fc::cerr<<pem;
178
179 BIO* mem = (BIO*)BIO_new_mem_buf( (void*)pem.c_str(), pem.size() );
180 my->rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL );
181 BIO_free(mem);
182
183 FC_ASSERT( my->rsa, "read private key" );
184 }
185
187 :my(k.my)
188 {
189 }
191 :my(std::move(k.my) )
192 {
193 }
195
197 {
198 my = p.my; return *this;
199 }
201 {
202 my = std::move(p.my); return *this;
203 }
204
206 {
207 FC_ASSERT( (size_t(RSA_size(my->rsa)) <= sizeof(sig)), "Invalid RSA size" );
208 uint32_t slen = 0;
209 if( 1 != RSA_sign( NID_sha1, (uint8_t*)&digest,
210 20, (unsigned char*)&sig, &slen, my->rsa ) )
211 {
212 FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
213 }
214 }
215
217 {
218 if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
219 signature sig;
220 sig.resize( RSA_size(my->rsa) );
221
222 uint32_t slen = 0;
223 if( 1 != RSA_sign( NID_sha1, (uint8_t*)digest.data(),
224 20, (unsigned char*)sig.data(), &slen, my->rsa ) )
225 {
226 FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
227 }
228 return sig;
229 }
231 {
232 if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
233 signature sig;
234 sig.resize( RSA_size(my->rsa) );
235
236 uint32_t slen = 0;
237 if( 1 != RSA_sign( NID_sha256, (uint8_t*)digest.data(),
238 32, (unsigned char*)sig.data(), &slen, my->rsa ) )
239 {
240 FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
241 }
242 return sig;
243 }
244
245
247 {
248 if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
249 bytes out;
250 out.resize( RSA_size(my->rsa) );
251 int rtn = RSA_private_encrypt( in.size(),
252 (unsigned char*)in.data(),
253 (unsigned char*)out.data(),
254 my->rsa, RSA_PKCS1_OAEP_PADDING );
255 if( rtn >= 0 ) {
256 out.resize(rtn);
257 return out;
258 }
259
260 FC_THROW_EXCEPTION( exception, "encrypt failed" );
261 }
262
263 bytes private_key::decrypt( const char* in, size_t l )const
264 {
265 if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
266 bytes out;
267 out.resize( RSA_size(my->rsa) );
268 int rtn = RSA_private_decrypt( l,
269 (unsigned char*)in,
270 (unsigned char*)out.data(),
271 my->rsa, RSA_PKCS1_OAEP_PADDING );
272 if( rtn >= 0 ) {
273 out.resize(rtn);
274 return out;
275 }
276 FC_THROW_EXCEPTION( exception, "decrypt failed" );
277 }
279 {
280 if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" );
281 bytes out;
282 out.resize( RSA_size(my->rsa) );
283 int rtn = RSA_private_decrypt( in.size(),
284 (unsigned char*)in.data(),
285 (unsigned char*)out.data(),
286 my->rsa, RSA_PKCS1_OAEP_PADDING );
287 if( rtn >= 0 ) {
288 out.resize(rtn);
289 return out;
290 }
291 FC_THROW_EXCEPTION( exception, "decrypt failed" );
292 }
293
295 {
296 bytes ba;
297 if( !my ) { return ba; }
298
299 BIO *mem = BIO_new(BIO_s_mem());
300 int e = PEM_write_bio_RSAPrivateKey( mem, my->rsa, NULL, NULL, 0, NULL, NULL );
301 if( e != 1 )
302 {
303 BIO_free(mem);
304 FC_THROW_EXCEPTION( exception, "Error writing private key, ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) );
305 }
306 char* dat;
307 uint32_t l = BIO_get_mem_data( mem, &dat );
308 // return bytes( dat, dat + l );
309
310 stringstream ss( string( dat, l ) );
311 stringstream key;
312 string tmp;
313 fc::getline( ss, tmp );
314 fc::getline( ss, tmp );
315
316 while( tmp.size() && tmp[0] != '-' )
317 {
318 key << tmp;
319 fc::getline( ss, tmp );
320 }
321 auto str = key.str();
322 str = fc::base64_decode( str );
323 ba = bytes( str.begin(), str.end() );
324 // ba = bytes( dat, dat + l );
325 BIO_free(mem);
326 return ba;
327 }
328
330 {
331 static bool init = true;
332 if( init ) { ERR_load_crypto_strings(); init = false; }
333
334 pub.my = std::make_shared<detail::pke_impl>();
335 priv.my = pub.my;
336 pub.my->rsa = RSA_generate_key( 2048, 65537, NULL, NULL );
337 }
338
340 void to_variant( const public_key& bi, variant& v )
341 {
342 v = bi.serialize();
343 }
344
346 void from_variant( const variant& v, public_key& bi )
347 {
348 bi = public_key( v.as<std::vector<char> >() );
349 }
350
351
353 void to_variant( const private_key& bi, variant& v )
354 {
355 v = bi.serialize();
356 }
357
359 void from_variant( const variant& v, private_key& bi )
360 {
361 bi = private_key( v.as<std::vector<char> >() );
362 }
363
364} // fc
const mie::Vuint & p
Definition bn.cpp:27
Used to generate a useful error report when an exception is thrown.
Definition exception.hpp:58
bytes encrypt(const bytes &) const
Definition pke.cpp:246
void sign(const sha1 &digest, array< char, 2048/8 > &sig) const
Definition pke.cpp:205
bytes decrypt(const char *bytes, size_t len) const
Definition pke.cpp:263
private_key & operator=(const private_key &p)
Definition pke.cpp:196
bytes serialize() const
Definition pke.cpp:294
public_key & operator=(const public_key &p)
Definition pke.cpp:61
bool verify(const sha1 &digest, const array< char, 2048/8 > &sig) const
Definition pke.cpp:69
bytes encrypt(const char *data, size_t len) const
Definition pke.cpp:87
bytes decrypt(const bytes &) const
Definition pke.cpp:117
bytes serialize() const
Definition pke.cpp:132
const char * data() const
Definition sha256.cpp:31
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition variant.hpp:191
T as() const
Definition variant.hpp:327
Defines exception's used by fc.
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
void init()
Definition lib_test.cpp:3
namespace sysio::chain
Definition authority.cpp:3
std::string string
Definition string.hpp:10
fc::sha256 digest(const T &value)
Definition digest.hpp:9
std::string base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len)
Definition base64.cpp:92
std::vector< char > bytes
Definition alt_bn128.hpp:10
bytes signature
Definition pke.hpp:17
void generate_key_pair(public_key &, private_key &)
Definition pke.cpp:329
void from_variant(const fc::variant &v, sysio::chain::chain_id_type &cid)
void to_variant(const sysio::chain::shared_public_key &var, fc::variant &vo)
Definition authority.cpp:4
std::string base64_decode(const std::string &encoded_string)
Definition base64.cpp:152
Definition name.hpp:106
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
uint8_t key[16]
Definition yubico_otp.c:41
CK_ULONG d
bool pub
int l