Method: As2::Message.verify

Defined in:
lib/as2/message.rb

.verify(content:, signature_text:, certificate:) ⇒ Hash

Check that the signature is valid.

This confirms 2 things:

1. The `signature_text` is valid for `content`, ie: the `content` has
   not been altered.
2. The `signature_text` was generated by the party who owns `certificate`,
   ie: The same private key generated `signature_text` and `certificate`.

Parameters:

  • content (String)
  • signature_text (String)
  • certificate (OpenSSL::X509::Certificate)

Returns:

  • (Hash)
    • :valid [boolean] was the verification successful or not?

    • :error [String, nil] a verification error message.

      will be empty when `valid` is true.
      


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/as2/message.rb', line 56

def self.verify(content:, signature_text:, certificate:)
  begin
    signature = OpenSSL::PKCS7.new(signature_text)

    # using an empty CA store. see notes on NOVERIFY flag below.
    store = OpenSSL::X509::Store.new

    # notes on verification process and flags used
    #
    # ## NOINTERN
    #
    # > If PKCS7_NOINTERN is set the certificates in the message itself are
    # > not searched when locating the signer's certificate. This means that
    # > all the signers certificates must be in the certs parameter.
    # >
    # > One application of PKCS7_NOINTERN is to only accept messages signed
    # > by a small number of certificates. The acceptable certificates would
    # > be passed in the certs parameter. In this case if the signer is not
    # > one of the certificates supplied in certs then the verify will fail
    # > because the signer cannot be found.
    #
    # https://www.openssl.org/docs/manmaster/man3/PKCS7_verify.html
    #
    # we want this so we can be sure that the `partner_certificate` we supply
    # was actually used to sign the message. otherwise we could get a positive
    # verification even if `partner_certificate` didn't sign the message
    # we're checking.
    #
    # ## NOVERIFY
    #
    # > If PKCS7_NOVERIFY is set the signer's certificates are not chain verified.
    #
    # ie: we won't attempt to connect signer (in the first param) to a root
    # CA (in `store`, which is empty). alternately, we could instead remove
    # this flag, and add `partner_certificate` to `store`. but what's the point?
    # we'd only be verifying that `partner_certificate` is connected to `partner_certificate`.
    valid = signature.verify([certificate], store, content, OpenSSL::PKCS7::NOVERIFY | OpenSSL::PKCS7::NOINTERN)

    # when `signature.verify` fails, signature.error_string will be populated.
    error = signature.error_string
  rescue => e
    valid = false
    error = "#{e.class}: #{e.message}"
  end

  {
    valid: valid,
    error: error
  }
end