PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
kcenon::pacs::security::certificate Class Reference

Represents an X.509 certificate. More...

#include <certificate.h>

Collaboration diagram for kcenon::pacs::security::certificate:
Collaboration graph

Public Member Functions

 certificate ()
 Default constructor - creates an empty certificate.
 
 certificate (const certificate &other)
 Copy constructor.
 
 certificate (certificate &&other) noexcept
 Move constructor.
 
auto operator= (const certificate &other) -> certificate &
 Copy assignment.
 
auto operator= (certificate &&other) noexcept -> certificate &
 Move assignment.
 
 ~certificate ()
 Destructor.
 
auto subject_name () const -> std::string
 Get the subject distinguished name.
 
auto subject_common_name () const -> std::string
 Get the common name from the subject.
 
auto subject_organization () const -> std::string
 Get the organization from the subject.
 
auto issuer_name () const -> std::string
 Get the issuer distinguished name.
 
auto serial_number () const -> std::string
 Get the certificate serial number.
 
auto thumbprint () const -> std::string
 Get the certificate thumbprint (SHA-256)
 
auto not_before () const -> std::chrono::system_clock::time_point
 Get the not-before date.
 
auto not_after () const -> std::chrono::system_clock::time_point
 Get the not-after date.
 
auto is_valid () const -> bool
 Check if the certificate is currently valid.
 
auto is_expired () const -> bool
 Check if the certificate has expired.
 
auto to_pem () const -> std::string
 Export certificate as PEM string.
 
auto to_der () const -> std::vector< std::uint8_t >
 Export certificate as DER bytes.
 
auto is_loaded () const noexcept -> bool
 Check if certificate is loaded.
 
auto impl () const noexcept -> const certificate_impl *
 Get internal implementation (for internal use only)
 
auto impl () noexcept -> certificate_impl *
 

Static Public Member Functions

static auto load_from_pem (std::string_view path) -> kcenon::common::Result< certificate >
 Load certificate from PEM file.
 
static auto load_from_pem_string (std::string_view pem_data) -> kcenon::common::Result< certificate >
 Load certificate from PEM string.
 
static auto load_from_der (std::span< const std::uint8_t > der_data) -> kcenon::common::Result< certificate >
 Load certificate from DER-encoded bytes.
 

Private Attributes

std::unique_ptr< certificate_impl > impl_
 

Friends

class certificate_chain
 

Detailed Description

Represents an X.509 certificate.

This class wraps an X.509 certificate and provides methods to access certificate information such as subject, issuer, validity period, and public key.

Thread Safety: This class is thread-safe for read operations.

Example:
auto cert_result = certificate::load_from_pem("/path/to/cert.pem");
if (cert_result.is_ok()) {
auto& cert = cert_result.value();
std::cout << "Subject: " << cert.subject_name() << "\n";
std::cout << "Issuer: " << cert.issuer_name() << "\n";
std::cout << "Valid: " << cert.is_valid() << "\n";
}
static auto load_from_pem(std::string_view path) -> kcenon::common::Result< certificate >
Load certificate from PEM file.

Definition at line 56 of file certificate.h.

Constructor & Destructor Documentation

◆ certificate() [1/3]

kcenon::pacs::security::certificate::certificate ( )

Default constructor - creates an empty certificate.

Definition at line 256 of file certificate.cpp.

256: impl_(std::make_unique<certificate_impl>()) {}
std::unique_ptr< certificate_impl > impl_

◆ certificate() [2/3]

kcenon::pacs::security::certificate::certificate ( const certificate & other)

Copy constructor.

Definition at line 258 of file certificate.cpp.

259 : impl_(std::make_unique<certificate_impl>(*other.impl_)) {}

◆ certificate() [3/3]

kcenon::pacs::security::certificate::certificate ( certificate && other)
defaultnoexcept

Move constructor.

◆ ~certificate()

kcenon::pacs::security::certificate::~certificate ( )
default

Destructor.

Member Function Documentation

◆ impl() [1/2]

auto kcenon::pacs::security::certificate::impl ( ) const -> const certificate_impl*
nodiscardnoexcept

Get internal implementation (for internal use only)

Definition at line 550 of file certificate.cpp.

550 {
551 return impl_.get();
552}

References impl_.

Referenced by kcenon::pacs::security::get_x509_from_certificate().

Here is the caller graph for this function:

◆ impl() [2/2]

auto kcenon::pacs::security::certificate::impl ( ) -> certificate_impl*
nodiscardnoexcept

