Module: Nfe::CertificateValidator
- Defined in:
- lib/nfe/certificate.rb,
sig/nfe/certificate.rbs
Overview
Local-only validation and inspection of A1 digital certificates (PKCS#12,
+.pfx+/+.p12+). Uses only the openssl stdlib — no network access, no new
runtime dependency.
The PKCS#12 bytes and password are handled in-memory only and never logged, persisted, or echoed into exception messages.
Constant Summary collapse
- DEFAULT_THRESHOLD_DAYS =
Default window (in days) within which a certificate is "expiring soon".
30- SECONDS_PER_DAY =
Number of seconds in a day, for day-delta math.
86_400
Class Method Summary collapse
- .coerce_time(value) ⇒ Object private
-
.days_until_expiration(not_after) ⇒ Integer
Whole days from now until
not_after(negative once expired). -
.expiring_soon?(not_after, threshold_days = DEFAULT_THRESHOLD_DAYS) ⇒ Boolean
truewhen expiry is within[0, threshold_days). -
.supported_format?(filename) ⇒ Boolean
truefor +.pfx+/+.p12+ (case-insensitive). -
.validate(der_bytes, password) ⇒ Nfe::CertificateInfo
Parse PKCS#12 bytes with the given password and extract certificate metadata.
Instance Method Summary collapse
- #self?.coerce_time ⇒ Time
- #self?.days_until_expiration ⇒ Integer
- #self?.expiring_soon? ⇒ Boolean
- #self?.supported_format? ⇒ Boolean
- #self?.validate ⇒ Nfe::CertificateInfo
Class Method Details
.coerce_time(value) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
83 84 85 |
# File 'lib/nfe/certificate.rb', line 83 def coerce_time(value) value.is_a?(Time) ? value : Time.parse(value.to_s) end |
.days_until_expiration(not_after) ⇒ Integer
Whole days from now until not_after (negative once expired).
69 70 71 72 |
# File 'lib/nfe/certificate.rb', line 69 def days_until_expiration(not_after) expiry = coerce_time(not_after) ((expiry - Time.now) / SECONDS_PER_DAY).floor end |
.expiring_soon?(not_after, threshold_days = DEFAULT_THRESHOLD_DAYS) ⇒ Boolean
Returns true when expiry is within [0, threshold_days).
77 78 79 80 |
# File 'lib/nfe/certificate.rb', line 77 def expiring_soon?(not_after, threshold_days = DEFAULT_THRESHOLD_DAYS) days = days_until_expiration(not_after) days >= 0 && days < threshold_days end |
.supported_format?(filename) ⇒ Boolean
Returns true for +.pfx+/+.p12+ (case-insensitive).
37 38 39 40 |
# File 'lib/nfe/certificate.rb', line 37 def supported_format?(filename) ext = filename.to_s.downcase.split(".").last %w[pfx p12].include?(ext) end |
.validate(der_bytes, password) ⇒ Nfe::CertificateInfo
Parse PKCS#12 bytes with the given password and extract certificate metadata.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/nfe/certificate.rb', line 50 def validate(der_bytes, password) pkcs12 = OpenSSL::PKCS12.new(der_bytes, password) cert = pkcs12.certificate CertificateInfo.new( subject: cert.subject.to_s, issuer: cert.issuer.to_s, not_before: cert.not_before, not_after: cert.not_after, serial_number: cert.serial.to_s ) rescue OpenSSL::OpenSSLError, ArgumentError, TypeError raise Nfe::InvalidRequestError, "Certificado ou senha inválidos" end |
Instance Method Details
#self?.coerce_time ⇒ Time
43 |
# File 'sig/nfe/certificate.rbs', line 43
def self?.coerce_time: (untyped value) -> Time
|
#self?.days_until_expiration ⇒ Integer
39 |
# File 'sig/nfe/certificate.rbs', line 39
def self?.days_until_expiration: ((Time | String) not_after) -> Integer
|
#self?.expiring_soon? ⇒ Boolean
41 |
# File 'sig/nfe/certificate.rbs', line 41
def self?.expiring_soon?: ((Time | String) not_after, ?Integer threshold_days) -> bool
|
#self?.supported_format? ⇒ Boolean
35 |
# File 'sig/nfe/certificate.rbs', line 35
def self?.supported_format?: (String? filename) -> bool
|
#self?.validate ⇒ Nfe::CertificateInfo
37 |
# File 'sig/nfe/certificate.rbs', line 37
def self?.validate: (String der_bytes, String password) -> Nfe::CertificateInfo
|