Class: PqcAsn1::DER::KeyInfo
- Inherits:
-
Object
- Object
- PqcAsn1::DER::KeyInfo
- Defined in:
- lib/pqc_asn1.rb
Instance Attribute Summary collapse
-
#format ⇒ Symbol
readonly
:spki or :pkcs8.
-
#key ⇒ String, PqcAsn1::SecureBuffer
readonly
Key bytes.
-
#oid ⇒ PqcAsn1::OID
readonly
Parsed algorithm OID.
-
#parameters ⇒ String?
readonly
Raw AlgorithmIdentifier parameter bytes (ASCII-8BIT, frozen), or nil when absent.
-
#public_key ⇒ String?
readonly
Optional public key from the PKCS#8 OneAsymmetricKey publicKey [1] field, or nil if absent.
Class Method Summary collapse
-
.detect_format(der) ⇒ Symbol
Detect whether DER bytes are SPKI or PKCS#8.
Instance Method Summary collapse
- #==(other) ⇒ Boolean (also: #eql?)
-
#algorithm ⇒ String
Human-readable algorithm name (e.g. "ML_DSA_44"), or the dotted OID string if the algorithm is not a known constant.
-
#deconstruct_keys(keys) ⇒ Hash{Symbol => Object}
Pattern-matching support (Ruby 2.7+).
-
#hash ⇒ Integer
For :pkcs8, the secret key is excluded from the hash to avoid leaking key material into hash tables or log output.
-
#initialize(oid, parameters, key, public_key, format) ⇒ KeyInfo
constructor
A new instance of KeyInfo.
-
#inspect ⇒ String
Key bytes are never shown for :pkcs8.
-
#to_der ⇒ String, PqcAsn1::SecureBuffer
Re-encode this KeyInfo back to DER bytes.
- #to_h ⇒ Hash{Symbol => Object}
-
#to_pem ⇒ String
Re-encode to PEM.
Constructor Details
#initialize(oid, parameters, key, public_key, format) ⇒ KeyInfo
Returns a new instance of KeyInfo.
297 298 299 300 301 302 303 304 |
# File 'lib/pqc_asn1.rb', line 297 def initialize(oid, parameters, key, public_key, format) @oid = oid @parameters = parameters @key = key @public_key = public_key @format = format freeze end |
Instance Attribute Details
#format ⇒ Symbol (readonly)
Returns :spki or :pkcs8.
294 295 296 |
# File 'lib/pqc_asn1.rb', line 294 def format @format end |
#key ⇒ String, PqcAsn1::SecureBuffer (readonly)
Returns key bytes. For :spki this is the public key (frozen String). For :pkcs8 this is a SecureBuffer holding the secret key.
287 288 289 |
# File 'lib/pqc_asn1.rb', line 287 def key @key end |
#oid ⇒ PqcAsn1::OID (readonly)
Returns parsed algorithm OID.
278 279 280 |
# File 'lib/pqc_asn1.rb', line 278 def oid @oid end |
#parameters ⇒ String? (readonly)
Returns raw AlgorithmIdentifier parameter bytes (ASCII-8BIT, frozen), or nil when absent.
282 283 284 |
# File 'lib/pqc_asn1.rb', line 282 def parameters @parameters end |
#public_key ⇒ String? (readonly)
Returns optional public key from the PKCS#8 OneAsymmetricKey publicKey [1] field, or nil if absent.
291 292 293 |
# File 'lib/pqc_asn1.rb', line 291 def public_key @public_key end |
Class Method Details
.detect_format(der) ⇒ Symbol
Detect whether DER bytes are SPKI or PKCS#8.
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/pqc_asn1.rb', line 276 class KeyInfo # @return [PqcAsn1::OID] parsed algorithm OID attr_reader :oid # @return [String, nil] raw AlgorithmIdentifier parameter bytes # (ASCII-8BIT, frozen), or nil when absent. attr_reader :parameters # @return [String, PqcAsn1::SecureBuffer] key bytes. # For :spki this is the public key (frozen String). # For :pkcs8 this is a SecureBuffer holding the secret key. attr_reader :key # @return [String, nil] optional public key from the PKCS#8 # OneAsymmetricKey publicKey [1] field, or nil if absent. attr_reader :public_key # @return [Symbol] :spki or :pkcs8 attr_reader :format # @api private — constructed by DER.parse_spki / DER.parse_pkcs8 via C extension def initialize(oid, parameters, key, public_key, format) @oid = oid @parameters = parameters @key = key @public_key = public_key @format = format freeze end # @return [Hash{Symbol => Object}] def to_h {oid: @oid, parameters: @parameters, key: @key, public_key: @public_key, format: @format} end # Pattern-matching support (Ruby 2.7+). # When +keys+ is non-nil, only the requested keys are returned, # avoiding unnecessary access to fields like +key+ (a SecureBuffer # that requires mprotect toggling). # @param keys [Array<Symbol>, nil] # @return [Hash{Symbol => Object}] def deconstruct_keys(keys) return to_h if keys.nil? keys.each_with_object({}) do |k, h| case k when :oid then h[:oid] = @oid when :parameters then h[:parameters] = @parameters when :key then h[:key] = @key when :public_key then h[:public_key] = @public_key when :format then h[:format] = @format end end end # @param other [Object] # @return [Boolean] def ==(other) other.is_a?(KeyInfo) && @oid == other.oid && @parameters == other.parameters && @key == other.key && @public_key == other.public_key && @format == other.format end alias_method :eql?, :== # @return [Integer] # For :pkcs8, the secret key is excluded from the hash to avoid # leaking key material into hash tables or log output. def hash if @format == :pkcs8 [@oid, @parameters, @public_key, @format].hash else [@oid, @parameters, @key, @public_key, @format].hash end end # Human-readable algorithm name (e.g. "ML_DSA_44"), or the dotted # OID string if the algorithm is not a known constant. # @return [String] def algorithm @oid.name || @oid.dotted end # Re-encode this KeyInfo back to DER bytes. # For :spki returns a frozen binary String. # For :pkcs8 returns a SecureBuffer. # @return [String, PqcAsn1::SecureBuffer] def to_der opts = {validate: false} opts[:parameters] = @parameters if @parameters opts[:public_key] = @public_key if @public_key case @format when :spki PqcAsn1::DER.build_spki(@oid, @key, **opts) when :pkcs8 PqcAsn1::DER.build_pkcs8(@oid, @key, **opts) else raise PqcAsn1::Error, "cannot re-encode format #{@format.inspect}" end end # Re-encode to PEM. Uses "PUBLIC KEY" for :spki and # "PRIVATE KEY" for :pkcs8. # # Security caveat: for :pkcs8, the returned PEM String is an # ordinary Ruby String on the heap, NOT a SecureBuffer. The # PEM text is not mmap-protected, not mlock'd, and may be # swapped to disk or copied by the GC compactor. Discard the # result as soon as possible to limit exposure of secret key # material. # # @return [String] US-ASCII PEM string def to_pem der = to_der label = case @format when :spki then "PUBLIC KEY" when :pkcs8 then "PRIVATE KEY" else raise PqcAsn1::Error, "cannot PEM-encode format #{@format.inspect}" end PqcAsn1::PEM.encode(der, label) end # Key bytes are never shown for :pkcs8. # @return [String] def inspect alg = @parameters ? " params=#{@parameters.bytesize}B" : "" pk = @public_key ? " public_key=#{@public_key.bytesize}B" : "" name = algorithm case @format when :spki "#<PqcAsn1::DER::KeyInfo format=:spki oid=#{name}#{alg} key=#{@key.bytesize}B>" when :pkcs8 "#<PqcAsn1::DER::KeyInfo format=:pkcs8 oid=#{name}#{alg} key=REDACTED#{pk}>" else "#<PqcAsn1::DER::KeyInfo format=#{@format.inspect}>" end end end |
Instance Method Details
#==(other) ⇒ Boolean Also known as: eql?
334 335 336 337 338 339 340 341 |
# File 'lib/pqc_asn1.rb', line 334 def ==(other) other.is_a?(KeyInfo) && @oid == other.oid && @parameters == other.parameters && @key == other.key && @public_key == other.public_key && @format == other.format end |
#algorithm ⇒ String
Human-readable algorithm name (e.g. "ML_DSA_44"), or the dotted OID string if the algorithm is not a known constant.
359 360 361 |
# File 'lib/pqc_asn1.rb', line 359 def algorithm @oid.name || @oid.dotted end |
#deconstruct_keys(keys) ⇒ Hash{Symbol => Object}
Pattern-matching support (Ruby 2.7+).
When keys is non-nil, only the requested keys are returned,
avoiding unnecessary access to fields like key (a SecureBuffer
that requires mprotect toggling).
318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/pqc_asn1.rb', line 318 def deconstruct_keys(keys) return to_h if keys.nil? keys.each_with_object({}) do |k, h| case k when :oid then h[:oid] = @oid when :parameters then h[:parameters] = @parameters when :key then h[:key] = @key when :public_key then h[:public_key] = @public_key when :format then h[:format] = @format end end end |
#hash ⇒ Integer
For :pkcs8, the secret key is excluded from the hash to avoid leaking key material into hash tables or log output.
348 349 350 351 352 353 354 |
# File 'lib/pqc_asn1.rb', line 348 def hash if @format == :pkcs8 [@oid, @parameters, @public_key, @format].hash else [@oid, @parameters, @key, @public_key, @format].hash end end |
#inspect ⇒ String
Key bytes are never shown for :pkcs8.
406 407 408 409 410 411 412 413 414 415 416 417 418 |
# File 'lib/pqc_asn1.rb', line 406 def inspect alg = @parameters ? " params=#{@parameters.bytesize}B" : "" pk = @public_key ? " public_key=#{@public_key.bytesize}B" : "" name = algorithm case @format when :spki "#<PqcAsn1::DER::KeyInfo format=:spki oid=#{name}#{alg} key=#{@key.bytesize}B>" when :pkcs8 "#<PqcAsn1::DER::KeyInfo format=:pkcs8 oid=#{name}#{alg} key=REDACTED#{pk}>" else "#<PqcAsn1::DER::KeyInfo format=#{@format.inspect}>" end end |
#to_der ⇒ String, PqcAsn1::SecureBuffer
Re-encode this KeyInfo back to DER bytes. For :spki returns a frozen binary String. For :pkcs8 returns a SecureBuffer.
367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/pqc_asn1.rb', line 367 def to_der opts = {validate: false} opts[:parameters] = @parameters if @parameters opts[:public_key] = @public_key if @public_key case @format when :spki PqcAsn1::DER.build_spki(@oid, @key, **opts) when :pkcs8 PqcAsn1::DER.build_pkcs8(@oid, @key, **opts) else raise PqcAsn1::Error, "cannot re-encode format #{@format.inspect}" end end |
#to_h ⇒ Hash{Symbol => Object}
307 308 309 310 |
# File 'lib/pqc_asn1.rb', line 307 def to_h {oid: @oid, parameters: @parameters, key: @key, public_key: @public_key, format: @format} end |
#to_pem ⇒ String
Re-encode to PEM. Uses "PUBLIC KEY" for :spki and "PRIVATE KEY" for :pkcs8.
Security caveat: for :pkcs8, the returned PEM String is an ordinary Ruby String on the heap, NOT a SecureBuffer. The PEM text is not mmap-protected, not mlock'd, and may be swapped to disk or copied by the GC compactor. Discard the result as soon as possible to limit exposure of secret key material.
393 394 395 396 397 398 399 400 401 402 |
# File 'lib/pqc_asn1.rb', line 393 def to_pem der = to_der label = case @format when :spki then "PUBLIC KEY" when :pkcs8 then "PRIVATE KEY" else raise PqcAsn1::Error, "cannot PEM-encode format #{@format.inspect}" end PqcAsn1::PEM.encode(der, label) end |