feat(timestamp): ensure signature is openssl compatible
This commit is contained in:
parent
86cda6a0b9
commit
fe8bd15939
2 changed files with 80 additions and 0 deletions
|
@ -12,5 +12,38 @@ class BillSignatureService
|
||||||
signature = Certigna::API.timestamp(bill.digest)
|
signature = Certigna::API.timestamp(bill.digest)
|
||||||
bill.set_signature(signature, day)
|
bill.set_signature(signature, day)
|
||||||
bill.save!
|
bill.save!
|
||||||
|
|
||||||
|
ensure_valid_signature(bill.reload)
|
||||||
|
rescue => error
|
||||||
|
operations.each { |o| o.update(bill_signature: nil) }
|
||||||
|
bill&.destroy
|
||||||
|
raise error
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ensure_valid_signature(bill)
|
||||||
|
Dir.mktmpdir do |dir|
|
||||||
|
operations_path = File.join(dir, 'operations')
|
||||||
|
File.write(operations_path, bill.serialized.download, mode: 'wb')
|
||||||
|
|
||||||
|
signature_path = File.join(dir, 'signature')
|
||||||
|
File.write(signature_path, bill.signature.download, mode: 'wb')
|
||||||
|
|
||||||
|
authorities_path = Rails.application.config.root.join('app', 'lib', 'certigna', 'authorities.crt').to_s
|
||||||
|
|
||||||
|
verify_cmd = "openssl ts -verify -CAfile #{authorities_path.shellescape} -data #{operations_path.shellescape} -in #{signature_path.shellescape} -token_in"
|
||||||
|
|
||||||
|
openssl_errors = nil
|
||||||
|
openssl_output = nil
|
||||||
|
|
||||||
|
process_status = Open3.popen3(verify_cmd) do |_stdin, stdout, stderr, wait_thr|
|
||||||
|
openssl_errors = stderr.read
|
||||||
|
openssl_output = stdout.read
|
||||||
|
wait_thr.value
|
||||||
|
end
|
||||||
|
|
||||||
|
if !process_status.success? || openssl_output&.strip != 'Verification: OK'
|
||||||
|
raise StandardError, "openssl verification failed: #{openssl_errors}"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,4 +32,51 @@ describe BillSignatureService do
|
||||||
it { is_expected.to eq 0 }
|
it { is_expected.to eq 0 }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".sign_operations" do
|
||||||
|
let(:date) { Date.today }
|
||||||
|
|
||||||
|
let(:operations_hash) { [['1', 'hash1'], ['2', 'hash2']] }
|
||||||
|
let(:operations) do
|
||||||
|
operations_hash
|
||||||
|
.map { |id, digest| DossierOperationLog.new(id:, digest:, operation: 'accepter') }
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:timestamp) { File.read('spec/fixtures/files/bill_signature/signature.der') }
|
||||||
|
|
||||||
|
subject { BillSignatureService.sign_operations(operations, date) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
DossierOperationLog.where(id: [1, 2]).destroy_all
|
||||||
|
|
||||||
|
expect(Certigna::API).to receive(:timestamp).and_return(timestamp)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when everything is fine" do
|
||||||
|
it do
|
||||||
|
expect { subject }.not_to raise_error
|
||||||
|
expect(BillSignature.count).to eq(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the digest does not match with the pre recorded timestamp token" do
|
||||||
|
let(:operations_hash) { [['1', 'hash1'], ['2', 'hash3']] }
|
||||||
|
|
||||||
|
it do
|
||||||
|
expect { subject }.to raise_error(/La validation a échoué : signature ne correspond pas à l’empreinte/)
|
||||||
|
expect(BillSignature.count).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the timestamp token cannot be verified by openssl" do
|
||||||
|
let(:timestamp) do
|
||||||
|
File.read('spec/fixtures/files/bill_signature/signature.der').tap { |s| s[-1] = 'd' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it do
|
||||||
|
expect { subject }.to raise_error(/openssl verification failed/)
|
||||||
|
expect(BillSignature.count).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue