Module: Legion::Audit::HashChain

Defined in:
lib/legion/audit/hash_chain.rb

Constant Summary collapse

ALGORITHM =
'SHA256'
GENESIS_HASH =
('0' * 64).freeze
CANONICAL_FIELDS =
%i[principal_id action resource source status detail created_at previous_hash].freeze

Class Method Summary collapse

Class Method Details

.canonical_payload(record) ⇒ Object



19
20
21
# File 'lib/legion/audit/hash_chain.rb', line 19

def canonical_payload(record)
  CANONICAL_FIELDS.map { |f| "#{f}:#{record[f]}" }.join('|')
end

.compute_hash(record) ⇒ Object



14
15
16
17
# File 'lib/legion/audit/hash_chain.rb', line 14

def compute_hash(record)
  payload = canonical_payload(record)
  OpenSSL::Digest.new(ALGORITHM).hexdigest(payload)
end

.verify_chain(records) ⇒ Object



23
24
25
26
27
28
29
# File 'lib/legion/audit/hash_chain.rb', line 23

def verify_chain(records)
  broken = []
  records.each_cons(2) do |prev, curr|
    broken << { id: curr[:id], expected: prev[:record_hash], got: curr[:previous_hash] } unless curr[:previous_hash] == prev[:record_hash]
  end
  { valid: broken.empty?, broken_links: broken, records_checked: records.size }
end