You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
11 KiB

Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
Add support for latest HTTP Signatures spec draft (#14556) * Add support for latest HTTP Signatures spec draft https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html - add support for the “hs2019” signature algorithm (assumed to be equivalent to RSA-SHA256, since we do not have a mechanism to specify the algorithm within the key metadata yet) - add support for (created) and (expires) pseudo-headers and related signature parameters, when using the hs2019 signature algorithm - adjust default “headers” parameter while being backwards-compatible with previous implementation - change the acceptable time window logic from 12 hours surrounding the “date” header to accepting signatures created up to 1 hour in the future and expiring up to 1 hour in the past (but only allowing expiration dates up to 12 hours after the creation date) This doesn't conform with the current draft, as it doesn't permit accounting for clock skew. This, however, should be addressed in a next version of the draft: https://github.com/httpwg/http-extensions/pull/1235 * Add additional signature requirements * Rewrite signature params parsing using Parslet * Make apparent which signature algorithm Mastodon on verification failure Mastodon uses RSASSA-PKCS1-v1_5, which is not recommended for new applications, and new implementers may thus unknowingly use RSASSA-PSS. * Add workaround for PeerTube's invalid signature header The previous parser allowed incorrect Signature headers, such as those produced by old versions of the `http-signature` node.js package, and seemingly used by PeerTube. This commit adds a workaround for that. * Fix `signature_key_id` raising an exception Previously, parsing failures would result in `signature_key_id` being nil, but the parser changes made that result in an exception. This commit changes the `signature_key_id` method to return `nil` in case of parsing failures. * Move extra HTTP signature helper methods to private methods * Relax (request-target) requirement to (request-target) || digest This lets requests from Plume work without lowering security significantly.
3 years ago
  1. # frozen_string_literal: true
  2. # Implemented according to HTTP signatures (Draft 6)
  3. # <https://tools.ietf.org/html/draft-cavage-http-signatures-06>
  4. module SignatureVerification
  5. extend ActiveSupport::Concern
  6. include DomainControlHelper
  7. EXPIRATION_WINDOW_LIMIT = 12.hours
  8. CLOCK_SKEW_MARGIN = 1.hour
  9. class SignatureVerificationError < StandardError; end
  10. class SignatureParamsParser < Parslet::Parser
  11. rule(:token) { match("[0-9a-zA-Z!#$%&'*+.^_`|~-]").repeat(1).as(:token) }
  12. rule(:quoted_string) { str('"') >> (qdtext | quoted_pair).repeat.as(:quoted_string) >> str('"') }
  13. # qdtext and quoted_pair are not exactly according to spec but meh
  14. rule(:qdtext) { match('[^\\\\"]') }
  15. rule(:quoted_pair) { str('\\') >> any }
  16. rule(:bws) { match('\s').repeat }
  17. rule(:param) { (token.as(:key) >> bws >> str('=') >> bws >> (token | quoted_string).as(:value)).as(:param) }
  18. rule(:comma) { bws >> str(',') >> bws }
  19. # Old versions of node-http-signature add an incorrect "Signature " prefix to the header
  20. rule(:buggy_prefix) { str('Signature ') }
  21. rule(:params) { buggy_prefix.maybe >> (param >> (comma >> param).repeat).as(:params) }
  22. root(:params)
  23. end
  24. class SignatureParamsTransformer < Parslet::Transform
  25. rule(params: subtree(:param)) do
  26. (param.is_a?(Array) ? param : [param]).each_with_object({}) { |(key, value), hash| hash[key] = value }
  27. end
  28. rule(param: { key: simple(:key), value: simple(:val) }) do
  29. [key, val]
  30. end
  31. rule(quoted_string: simple(:string)) do
  32. string.to_s
  33. end
  34. rule(token: simple(:string)) do
  35. string.to_s
  36. end
  37. end
  38. def require_account_signature!
  39. render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account
  40. end
  41. def require_actor_signature!
  42. render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_actor
  43. end
  44. def signed_request?
  45. request.headers['Signature'].present?
  46. end
  47. def signature_verification_failure_reason
  48. @signature_verification_failure_reason
  49. end
  50. def signature_verification_failure_code
  51. @signature_verification_failure_code || 401
  52. end
  53. def signature_key_id
  54. signature_params['keyId']
  55. rescue SignatureVerificationError
  56. nil
  57. end
  58. def signed_request_account
  59. signed_request_actor.is_a?(Account) ? signed_request_actor : nil
  60. end
  61. def signed_request_actor
  62. return @signed_request_actor if defined?(@signed_request_actor)
  63. raise SignatureVerificationError, 'Request not signed' unless signed_request?
  64. raise SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters?
  65. raise SignatureVerificationError, 'Unsupported signature algorithm (only rsa-sha256 and hs2019 are supported)' unless %w(rsa-sha256 hs2019).include?(signature_algorithm)
  66. raise SignatureVerificationError, 'Signed request date outside acceptable time window' unless matches_time_window?
  67. verify_signature_strength!
  68. verify_body_digest!
  69. actor = actor_from_key_id(signature_params['keyId'])
  70. raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
  71. signature = Base64.decode64(signature_params['signature'])
  72. compare_signed_string = build_signed_string
  73. return actor unless verify_signature(actor, signature, compare_signed_string).nil?
  74. actor = stoplight_wrap_request { actor_refresh_key!(actor) }
  75. raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
  76. return actor unless verify_signature(actor, signature, compare_signed_string).nil?
  77. fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)"
  78. rescue SignatureVerificationError => e
  79. fail_with! e.message
  80. rescue HTTP::Error, OpenSSL::SSL::SSLError => e
  81. fail_with! "Failed to fetch remote data: #{e.message}"
  82. rescue Mastodon::UnexpectedResponseError
  83. fail_with! 'Failed to fetch remote data (got unexpected reply from server)'
  84. rescue Stoplight::Error::RedLight
  85. fail_with! 'Fetching attempt skipped because of recent connection failure'
  86. end
  87. def request_body
  88. @request_body ||= request.raw_post
  89. end
  90. private
  91. def fail_with!(message)
  92. @signature_verification_failure_reason = message
  93. @signed_request_actor = nil
  94. end
  95. def signature_params
  96. @signature_params ||= begin
  97. raw_signature = request.headers['Signature']
  98. tree = SignatureParamsParser.new.parse(raw_signature)
  99. SignatureParamsTransformer.new.apply(tree)
  100. end
  101. rescue Parslet::ParseFailed
  102. raise SignatureVerificationError, 'Error parsing signature parameters'
  103. end
  104. def signature_algorithm
  105. signature_params.fetch('algorithm', 'hs2019')
  106. end
  107. def signed_headers
  108. signature_params.fetch('headers', signature_algorithm == 'hs2019' ? '(created)' : 'date').downcase.split(' ')
  109. end
  110. def verify_signature_strength!
  111. raise SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)')
  112. raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(Request::REQUEST_TARGET) || signed_headers.include?('digest')
  113. raise SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host')
  114. raise SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest')
  115. end
  116. def verify_body_digest!
  117. return unless signed_headers.include?('digest')
  118. raise SignatureVerificationError, 'Digest header missing' unless request.headers.key?('Digest')
  119. digests = request.headers['Digest'].split(',').map { |digest| digest.split('=', 2) }.map { |key, value| [key.downcase, value] }
  120. sha256 = digests.assoc('sha-256')
  121. raise SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil?
  122. return if body_digest == sha256[1]
  123. digest_size = begin
  124. Base64.strict_decode64(sha256[1].strip).length
  125. rescue ArgumentError
  126. raise SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a valid base64 string. Given digest: #{sha256[1]}"
  127. end
  128. raise SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a SHA-256 digest. Given digest: #{sha256[1]}" if digest_size != 32
  129. raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}"
  130. end
  131. def verify_signature(actor, signature, compare_signed_string)
  132. if actor.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string)
  133. @signed_request_actor = actor
  134. @signed_request_actor
  135. end
  136. rescue OpenSSL::PKey::RSAError
  137. nil
  138. end
  139. def build_signed_string
  140. signed_headers.map do |signed_header|
  141. if signed_header == Request::REQUEST_TARGET
  142. "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
  143. elsif signed_header == '(created)'
  144. raise SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019'
  145. raise SignatureVerificationError, 'Pseudo-header (created) used but corresponding argument missing' if signature_params['created'].blank?
  146. "(created): #{signature_params['created']}"
  147. elsif signed_header == '(expires)'
  148. raise SignatureVerificationError, 'Invalid pseudo-header (expires) for rsa-sha256' unless signature_algorithm == 'hs2019'
  149. raise SignatureVerificationError, 'Pseudo-header (expires) used but corresponding argument missing' if signature_params['expires'].blank?
  150. "(expires): #{signature_params['expires']}"
  151. else
  152. "#{signed_header}: #{request.headers[to_header_name(signed_header)]}"
  153. end
  154. end.join("\n")
  155. end
  156. def matches_time_window?
  157. created_time = nil
  158. expires_time = nil
  159. begin
  160. if signature_algorithm == 'hs2019' && signature_params['created'].present?
  161. created_time = Time.at(signature_params['created'].to_i).utc
  162. elsif request.headers['Date'].present?
  163. created_time = Time.httpdate(request.headers['Date']).utc
  164. end
  165. expires_time = Time.at(signature_params['expires'].to_i).utc if signature_params['expires'].present?
  166. rescue ArgumentError
  167. return false
  168. end
  169. expires_time ||= created_time + 5.minutes unless created_time.nil?
  170. expires_time = [expires_time, created_time + EXPIRATION_WINDOW_LIMIT].min unless created_time.nil?
  171. return false if created_time.present? && created_time > Time.now.utc + CLOCK_SKEW_MARGIN
  172. return false if expires_time.present? && Time.now.utc > expires_time + CLOCK_SKEW_MARGIN
  173. true
  174. end
  175. def body_digest
  176. @body_digest ||= Digest::SHA256.base64digest(request_body)
  177. end
  178. def to_header_name(name)
  179. name.split(/-/).map(&:capitalize).join('-')
  180. end
  181. def missing_required_signature_parameters?
  182. signature_params['keyId'].blank? || signature_params['signature'].blank?
  183. end
  184. def actor_from_key_id(key_id)
  185. domain = key_id.start_with?('acct:') ? key_id.split('@').last : key_id
  186. if domain_not_allowed?(domain)
  187. @signature_verification_failure_code = 403
  188. return
  189. end
  190. if key_id.start_with?('acct:')
  191. stoplight_wrap_request { ResolveAccountService.new.call(key_id.gsub(/\Aacct:/, ''), suppress_errors: false) }
  192. elsif !ActivityPub::TagManager.instance.local_uri?(key_id)
  193. account = ActivityPub::TagManager.instance.uri_to_actor(key_id)
  194. account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false, suppress_errors: false) }
  195. account
  196. end
  197. rescue Mastodon::PrivateNetworkAddressError => e
  198. raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
  199. rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, ActivityPub::FetchRemoteKeyService::Error, Webfinger::Error => e
  200. raise SignatureVerificationError, e.message
  201. end
  202. def stoplight_wrap_request(&block)
  203. Stoplight("source:#{request.remote_ip}", &block)
  204. .with_threshold(1)
  205. .with_cool_off_time(5.minutes.seconds)
  206. .with_error_handler { |error, handle| error.is_a?(HTTP::Error) || error.is_a?(OpenSSL::SSL::SSLError) ? handle.call(error) : raise(error) }
  207. .run
  208. end
  209. def actor_refresh_key!(actor)
  210. return if actor.local? || !actor.activitypub?
  211. return actor.refresh! if actor.respond_to?(:refresh!) && actor.possibly_stale?
  212. ActivityPub::FetchRemoteActorService.new.call(actor.uri, only_key: true, suppress_errors: false)
  213. rescue Mastodon::PrivateNetworkAddressError => e
  214. raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
  215. rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, Webfinger::Error => e
  216. raise SignatureVerificationError, e.message
  217. end
  218. end