# frozen_string_literal: true
|
|
|
|
# gem install base32
|
|
|
|
require 'openssl'
|
|
require 'base32'
|
|
require 'pp'
|
|
require 'resolv'
|
|
|
|
def pad(base32str)
|
|
base32str +
|
|
case base32str.length % 8
|
|
when 2 then '======'
|
|
when 4 then '===='
|
|
when 5 then '==='
|
|
when 7 then '='
|
|
else ''
|
|
end
|
|
end
|
|
|
|
def rm_pad(base32text)
|
|
base32text.gsub '=', ''
|
|
end
|
|
|
|
def download(pub_key_link)
|
|
Resolv::DNS.open do |dns|
|
|
resource = dns.getresource(pub_key_link, Resolv::DNS::Resource::IN::TXT)
|
|
key = resource.data.split('\n').join("\n")
|
|
unless key.include? '-----BEGIN PUBLIC KEY-----'
|
|
key = "-----BEGIN PUBLIC KEY-----\n#{key}\n-----END PUBLIC KEY-----\n"
|
|
end
|
|
return key
|
|
end
|
|
nil
|
|
end
|
|
|
|
def parse_and_verify_qr(qr)
|
|
(schema, qrtype, version, signature_b32, pub_key_link, payload) = qr.split(/:/)
|
|
|
|
puts "Parsed QR\t #{schema} #{qrtype} #{version} #{signature_b32} #{pub_key_link} #{payload}"
|
|
|
|
sha_payload = Digest::SHA256.digest(payload)
|
|
signature = Base32.decode(pad(signature_b32))
|
|
|
|
puts "Payload Bytes\t #{sha_payload.bytes}"
|
|
puts "Signature DER\t #{signature.bytes}"
|
|
|
|
vk = OpenSSL::PKey::EC.new(download(pub_key_link))
|
|
verified = vk.dsa_verify_asn1(sha_payload, signature)
|
|
|
|
puts "\nVerify Payload\t #{verified}"
|
|
|
|
verified
|
|
end
|
|
|
|
def sign_and_format_qr(sk, schema, qrtype, version, pub_key_link, payload)
|
|
sha_payload = Digest::SHA256.digest(payload)
|
|
sig = sk.dsa_sign_asn1(sha_payload)
|
|
|
|
formatted_sig = rm_pad(Base32.encode(sig))
|
|
|
|
[schema, qrtype, version, formatted_sig, pub_key_link, payload].join ':'
|
|
end
|
|
|
|
uri = 'CRED:STATUS:2:GBCAEIAHV2J6PWDSYVLI67RN55WVHIMUTKLFF5GZ4NPHPZ7ZSIJE4MP5M4BCAU6QVDHUP4RQCPXW6XJDAM54VMZ7XURUN34WFT2RWL5ETTZDNHUF:KEYS.PATHCHECK.ORG:1/BUQHHANUB4Z5KHBZTYCWMNI4RQ6CP5WFVVQCUXYHCQVY5WLDDFPA/'
|
|
|
|
puts ''
|
|
puts 'Loading hardcoded QR'
|
|
puts ''
|
|
|
|
parse_and_verify_qr(uri)
|
|
|
|
puts ''
|
|
puts 'Resigning same payload'
|
|
puts ''
|
|
|
|
(schema, qrtype, version, _, pub_key_link, payload) = uri.split(/:/)
|
|
sk = OpenSSL::PKey::EC.new(File.read('keys/ecdsa_private_key'))
|
|
new_qr = sign_and_format_qr(sk, schema, qrtype, version, pub_key_link, payload)
|
|
|
|
puts "New QR Signed\t #{new_qr}"
|
|
puts ''
|
|
|
|
parse_and_verify_qr(new_qr)
|