Definition at line 554 of file certificate.cpp.

554 {
555 return impl_.get();
556}

References impl_.

◆ is_expired()

auto kcenon::pacs::security::certificate::is_expired ( ) const -> bool
nodiscard

Check if the certificate has expired.

Returns
true if certificate has expired

Definition at line 506 of file certificate.cpp.

506 {
507 if (!impl_->is_loaded()) {
508 return true;
509 }
510
511 auto now = std::chrono::system_clock::now();
512 return now > not_after();
513}
auto not_after() const -> std::chrono::system_clock::time_point
Get the not-after date.

References impl_, and not_after().

Here is the call graph for this function:

◆ is_loaded()

auto kcenon::pacs::security::certificate::is_loaded ( ) const -> bool
nodiscardnoexcept

Check if certificate is loaded.

Returns
true if certificate data is loaded

Definition at line 546 of file certificate.cpp.

546 {
547 return impl_ && impl_->is_loaded();
548}

References impl_.

◆ is_valid()

auto kcenon::pacs::security::certificate::is_valid ( ) const -> bool
nodiscard

Check if the certificate is currently valid.

Returns
true if current time is within validity period

Definition at line 497 of file certificate.cpp.

497 {
498 if (!impl_->is_loaded()) {
499 return false;
500 }
501
502 auto now = std::chrono::system_clock::now();
503 return now >= not_before() && now <= not_after();
504}
auto not_before() const -> std::chrono::system_clock::time_point
Get the not-before date.

References impl_, not_after(), and not_before().

Here is the call graph for this function:

◆ issuer_name()

auto kcenon::pacs::security::certificate::issuer_name ( ) const -> std::string
nodiscard

Get the issuer distinguished name.

Returns
Issuer name

Definition at line 410 of file certificate.cpp.

410 {
411 if (!impl_->is_loaded()) {
412 return "";
413 }
414
415 X509_NAME* name = X509_get_issuer_name(impl_->x509());
416 if (!name) {
417 return "";
418 }
419
420 bio_ptr bio(BIO_new(BIO_s_mem()));
421 X509_NAME_print_ex(bio.get(), name, 0, XN_FLAG_RFC2253);
422
423 char* data = nullptr;
424 long len = BIO_get_mem_data(bio.get(), &data);
425 return std::string(data, static_cast<size_t>(len));
426}
std::string_view name

References impl_, and name.

◆ load_from_der()

auto kcenon::pacs::security::certificate::load_from_der ( std::span< const std::uint8_t > der_data) -> kcenon::common::Result<certificate>
staticnodiscard

Load certificate from DER-encoded bytes.

Parameters
der_dataDER-encoded certificate bytes
Returns
Result containing certificate or error

Definition at line 306 of file certificate.cpp.

307 {
308 const unsigned char* data = der_data.data();
309 X509* x509 = d2i_X509(nullptr, &data, static_cast<long>(der_data.size()));
310 if (!x509) {
311 return kcenon::common::make_error<certificate>(
312 4, "Failed to parse DER certificate: " + get_openssl_error(), "certificate");
313 }
314
315 certificate cert;
316 cert.impl_ = std::make_unique<certificate_impl>(x509);
317 return cert;
318}

References impl_.

Referenced by kcenon::pacs::security::digital_signature::get_signature_info(), kcenon::pacs::security::digital_signature::verify(), and kcenon::pacs::security::digital_signature::verify_with_trust().

Here is the caller graph for this function:

◆ load_from_pem()

auto kcenon::pacs::security::certificate::load_from_pem ( std::string_view path) -> kcenon::common::Result<certificate>
staticnodiscard

Load certificate from PEM file.

Parameters
pathPath to PEM-encoded certificate file
Returns
Result containing certificate or error

Definition at line 274 of file certificate.cpp.

275 {
276 auto content_result = read_file(path);
277 if (content_result.is_err()) {
278 return kcenon::common::make_error<certificate>(
279 content_result.error().code,
280 content_result.error().message,
281 "certificate");
282 }
283
284 return load_from_pem_string(content_result.value());
285}
static auto load_from_pem_string(std::string_view pem_data) -> kcenon::common::Result< certificate >
Load certificate from PEM string.

◆ load_from_pem_string()

auto kcenon::pacs::security::certificate::load_from_pem_string ( std::string_view pem_data) -> kcenon::common::Result<certificate>
staticnodiscard

Load certificate from PEM string.

