Class: BSV::Auth::VerifiableCertificate
- Inherits:
-
Certificate
- Object
- Certificate
- BSV::Auth::VerifiableCertificate
- Defined in:
- lib/bsv/auth/verifiable_certificate.rb
Overview
A Certificate subclass for selective field revelation on the verifier side.
VerifiableCertificate holds a verifier-specific keyring — a map from field names to Base64-encoded symmetric keys encrypted for the verifier. Calling #decrypt_fields decrypts each entry in the keyring using the verifier’s wallet and then uses the recovered key to decrypt the corresponding field value from the base certificate.
Protocol details
Each keyring entry is decrypted via BRC-42 key derivation:
-
Protocol: [2, ‘certificate field encryption’]
-
Key ID: “#{serial_number} #{field_name}”
-
Counterparty: the certificate
subjectpublic key
Wallet parameters are duck-typed — any object responding to :decrypt is accepted. No direct dependency on BSV::Wallet::ProtoWallet is introduced here.
Constant Summary
Constants inherited from Certificate
Certificate::CERT_FIELD_ENC_PROTOCOL, Certificate::CERT_SIG_PROTOCOL
Instance Attribute Summary collapse
-
#decrypted_fields ⇒ Hash?
readonly
Field name → decrypted plaintext string, or nil before decryption.
-
#keyring ⇒ Hash
readonly
Field name → Base64-encoded verifier-specific encrypted key.
Attributes inherited from Certificate
#certifier, #fields, #revocation_outpoint, #serial_number, #signature, #subject, #type
Class Method Summary collapse
-
.from_certificate(certificate, keyring) ⇒ VerifiableCertificate
Construct a VerifiableCertificate from a base Certificate and a keyring.
-
.from_hash(hash) ⇒ VerifiableCertificate
Construct a VerifiableCertificate from a plain Hash.
Instance Method Summary collapse
-
#decrypt_fields(verifier_wallet, privileged: false, privileged_reason: nil) ⇒ Hash
Decrypt selectively revealed certificate fields using the verifier’s wallet.
-
#initialize(type:, serial_number:, subject:, certifier:, revocation_outpoint:, fields:, keyring:, signature: nil, decrypted_fields: nil) ⇒ VerifiableCertificate
constructor
A new instance of VerifiableCertificate.
-
#to_h ⇒ Hash
Return the certificate as a plain Hash with snake_case keys, including
keyringanddecrypted_fields(if present).
Methods inherited from Certificate
certificate_field_encryption_details, from_binary, #sign, #to_binary, #verify
Constructor Details
#initialize(type:, serial_number:, subject:, certifier:, revocation_outpoint:, fields:, keyring:, signature: nil, decrypted_fields: nil) ⇒ VerifiableCertificate
Returns a new instance of VerifiableCertificate.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/bsv/auth/verifiable_certificate.rb', line 45 def initialize(type:, serial_number:, subject:, certifier:, revocation_outpoint:, fields:, keyring:, signature: nil, decrypted_fields: nil) super( type: type, serial_number: serial_number, subject: subject, certifier: certifier, revocation_outpoint: revocation_outpoint, fields: fields, signature: signature ) @keyring = keyring @decrypted_fields = decrypted_fields end |
Instance Attribute Details
#decrypted_fields ⇒ Hash? (readonly)
Returns field name → decrypted plaintext string, or nil before decryption.
34 35 36 |
# File 'lib/bsv/auth/verifiable_certificate.rb', line 34 def decrypted_fields @decrypted_fields end |
#keyring ⇒ Hash (readonly)
Returns field name → Base64-encoded verifier-specific encrypted key.
31 32 33 |
# File 'lib/bsv/auth/verifiable_certificate.rb', line 31 def keyring @keyring end |
Class Method Details
.from_certificate(certificate, keyring) ⇒ VerifiableCertificate
Construct a VerifiableCertificate from a base Certificate and a keyring.
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/bsv/auth/verifiable_certificate.rb', line 67 def self.from_certificate(certificate, keyring) new( type: certificate.type, serial_number: certificate.serial_number, subject: certificate.subject, certifier: certificate.certifier, revocation_outpoint: certificate.revocation_outpoint, fields: certificate.fields, keyring: keyring, signature: certificate.signature ) end |
.from_hash(hash) ⇒ VerifiableCertificate
Construct a VerifiableCertificate from a plain Hash.
Accepts both snake_case and camelCase key variants.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/bsv/auth/verifiable_certificate.rb', line 86 def self.from_hash(hash) h = normalise_hash_keys(hash) new( type: h['type'], serial_number: h['serial_number'], subject: h['subject'], certifier: h['certifier'], revocation_outpoint: h['revocation_outpoint'], fields: h['fields'] || {}, keyring: h['keyring'] || {}, signature: h['signature'], decrypted_fields: h['decrypted_fields'] ) end |
Instance Method Details
#decrypt_fields(verifier_wallet, privileged: false, privileged_reason: nil) ⇒ Hash
Decrypt selectively revealed certificate fields using the verifier’s wallet.
Algorithm:
-
Raises if
keyringis nil or empty. -
For each field in
keyring:-
Decrypts the encrypted revelation key via
verifier_wallet.decrypt, using protocol [2, ‘certificate field encryption’] and key_id “#{serial_number} #{field_name}”, counterparty = subject. -
Uses the recovered bytes as a Primitives::SymmetricKey.
-
Decrypts the corresponding encrypted field value.
-
Stores the UTF-8 plaintext.
-
-
Caches and returns the decrypted fields hash.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/bsv/auth/verifiable_certificate.rb', line 120 def decrypt_fields(verifier_wallet, privileged: false, privileged_reason: nil) raise ArgumentError, 'A keyring is required to decrypt certificate fields for the verifier.' if @keyring.nil? || @keyring.empty? begin result = {} @keyring.each do |field_name, encrypted_key_b64| dec_args = { ciphertext: Base64.strict_decode64(encrypted_key_b64).bytes, counterparty: @subject, privileged: privileged, privileged_reason: privileged_reason }.merge(Certificate.certificate_field_encryption_details(field_name, @serial_number)) field_revelation_key = verifier_wallet.decrypt(dec_args)[:plaintext] sym_key = BSV::Primitives::SymmetricKey.new(field_revelation_key.pack('C*')) decrypted_bytes = sym_key.decrypt(Base64.strict_decode64(@fields[field_name])) result[field_name] = decrypted_bytes.force_encoding('UTF-8') end @decrypted_fields = result result rescue ArgumentError raise rescue StandardError raise 'Failed to decrypt selectively revealed certificate fields using keyring.' end end |
#to_h ⇒ Hash
Return the certificate as a plain Hash with snake_case keys, including keyring and decrypted_fields (if present).
153 154 155 156 157 158 |
# File 'lib/bsv/auth/verifiable_certificate.rb', line 153 def to_h h = super h['keyring'] = @keyring.dup h['decrypted_fields'] = @decrypted_fields.dup if @decrypted_fields h end |