Async 1.8.0
AsyncSslCertSigningReq.h
Go to the documentation of this file.
1
31#ifndef ASYNC_CERT_SIGNING_REQ_INCLUDED
32#define ASYNC_CERT_SIGNING_REQ_INCLUDED
33
34
35/****************************************************************************
36 *
37 * System Includes
38 *
39 ****************************************************************************/
40
41#include <openssl/x509.h>
42#include <cassert>
43#include <string>
44#include <iostream>
45#include <vector>
46#include <algorithm>
47#include <iomanip>
48
49
50/****************************************************************************
51 *
52 * Project Includes
53 *
54 ****************************************************************************/
55
56#include <AsyncSslKeypair.h>
58
59
60/****************************************************************************
61 *
62 * Local Includes
63 *
64 ****************************************************************************/
65
66
67
68/****************************************************************************
69 *
70 * Forward declarations
71 *
72 ****************************************************************************/
73
74
75
76/****************************************************************************
77 *
78 * Namespace
79 *
80 ****************************************************************************/
81
82namespace Async
83{
84
85
86/****************************************************************************
87 *
88 * Forward declarations of classes inside of the declared namespace
89 *
90 ****************************************************************************/
91
92
93
94/****************************************************************************
95 *
96 * Defines & typedefs
97 *
98 ****************************************************************************/
99
100
101
102/****************************************************************************
103 *
104 * Exported Global Variables
105 *
106 ****************************************************************************/
107
108
109
110/****************************************************************************
111 *
112 * Class definitions
113 *
114 ****************************************************************************/
115
124{
125 public:
126 enum : long
127 {
128 VERSION_1 = 0
129 };
130
135 {
136 m_req = X509_REQ_new();
137 assert(m_req != nullptr);
138 }
139
147 SslCertSigningReq(X509_REQ* req) : m_req(req) {}
148
154 : m_req(other.m_req), m_file_path(other.m_file_path)
155 {
156 other.m_req = nullptr;
157 other.m_file_path.clear();
158 }
159
165 {
166#if OPENSSL_VERSION_MAJOR >= 3
167 m_req = X509_REQ_dup(other);
168#else
169 m_req = X509_REQ_dup(const_cast<X509_REQ*>(other.m_req));
170#endif
171 m_file_path = other.m_file_path;
172 }
173
178 //SslCertSigningReq(const std::string& pem)
179 //{
180 // readPem(pem);
181 //}
182
187 {
188 if (m_req != nullptr)
189 {
190 X509_REQ_free(m_req);
191 m_req = nullptr;
192 }
193 m_file_path.clear();
194 }
195
202 {
203#if OPENSSL_VERSION_MAJOR >= 3
204 m_req = X509_REQ_dup(other);
205#else
206 m_req = X509_REQ_dup(const_cast<X509_REQ*>(other.m_req));
207#endif
208 m_file_path = other.m_file_path;
209 return *this;
210 }
211
218 {
219 m_req = other.m_req;
220 m_file_path = other.m_file_path;
221 other.m_req = nullptr;
222 other.m_file_path.clear();
223 return *this;
224 }
225
230 operator const X509_REQ*() const { return m_req; }
231
236 void set(X509_REQ* req)
237 {
238 if (m_req != nullptr)
239 {
240 X509_REQ_free(m_req);
241 }
242 m_req = req;
243 }
244
250 void clear(void)
251 {
252 if (m_req != nullptr)
253 {
254 X509_REQ_free(m_req);
255 }
256 m_req = X509_REQ_new();
257 }
258
263 bool isNull(void) const { return (m_req == nullptr); }
264
274 {
275 assert(m_req != nullptr);
276 return (X509_REQ_set_version(m_req, version) == 1);
277 }
278
283 long version(void) const { return X509_REQ_get_version(m_req); }
284
292 bool addSubjectName(const std::string& field, const std::string& value)
293 {
294 assert(m_req != nullptr);
295 X509_NAME* name = X509_REQ_get_subject_name(m_req);
296 if (name == nullptr)
297 {
298 name = X509_NAME_new();
299 }
300 assert(name != nullptr);
301 bool success = (X509_NAME_add_entry_by_txt(name, field.c_str(),
302 MBSTRING_UTF8,
303 reinterpret_cast<const unsigned char*>(value.c_str()),
304 value.size(), -1, 0) == 1);
305 success = success && (X509_REQ_set_subject_name(m_req, name) == 1);
306 return success;
307 }
308
314 bool setSubjectName(X509_NAME* name)
315 {
316 assert(m_req != nullptr);
317 return X509_REQ_set_subject_name(m_req, name);
318 }
319
324 const X509_NAME* subjectName(void) const
325 {
326 if (m_req == nullptr) return nullptr;
327 return X509_REQ_get_subject_name(m_req);
328 }
329
334 std::vector<unsigned char> subjectDigest(void) const
335 {
336 std::vector<unsigned char> md;
337 auto subj = subjectName();
338 if (subj != nullptr)
339 {
340 auto mdtype = EVP_sha256();
341 //unsigned int mdlen = EVP_MD_meth_get_result_size(mdtype);
342 //unsigned int mdlen = EVP_MD_get_size(mdtype);
343 unsigned int mdlen = EVP_MD_size(mdtype);
344 md.resize(mdlen);
345 if (X509_NAME_digest(subj, mdtype, md.data(), &mdlen) != 1)
346 {
347 md.resize(0);
348 }
349 }
350 return md;
351 }
352
357 std::string subjectNameString(void) const
358 {
359 std::string str;
360 const X509_NAME* nm = subjectName();
361 if (nm != nullptr)
362 {
363 BIO *mem = BIO_new(BIO_s_mem());
364 assert(mem != nullptr);
365 // Print all subject names on one line. Don't escape multibyte chars.
366 int len = X509_NAME_print_ex(mem, nm, 0,
367 XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB);
368 if (len > 0)
369 {
370 char buf[len+1];
371 len = BIO_read(mem, buf, sizeof(buf));
372 if (len > 0)
373 {
374 str = std::string(buf, len);
375 }
376 }
377 BIO_free(mem);
378 }
379 return str;
380 }
381
386 std::string commonName(void) const
387 {
388 std::string cn;
389
390 const auto subj = subjectName();
391 if (subj == nullptr)
392 {
393 return cn;
394 }
395
396 // Assume there is only one CN
397#if OPENSSL_VERSION_MAJOR >= 3
398 int lastpos = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
399#else
400 auto s = X509_NAME_dup(const_cast<X509_NAME*>(subj));
401 int lastpos = X509_NAME_get_index_by_NID(s, NID_commonName, -1);
402 X509_NAME_free(s);
403#endif
404 //int lastpos = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
405 if (lastpos >= 0)
406 {
407 X509_NAME_ENTRY *e = X509_NAME_get_entry(subj, lastpos);
408 ASN1_STRING *d = X509_NAME_ENTRY_get_data(e);
409 cn = reinterpret_cast<const char*>(ASN1_STRING_get0_data(d));
410 }
411 return cn;
412 }
413
419 {
420 assert(m_req != nullptr);
421#if OPENSSL_VERSION_MAJOR >= 3
422 X509_REQ_add_extensions(m_req, exts);
423#else
424 auto e = sk_X509_EXTENSION_dup(exts);
425 X509_REQ_add_extensions(m_req, e);
426 sk_X509_EXTENSION_free(e);
427#endif
428 }
429
435 {
436 assert(m_req != nullptr);
437 return SslX509Extensions(X509_REQ_get_extensions(m_req));
438 }
439
445 {
446 assert(m_req != nullptr);
447 return SslKeypair(X509_REQ_get_pubkey(m_req));
448 }
449
456 {
457 assert(m_req != nullptr);
458 return (X509_REQ_set_pubkey(m_req, pubkey) == 1);
459 }
460
466 bool sign(SslKeypair& privkey)
467 {
468 assert(m_req != nullptr);
469 auto md = EVP_sha256();
470 //auto md_size = EVP_MD_get_size(md);
471 auto md_size = EVP_MD_size(md);
472 return (X509_REQ_sign(m_req, privkey, md) == md_size);
473 }
474
482 bool verify(SslKeypair& pubkey) const
483 {
484 assert(m_req != nullptr);
485 return (X509_REQ_verify(m_req, pubkey) == 1);
486 }
487
492 std::vector<unsigned char> digest(void) const
493 {
494 assert(m_req != nullptr);
495 std::vector<unsigned char> md;
496 auto mdtype = EVP_sha256();
497 //unsigned int mdlen = EVP_MD_get_size(mdtype);
498 unsigned int mdlen = EVP_MD_size(mdtype);
499 md.resize(mdlen);
500 unsigned int len = md.size();
501 if (X509_REQ_digest(m_req, mdtype, md.data(), &len) != 1)
502 {
503 md.resize(0);
504 }
505 return md;
506 }
507
513 bool readPem(const std::string& pem)
514 {
515 BIO *mem = BIO_new(BIO_s_mem());
516 BIO_puts(mem, pem.c_str());
517 if (m_req != nullptr)
518 {
519 X509_REQ_free(m_req);
520 }
521 m_req = PEM_read_bio_X509_REQ(mem, nullptr, nullptr, nullptr);
522 BIO_free(mem);
523 return (m_req != nullptr);
524 }
525
531 bool readPemFile(const std::string& filename)
532 {
533 m_file_path = filename;
534 if (m_req != nullptr)
535 {
536 X509_REQ_free(m_req);
537 m_req = nullptr;
538 }
539 FILE *p_file = fopen(filename.c_str(), "r");
540 if (p_file == nullptr)
541 {
542 return false;
543 }
544 m_req = PEM_read_X509_REQ(p_file, nullptr, nullptr, nullptr);
545 fclose(p_file);
546 return (m_req != nullptr);
547 }
548
556 const std::string& filePath(void) const { return m_file_path; }
557
563 bool writePemFile(FILE* f)
564 {
565 assert(m_req != nullptr);
566 if (f == nullptr)
567 {
568 return false;
569 }
570 int ret = PEM_write_X509_REQ(f, m_req);
571 fclose(f);
572 return (ret == 1);
573 }
574
580 bool writePemFile(const std::string& filename)
581 {
582 return writePemFile(fopen(filename.c_str(), "w"));
583 }
584
590 bool appendPemFile(const std::string& filename)
591 {
592 return writePemFile(fopen(filename.c_str(), "a"));
593 }
594
599 std::string pem(void) const
600 {
601 assert(m_req != nullptr);
602 BIO *mem = BIO_new(BIO_s_mem());
603 int ret = PEM_write_bio_X509_REQ(mem, m_req);
604 assert(ret == 1);
605 char buf[16384];
606 int len = BIO_read(mem, buf, sizeof(buf));
607 assert(len > 0);
608 BIO_free(mem);
609 return std::string(buf, len);
610 }
611
616 void print(const std::string& prefix="") const
617 {
618 //int ext_idx = X509_REQ_get_ext_by_NID(m_req, NID_subject_alt_name, -1);
619 auto sanstr = extensions().subjectAltName().toString();
620 //const auto csr_digest = byteVecToString(digest());
621 //const auto subj_digest = byteVecToString(subjectDigest());
622 std::cout
623 //<< prefix << "Version : " << (version()+1) << "\n"
624 << prefix << "Subject : " << subjectNameString() << "\n"
625 //<< prefix << "Subject Digest : " << subj_digest << "\n"
626 ;
627 if (!sanstr.empty())
628 {
629 std::cout << prefix << "Subject Alt Name : " << sanstr << "\n";
630 }
631 std::cout
632 //<< prefix << "SHA256 Digest : " << csr_digest << "\n"
633 << std::flush;
634 }
635
636 protected:
637
638 private:
639 X509_REQ* m_req = nullptr;
640 std::string m_file_path;
641
642 //std::string byteVecToString(const std::vector<unsigned char> vec) const
643 //{
644 // if (vec.empty())
645 // {
646 // return std::string();
647 // }
648 // std::ostringstream oss;
649 // oss << std::hex << std::setfill('0');
650 // oss << std::setw(2) << static_cast<unsigned>(vec.front());
651 // std::for_each(
652 // std::next(vec.begin()),
653 // vec.end(),
654 // [&](unsigned char x)
655 // {
656 // oss << ":" << std::setw(2) << static_cast<unsigned>(x);
657 // });
658 // return oss.str();
659 //}
660}; /* class SslCertSigningReq */
661
662
663} /* namespace */
664
665#endif /* ASYNC_CERT_SIGNING_REQ_INCLUDED */
666
667/*
668 * This file has not been truncated
669 */
Represent private and public keys.
A class representing X.509 v3 extensions.
A class representing a certificate signing request.
bool setSubjectName(X509_NAME *name)
Set the subject name from a X509_NAME pointer.
bool readPemFile(const std::string &filename)
Read PEM formatted CSR data from file into this object.
SslCertSigningReq & operator=(SslCertSigningReq &other)
Copy assignment operator.
void addExtensions(SslX509Extensions &exts)
Add extensions to this CSR.
const std::string & filePath(void) const
Get the file path associated with this CSR.
SslCertSigningReq(void)
Default constructor.
void set(X509_REQ *req)
Initialize this object from an existing X509_REQ object.
const X509_NAME * subjectName(void) const
Return the subject name as a X509_NAME pointer.
~SslCertSigningReq(void)
Constructor taking PEM data.
bool appendPemFile(const std::string &filename)
Append the CSR data to a PEM file.
bool setPublicKey(SslKeypair &pubkey)
Set the public key.
void print(const std::string &prefix="") const
Print the info in this CSR to std::cout.
SslCertSigningReq(SslCertSigningReq &&other)
Move constructor.
bool writePemFile(const std::string &filename)
Write the CSR data to a PEM file.
SslKeypair publicKey(void) const
Get the public key.
SslX509Extensions extensions(void) const
Get the extensions in this CSR.
SslCertSigningReq(X509_REQ *req)
Constructor using existing X509_REQ.
bool isNull(void) const
Check if this object is empty.
std::vector< unsigned char > subjectDigest(void) const
Get the subject digest.
long version(void) const
Get the version of this CSR.
std::string pem(void) const
Get the data in this CSR as a PEM string.
void clear(void)
Remove all information in this object.
SslCertSigningReq & operator=(SslCertSigningReq &&other)
Move assigned operator.
bool writePemFile(FILE *f)
Write the CSR data to a PEM file.
bool verify(SslKeypair &pubkey) const
Verify the signature of this CSR.
SslCertSigningReq(SslCertSigningReq &other)
Copy constructor.
std::string commonName(void) const
Get the subject common name.
bool sign(SslKeypair &privkey)
Sign the CSR using the given private key.
std::string subjectNameString(void) const
Get the subject DN as a string.
bool addSubjectName(const std::string &field, const std::string &value)
Add a subject name component.
bool readPem(const std::string &pem)
Read PEM formatted CSR data into this object.
std::vector< unsigned char > digest(void) const
Get the sha256 digest of this CSR.
bool setVersion(long version)
Set the version of the request.
A class representing private and public keys.
std::string toString(int type=-1) const
Convert all SANs to a string.
A class representing X.509 extensions.
SslX509ExtSubjectAltName subjectAltName(void) const
Get the subject alternative names extension.
Namespace for the asynchronous programming classes.