Parameters
pem_dataPEM-encoded certificate data
Returns
Result containing certificate or error

Definition at line 287 of file certificate.cpp.

288 {
289 bio_ptr bio(BIO_new_mem_buf(pem_data.data(), static_cast<int>(pem_data.size())));
290 if (!bio) {
291 return kcenon::common::make_error<certificate>(
292 2, "Failed to create BIO: " + get_openssl_error(), "certificate");
293 }
294
295 X509* x509 = PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr);
296 if (!x509) {
297 return kcenon::common::make_error<certificate>(
298 3, "Failed to parse PEM certificate: " + get_openssl_error(), "certificate");
299 }
300
301 certificate cert;
302 cert.impl_ = std::make_unique<certificate_impl>(x509);
303 return cert;
304}

References impl_.

◆ not_after()

auto kcenon::pacs::security::certificate::not_after ( ) const -> std::chrono::system_clock::time_point
nodiscard

Get the not-after date.

Returns
End of validity period

Definition at line 488 of file certificate.cpp.

488 {
489 if (!impl_->is_loaded()) {
490 return std::chrono::system_clock::time_point{};
491 }
492
493 const ASN1_TIME* time = X509_get0_notAfter(impl_->x509());
494 return asn1_time_to_time_point(time);
495}

References impl_.

Referenced by is_expired(), and is_valid().

Here is the caller graph for this function:

◆ not_before()

auto kcenon::pacs::security::certificate::not_before ( ) const -> std::chrono::system_clock::time_point
nodiscard

Get the not-before date.

Returns
Start of validity period

Definition at line 479 of file certificate.cpp.

479 {
480 if (!impl_->is_loaded()) {
481 return std::chrono::system_clock::time_point{};
482 }
483
484 const ASN1_TIME* time = X509_get0_notBefore(impl_->x509());
485 return asn1_time_to_time_point(time);
486}

References impl_.

Referenced by is_valid().

Here is the caller graph for this function:

◆ operator=() [1/2]

auto kcenon::pacs::security::certificate::operator= ( certificate && other) -> certificate &
defaultnoexcept

Move assignment.

◆ operator=() [2/2]

auto kcenon::pacs::security::certificate::operator= ( const certificate & other) -> certificate&

Copy assignment.

Definition at line 263 of file certificate.cpp.

263 {
264 if (this != &other) {
265 impl_ = std::make_unique<certificate_impl>(*other.impl_);
266 }
267 return *this;
268}

References kcenon::pacs::security::other.

◆ serial_number()

auto kcenon::pacs::security::certificate::serial_number ( ) const -> std::string
nodiscard

Get the certificate serial number.

Returns
Serial number as hex string

Definition at line 428 of file certificate.cpp.

428 {
429 if (!impl_->is_loaded()) {
430 return "";
431 }
432
433 const ASN1_INTEGER* serial = X509_get_serialNumber(impl_->x509());
434 if (!serial) {
435 return "";
436 }
437
438 BIGNUM* bn = ASN1_INTEGER_to_BN(serial, nullptr);
439 if (!bn) {
440 return "";
441 }
442
443 char* hex = BN_bn2hex(bn);
444 BN_free(bn);
445
446 if (!hex) {
447 return "";
448 }
449
450 std::string result(hex);
451 OPENSSL_free(hex);
452 return result;
453}

References impl_.

◆ subject_common_name()

auto kcenon::pacs::security::certificate::subject_common_name ( ) const -> std::string
nodiscard

Get the common name from the subject.

Returns
Common name (CN) or empty string if not present

Definition at line 338 of file certificate.cpp.

338 {
339 if (!impl_->is_loaded()) {
340 return "";
341 }
342
343 X509_NAME* name = X509_get_subject_name(impl_->x509());
344 if (!name) {
345 return "";
346 }
347
348 int idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
349 if (idx < 0) {
350 return "";
351 }
352
353 X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
354 if (!entry) {
355 return "";
356 }
357
358 ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
359 if (!data) {
360 return "";
361 }
362
363 unsigned char* utf8 = nullptr;
364 int len = ASN1_STRING_to_UTF8(&utf8, data);
365 if (len < 0) {
366 return "";
367 }
368
369 std::string result(reinterpret_cast<char*>(utf8), static_cast<size_t>(len));
370 OPENSSL_free(utf8);
371 return result;
372}

References impl_, and name.

◆ subject_name()

auto kcenon::pacs::security::certificate::subject_name ( ) const -> std::string
nodiscard

Get the subject distinguished name.

Returns
Subject name (e.g., "CN=John Doe,O=Hospital,C=US")

Definition at line 320 of file certificate.cpp.

320 {
321 if (!impl_->is_loaded()) {
322 return "";
323 }
324
325 X509_NAME* name = X509_get_subject_name(impl_->x509());
326 if (!name) {
327 return "";
328 }
329
330 bio_ptr bio(BIO_new(BIO_s_mem()));
331 X509_NAME_print_ex(bio.get(), name, 0, XN_FLAG_RFC2253);
332
333 char* data = nullptr;
334 long len = BIO_get_mem_data(bio.get(), &data);
335 return std::string(data, static_cast<size_t>(len));
336}

References impl_, and name.

◆ subject_organization()

auto kcenon::pacs::security::certificate::subject_organization ( ) const -> std::string
nodiscard

Get the organization from the subject.

Returns
Organization (O) or empty string if not present

Definition at line 374 of file certificate.cpp.

374 {
375 if (!impl_->is_loaded()) {
376 return "";
377 }
378
379 X509_NAME* name = X509_get_subject_name(impl_->x509());
380 if (!name) {
381 return "";
382 }
383
384 int idx = X509_NAME_get_index_by_NID(name, NID_organizationName, -1);
385 if (idx < 0) {
386 return "";
387 }
388
389 X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
390 if (!entry) {
391 return "";
392 }
393
394 ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
395 if (!data) {
396 return "";
397 }
398
399 unsigned char* utf8 = nullptr;
400 int len = ASN1_STRING_to_UTF8(&utf8, data);
401 if (len < 0) {
402 return "";
403 }
404
405 std::string result(reinterpret_cast<char*>(utf8), static_cast<size_t>(len));
406 OPENSSL_free(utf8);
407 return result;
408}

References impl_, and name.

◆ thumbprint()

auto kcenon::pacs::security::certificate::thumbprint ( ) const -> std::string
nodiscard

Get the certificate thumbprint (SHA-256)

Returns
Thumbprint as hex string

Definition at line 455 of file certificate.cpp.

455 {
456 if (!impl_->is_loaded()) {
457 return "";
458 }
459
460 unsigned char hash[EVP_MAX_MD_SIZE];
461 unsigned int hash_len = 0;
462
463 if (X509_digest(impl_->x509(), EVP_sha256(), hash, &hash_len) != 1) {
464 return "";
465 }
466
467 std::string result;
468 result.reserve(hash_len * 2);
469
470 static const char hex_chars[] = "0123456789ABCDEF";
471 for (unsigned int i = 0; i < hash_len; ++i) {
472 result += hex_chars[(hash[i] >> 4) & 0x0F];
473 result += hex_chars[hash[i] & 0x0F];
474 }
475
476 return result;
477}
@ hash
Hash the value for research linkage.

References kcenon::pacs::security::hash, and impl_.

◆ to_der()

auto kcenon::pacs::security::certificate::to_der ( ) const -> std::vector<std::uint8_t>
nodiscard

Export certificate as DER bytes.

Returns
DER-encoded certificate

Definition at line 530 of file certificate.cpp.

530 {
531 if (!impl_->is_loaded()) {
532 return {};
533 }
534
535 unsigned char* data = nullptr;
536 int len = i2d_X509(impl_->x509(), &data);
537 if (len <= 0) {
538 return {};
539 }
540
541 std::vector<std::uint8_t> result(data, data + len);
542 OPENSSL_free(data);
543 return result;
544}

References impl_.

◆ to_pem()

auto kcenon::pacs::security::certificate::to_pem ( ) const -> std::string
nodiscard

Export certificate as PEM string.

Returns
PEM-encoded certificate

Definition at line 515 of file certificate.cpp.

515 {
516 if (!impl_->is_loaded()) {
517 return "";
518 }
519
520 bio_ptr bio(BIO_new(BIO_s_mem()));
521 if (PEM_write_bio_X509(bio.get(), impl_->x509()) != 1) {
522 return "";
523 }
524
525 char* data = nullptr;
526 long len = BIO_get_mem_data(bio.get(), &data);
527 return std::string(data, static_cast<size_t>(len));
528}

References impl_.

Friends And Related Symbol Documentation

◆ certificate_chain

friend class certificate_chain
friend

Definition at line 217 of file certificate.h.

Member Data Documentation

◆ impl_


The documentation for this class was generated from the following files: