aws-sigv4 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/VERSION +1 -1
- data/lib/aws-sigv4/asymmetric_credentials.rb +91 -0
- data/lib/aws-sigv4/signature.rb +3 -0
- data/lib/aws-sigv4/signer.rb +81 -26
- data/lib/aws-sigv4.rb +1 -0
- metadata +8 -7
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 25c3ddf60803af303d37af469c7250ceba22d6a23e62bbfb7a9a82ae3d01b8e8
         | 
| 4 | 
            +
              data.tar.gz: 36537ef12949c9d0a632060485c3dcf340176a8241c3e65828e47991581e7c89
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: aa33926ae5a1804fee36cce9b7cadead40d9d5806154e62840be377c663d94dbac07ea537601f4fa47c1d4861dccb3bdf7801b2b1edf256a0a452a73fdf2c9de
         | 
| 7 | 
            +
              data.tar.gz: 8e1e705a6dfef2edd5af640de60f01321f1a811f41f407e906f08881d83d197ba9011c4ed3d2a218f6f17f94fcd602e0a6759abcf7c5e5e27f5d66465c3f3f3c
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            1. | 
| 1 | 
            +
            1.9.0
         | 
| @@ -0,0 +1,91 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Aws
         | 
| 4 | 
            +
              module Sigv4
         | 
| 5 | 
            +
                # To make it easier to support mixed mode, we have created an asymmetric
         | 
| 6 | 
            +
                # key derivation mechanism. This module derives
         | 
| 7 | 
            +
                # asymmetric keys from the current secret for use with
         | 
| 8 | 
            +
                # Asymmetric signatures.
         | 
| 9 | 
            +
                # @api private
         | 
| 10 | 
            +
                module AsymmetricCredentials
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  N_MINUS_2 = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 - 2
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  # @param [String] :access_key_id
         | 
| 15 | 
            +
                  # @param [String] :secret_access_key
         | 
| 16 | 
            +
                  # @return [OpenSSL::PKey::EC, Hash]
         | 
| 17 | 
            +
                  def self.derive_asymmetric_key(access_key_id, secret_access_key)
         | 
| 18 | 
            +
                    check_openssl_support!
         | 
| 19 | 
            +
                    label = 'AWS4-ECDSA-P256-SHA256'
         | 
| 20 | 
            +
                    bit_len = 256
         | 
| 21 | 
            +
                    counter = 0x1
         | 
| 22 | 
            +
                    input_key = "AWS4A#{secret_access_key}"
         | 
| 23 | 
            +
                    d = 0 # d will end up being the private key
         | 
| 24 | 
            +
                    while true do
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      kdf_context = access_key_id.unpack('C*') + [counter].pack('C').unpack('C') #1 byte for counter
         | 
| 27 | 
            +
                      input = label.unpack('C*') + [0x00] + kdf_context + [bit_len].pack('L>').unpack('CCCC') # 4 bytes (change endianess)
         | 
| 28 | 
            +
                      k0 = OpenSSL::HMAC.digest("SHA256", input_key, ([0, 0, 0, 0x01] + input).pack('C*'))
         | 
| 29 | 
            +
                      c = be_bytes_to_num( k0.unpack('C*') )
         | 
| 30 | 
            +
                      if c <= N_MINUS_2
         | 
| 31 | 
            +
                        d = c + 1
         | 
| 32 | 
            +
                        break
         | 
| 33 | 
            +
                      elsif counter > 0xFF
         | 
| 34 | 
            +
                        raise 'Counter exceeded 1 byte - unable to get asym creds'
         | 
| 35 | 
            +
                      else
         | 
| 36 | 
            +
                        counter += 1
         | 
| 37 | 
            +
                      end
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    # compute the public key
         | 
| 41 | 
            +
                    group = OpenSSL::PKey::EC::Group.new('prime256v1')
         | 
| 42 | 
            +
                    public_key = group.generator.mul(d)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    ec = generate_ec(public_key, d)
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    # pk_x and pk_y are not needed for signature, but useful in verification/testing
         | 
| 47 | 
            +
                    pk_b = public_key.to_octet_string(:uncompressed).unpack('C*') # 0x04 byte followed by 2 32-byte integers
         | 
| 48 | 
            +
                    pk_x = be_bytes_to_num(pk_b[1,32])
         | 
| 49 | 
            +
                    pk_y = be_bytes_to_num(pk_b[33,32])
         | 
| 50 | 
            +
                    [ec, {ec: ec, public_key: public_key, pk_x: pk_x, pk_y: pk_y, d: d}]
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  private
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  # @return [Number] The value of the bytes interpreted as a big-endian
         | 
| 56 | 
            +
                  # unsigned integer.
         | 
| 57 | 
            +
                  def self.be_bytes_to_num(bytes)
         | 
| 58 | 
            +
                    x = 0
         | 
| 59 | 
            +
                    bytes.each { |b| x = (x*256) + b }
         | 
| 60 | 
            +
                    x
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  # Prior to openssl3 we could directly set public and private key on EC
         | 
| 64 | 
            +
                  # However, openssl3 deprecated those methods and we must now construct
         | 
| 65 | 
            +
                  # a der with the keys and load the EC from it.
         | 
| 66 | 
            +
                  def self.generate_ec(public_key, d)
         | 
| 67 | 
            +
                    # format reversed from: OpenSSL::ASN1.decode_all(OpenSSL::PKey::EC.new.to_der)
         | 
| 68 | 
            +
                    asn1 = OpenSSL::ASN1::Sequence([
         | 
| 69 | 
            +
                      OpenSSL::ASN1::Integer(OpenSSL::BN.new(1)),
         | 
| 70 | 
            +
                      OpenSSL::ASN1::OctetString([d.to_s(16)].pack('H*')),
         | 
| 71 | 
            +
                      OpenSSL::ASN1::ASN1Data.new([OpenSSL::ASN1::ObjectId("prime256v1")], 0, :CONTEXT_SPECIFIC),
         | 
| 72 | 
            +
                      OpenSSL::ASN1::ASN1Data.new(
         | 
| 73 | 
            +
                        [OpenSSL::ASN1::BitString(public_key.to_octet_string(:uncompressed))],
         | 
| 74 | 
            +
                        1, :CONTEXT_SPECIFIC
         | 
| 75 | 
            +
                      )
         | 
| 76 | 
            +
                    ])
         | 
| 77 | 
            +
                    OpenSSL::PKey::EC.new(asn1.to_der)
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def self.check_openssl_support!
         | 
| 81 | 
            +
                    return true unless defined?(JRUBY_VERSION)
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    # See: https://github.com/jruby/jruby-openssl/issues/306
         | 
| 84 | 
            +
                    # JRuby-openssl < 0.15 does not support OpenSSL::PKey::EC::Point#mul
         | 
| 85 | 
            +
                    return true if OpenSSL::PKey::EC::Point.instance_methods.include?(:mul)
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                    raise 'Sigv4a Asymmetric Credential derivation requires jruby-openssl >= 0.15'
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
            end
         | 
    
        data/lib/aws-sigv4/signature.rb
    CHANGED
    
    | @@ -32,6 +32,9 @@ module Aws | |
| 32 32 | 
             
                  # @return [String] For debugging purposes.
         | 
| 33 33 | 
             
                  attr_accessor :content_sha256
         | 
| 34 34 |  | 
| 35 | 
            +
                  # @return [String] For debugging purposes.
         | 
| 36 | 
            +
                  attr_accessor :signature
         | 
| 37 | 
            +
             | 
| 35 38 | 
             
                  # @return [Hash] Internal data for debugging purposes.
         | 
| 36 39 | 
             
                  attr_accessor :extra
         | 
| 37 40 | 
             
                end
         | 
    
        data/lib/aws-sigv4/signer.rb
    CHANGED
    
    | @@ -84,14 +84,16 @@ module Aws | |
| 84 84 |  | 
| 85 85 | 
             
                  # @overload initialize(service:, region:, access_key_id:, secret_access_key:, session_token:nil, **options)
         | 
| 86 86 | 
             
                  #   @param [String] :service The service signing name, e.g. 's3'.
         | 
| 87 | 
            -
                  #   @param [String] :region The region name, e.g. 'us-east-1'.
         | 
| 87 | 
            +
                  #   @param [String] :region The region name, e.g. 'us-east-1'. When signing
         | 
| 88 | 
            +
                  #    with sigv4a, this should be a comma separated list of regions.
         | 
| 88 89 | 
             
                  #   @param [String] :access_key_id
         | 
| 89 90 | 
             
                  #   @param [String] :secret_access_key
         | 
| 90 91 | 
             
                  #   @param [String] :session_token (nil)
         | 
| 91 92 | 
             
                  #
         | 
| 92 93 | 
             
                  # @overload initialize(service:, region:, credentials:, **options)
         | 
| 93 94 | 
             
                  #   @param [String] :service The service signing name, e.g. 's3'.
         | 
| 94 | 
            -
                  #   @param [String] :region The region name, e.g. 'us-east-1'.
         | 
| 95 | 
            +
                  #   @param [String] :region The region name, e.g. 'us-east-1'. When signing
         | 
| 96 | 
            +
                  #    with sigv4a, this should be a comma separated list of regions.
         | 
| 95 97 | 
             
                  #   @param [Credentials] :credentials Any object that responds to the following
         | 
| 96 98 | 
             
                  #     methods:
         | 
| 97 99 | 
             
                  #
         | 
| @@ -102,7 +104,8 @@ module Aws | |
| 102 104 | 
             
                  #
         | 
| 103 105 | 
             
                  # @overload initialize(service:, region:, credentials_provider:, **options)
         | 
| 104 106 | 
             
                  #   @param [String] :service The service signing name, e.g. 's3'.
         | 
| 105 | 
            -
                  #   @param [String] :region The region name, e.g. 'us-east-1'.
         | 
| 107 | 
            +
                  #   @param [String] :region The region name, e.g. 'us-east-1'. When signing
         | 
| 108 | 
            +
                  #    with sigv4a, this should be a comma separated list of regions.
         | 
| 106 109 | 
             
                  #   @param [#credentials] :credentials_provider An object that responds
         | 
| 107 110 | 
             
                  #     to `#credentials`, returning an object that responds to the following
         | 
| 108 111 | 
             
                  #     methods:
         | 
| @@ -127,8 +130,7 @@ module Aws | |
| 127 130 | 
             
                  #   every other AWS service as of late 2016.
         | 
| 128 131 | 
             
                  #
         | 
| 129 132 | 
             
                  # @option options [Symbol] :signing_algorithm (:sigv4) The
         | 
| 130 | 
            -
                  #   algorithm to use for signing. | 
| 131 | 
            -
                  #   `aws-crt` is available.
         | 
| 133 | 
            +
                  #   algorithm to use for signing.
         | 
| 132 134 | 
             
                  #
         | 
| 133 135 | 
             
                  # @option options [Boolean] :omit_session_token (false)
         | 
| 134 136 | 
             
                  #   (Supported only when `aws-crt` is available) If `true`,
         | 
| @@ -136,8 +138,8 @@ module Aws | |
| 136 138 | 
             
                  #   but is treated as "unsigned" and does not contribute
         | 
| 137 139 | 
             
                  #   to the authorization signature.
         | 
| 138 140 | 
             
                  #
         | 
| 139 | 
            -
                  # @option options [Boolean] :normalize_path (true)  | 
| 140 | 
            -
                  #    | 
| 141 | 
            +
                  # @option options [Boolean] :normalize_path (true) When `true`, the
         | 
| 142 | 
            +
                  #   uri paths will be normalized when building the canonical request.
         | 
| 141 143 | 
             
                  def initialize(options = {})
         | 
| 142 144 | 
             
                    @service = extract_service(options)
         | 
| 143 145 | 
             
                    @region = extract_region(options)
         | 
| @@ -152,12 +154,6 @@ module Aws | |
| 152 154 | 
             
                    @normalize_path = options.fetch(:normalize_path, true)
         | 
| 153 155 | 
             
                    @omit_session_token = options.fetch(:omit_session_token, false)
         | 
| 154 156 |  | 
| 155 | 
            -
                    if @signing_algorithm == :sigv4a && !Signer.use_crt?
         | 
| 156 | 
            -
                      raise ArgumentError, 'You are attempting to sign a' \
         | 
| 157 | 
            -
            ' request with sigv4a which requires the `aws-crt` gem.'\
         | 
| 158 | 
            -
            ' Please install the gem or add it to your gemfile.'
         | 
| 159 | 
            -
                    end
         | 
| 160 | 
            -
             | 
| 161 157 | 
             
                    if @signing_algorithm == 'sigv4-s3express'.to_sym &&
         | 
| 162 158 | 
             
                       Signer.use_crt? && Aws::Crt::GEM_VERSION <= '0.1.9'
         | 
| 163 159 | 
             
                      raise ArgumentError,
         | 
| @@ -246,6 +242,7 @@ module Aws | |
| 246 242 |  | 
| 247 243 | 
             
                    http_method = extract_http_method(request)
         | 
| 248 244 | 
             
                    url = extract_url(request)
         | 
| 245 | 
            +
                    Signer.normalize_path(url) if @normalize_path
         | 
| 249 246 | 
             
                    headers = downcase_headers(request[:headers])
         | 
| 250 247 |  | 
| 251 248 | 
             
                    datetime = headers['x-amz-date']
         | 
| @@ -258,7 +255,7 @@ module Aws | |
| 258 255 | 
             
                    sigv4_headers = {}
         | 
| 259 256 | 
             
                    sigv4_headers['host'] = headers['host'] || host(url)
         | 
| 260 257 | 
             
                    sigv4_headers['x-amz-date'] = datetime
         | 
| 261 | 
            -
                    if creds.session_token
         | 
| 258 | 
            +
                    if creds.session_token && !@omit_session_token
         | 
| 262 259 | 
             
                      if @signing_algorithm == 'sigv4-s3express'.to_sym
         | 
| 263 260 | 
             
                        sigv4_headers['x-amz-s3session-token'] = creds.session_token
         | 
| 264 261 | 
             
                      else
         | 
| @@ -268,26 +265,45 @@ module Aws | |
| 268 265 |  | 
| 269 266 | 
             
                    sigv4_headers['x-amz-content-sha256'] ||= content_sha256 if @apply_checksum_header
         | 
| 270 267 |  | 
| 268 | 
            +
                    if @signing_algorithm == :sigv4a && @region && !@region.empty?
         | 
| 269 | 
            +
                      sigv4_headers['x-amz-region-set'] = @region
         | 
| 270 | 
            +
                    end
         | 
| 271 271 | 
             
                    headers = headers.merge(sigv4_headers) # merge so we do not modify given headers hash
         | 
| 272 272 |  | 
| 273 | 
            +
                    algorithm = sts_algorithm
         | 
| 274 | 
            +
             | 
| 273 275 | 
             
                    # compute signature parts
         | 
| 274 276 | 
             
                    creq = canonical_request(http_method, url, headers, content_sha256)
         | 
| 275 | 
            -
                    sts = string_to_sign(datetime, creq)
         | 
| 276 | 
            -
             | 
| 277 | 
            +
                    sts = string_to_sign(datetime, creq, algorithm)
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    sig =
         | 
| 280 | 
            +
                      if @signing_algorithm == :sigv4a
         | 
| 281 | 
            +
                        asymmetric_signature(creds, sts)
         | 
| 282 | 
            +
                      else
         | 
| 283 | 
            +
                        signature(creds.secret_access_key, date, sts)
         | 
| 284 | 
            +
                      end
         | 
| 285 | 
            +
             | 
| 286 | 
            +
                    algorithm = sts_algorithm
         | 
| 277 287 |  | 
| 278 288 | 
             
                    # apply signature
         | 
| 279 289 | 
             
                    sigv4_headers['authorization'] = [
         | 
| 280 | 
            -
                      " | 
| 290 | 
            +
                      "#{algorithm} Credential=#{credential(creds, date)}",
         | 
| 281 291 | 
             
                      "SignedHeaders=#{signed_headers(headers)}",
         | 
| 282 292 | 
             
                      "Signature=#{sig}",
         | 
| 283 293 | 
             
                    ].join(', ')
         | 
| 284 294 |  | 
| 295 | 
            +
                    # skip signing the session token, but include it in the headers
         | 
| 296 | 
            +
                    if creds.session_token && @omit_session_token
         | 
| 297 | 
            +
                      sigv4_headers['x-amz-security-token'] = creds.session_token
         | 
| 298 | 
            +
                    end
         | 
| 299 | 
            +
             | 
| 285 300 | 
             
                    # Returning the signature components.
         | 
| 286 301 | 
             
                    Signature.new(
         | 
| 287 302 | 
             
                      headers: sigv4_headers,
         | 
| 288 303 | 
             
                      string_to_sign: sts,
         | 
| 289 304 | 
             
                      canonical_request: creq,
         | 
| 290 | 
            -
                      content_sha256: content_sha256
         | 
| 305 | 
            +
                      content_sha256: content_sha256,
         | 
| 306 | 
            +
                      signature: sig
         | 
| 291 307 | 
             
                    )
         | 
| 292 308 | 
             
                  end
         | 
| 293 309 |  | 
| @@ -421,6 +437,7 @@ module Aws | |
| 421 437 |  | 
| 422 438 | 
             
                    http_method = extract_http_method(options)
         | 
| 423 439 | 
             
                    url = extract_url(options)
         | 
| 440 | 
            +
                    Signer.normalize_path(url) if @normalize_path
         | 
| 424 441 |  | 
| 425 442 | 
             
                    headers = downcase_headers(options[:headers])
         | 
| 426 443 | 
             
                    headers['host'] ||= host(url)
         | 
| @@ -433,8 +450,10 @@ module Aws | |
| 433 450 | 
             
                    content_sha256 ||= options[:body_digest]
         | 
| 434 451 | 
             
                    content_sha256 ||= sha256_hexdigest(options[:body] || '')
         | 
| 435 452 |  | 
| 453 | 
            +
                    algorithm = sts_algorithm
         | 
| 454 | 
            +
             | 
| 436 455 | 
             
                    params = {}
         | 
| 437 | 
            -
                    params['X-Amz-Algorithm'] =  | 
| 456 | 
            +
                    params['X-Amz-Algorithm'] = algorithm
         | 
| 438 457 | 
             
                    params['X-Amz-Credential'] = credential(creds, date)
         | 
| 439 458 | 
             
                    params['X-Amz-Date'] = datetime
         | 
| 440 459 | 
             
                    params['X-Amz-Expires'] = presigned_url_expiration(options, expiration, Time.strptime(datetime, "%Y%m%dT%H%M%S%Z")).to_s
         | 
| @@ -447,6 +466,10 @@ module Aws | |
| 447 466 | 
             
                    end
         | 
| 448 467 | 
             
                    params['X-Amz-SignedHeaders'] = signed_headers(headers)
         | 
| 449 468 |  | 
| 469 | 
            +
                    if @signing_algorithm == :sigv4a && @region
         | 
| 470 | 
            +
                      params['X-Amz-Region-Set'] = @region
         | 
| 471 | 
            +
                    end
         | 
| 472 | 
            +
             | 
| 450 473 | 
             
                    params = params.map do |key, value|
         | 
| 451 474 | 
             
                      "#{uri_escape(key)}=#{uri_escape(value)}"
         | 
| 452 475 | 
             
                    end.join('&')
         | 
| @@ -458,13 +481,23 @@ module Aws | |
| 458 481 | 
             
                    end
         | 
| 459 482 |  | 
| 460 483 | 
             
                    creq = canonical_request(http_method, url, headers, content_sha256)
         | 
| 461 | 
            -
                    sts = string_to_sign(datetime, creq)
         | 
| 462 | 
            -
                     | 
| 484 | 
            +
                    sts = string_to_sign(datetime, creq, algorithm)
         | 
| 485 | 
            +
                    signature =
         | 
| 486 | 
            +
                      if @signing_algorithm == :sigv4a
         | 
| 487 | 
            +
                        asymmetric_signature(creds, sts)
         | 
| 488 | 
            +
                      else
         | 
| 489 | 
            +
                        signature(creds.secret_access_key, date, sts)
         | 
| 490 | 
            +
                      end
         | 
| 491 | 
            +
                    url.query += '&X-Amz-Signature=' + signature
         | 
| 463 492 | 
             
                    url
         | 
| 464 493 | 
             
                  end
         | 
| 465 494 |  | 
| 466 495 | 
             
                  private
         | 
| 467 496 |  | 
| 497 | 
            +
                  def sts_algorithm
         | 
| 498 | 
            +
                    @signing_algorithm == :sigv4a ? 'AWS4-ECDSA-P256-SHA256' : 'AWS4-HMAC-SHA256'
         | 
| 499 | 
            +
                  end
         | 
| 500 | 
            +
             | 
| 468 501 | 
             
                  def canonical_request(http_method, url, headers, content_sha256)
         | 
| 469 502 | 
             
                    [
         | 
| 470 503 | 
             
                      http_method,
         | 
| @@ -476,9 +509,9 @@ module Aws | |
| 476 509 | 
             
                    ].join("\n")
         | 
| 477 510 | 
             
                  end
         | 
| 478 511 |  | 
| 479 | 
            -
                  def string_to_sign(datetime, canonical_request)
         | 
| 512 | 
            +
                  def string_to_sign(datetime, canonical_request, algorithm)
         | 
| 480 513 | 
             
                    [
         | 
| 481 | 
            -
                       | 
| 514 | 
            +
                      algorithm,
         | 
| 482 515 | 
             
                      datetime,
         | 
| 483 516 | 
             
                      credential_scope(datetime[0,8]),
         | 
| 484 517 | 
             
                      sha256_hexdigest(canonical_request),
         | 
| @@ -511,10 +544,10 @@ module Aws | |
| 511 544 | 
             
                  def credential_scope(date)
         | 
| 512 545 | 
             
                    [
         | 
| 513 546 | 
             
                      date,
         | 
| 514 | 
            -
                      @region,
         | 
| 547 | 
            +
                      (@region unless @signing_algorithm == :sigv4a),
         | 
| 515 548 | 
             
                      @service,
         | 
| 516 | 
            -
                      'aws4_request' | 
| 517 | 
            -
                    ].join('/')
         | 
| 549 | 
            +
                      'aws4_request'
         | 
| 550 | 
            +
                    ].compact.join('/')
         | 
| 518 551 | 
             
                  end
         | 
| 519 552 |  | 
| 520 553 | 
             
                  def credential(credentials, date)
         | 
| @@ -529,6 +562,16 @@ module Aws | |
| 529 562 | 
             
                    hexhmac(k_credentials, string_to_sign)
         | 
| 530 563 | 
             
                  end
         | 
| 531 564 |  | 
| 565 | 
            +
                  def asymmetric_signature(creds, string_to_sign)
         | 
| 566 | 
            +
                    ec, _ = Aws::Sigv4::AsymmetricCredentials.derive_asymmetric_key(
         | 
| 567 | 
            +
                      creds.access_key_id, creds.secret_access_key
         | 
| 568 | 
            +
                    )
         | 
| 569 | 
            +
                    sts_digest = OpenSSL::Digest::SHA256.digest(string_to_sign)
         | 
| 570 | 
            +
                    s = ec.dsa_sign_asn1(sts_digest)
         | 
| 571 | 
            +
             | 
| 572 | 
            +
                    Digest.hexencode(s)
         | 
| 573 | 
            +
                  end
         | 
| 574 | 
            +
             | 
| 532 575 | 
             
                  # Comparing to original signature v4 algorithm,
         | 
| 533 576 | 
             
                  # returned signature is a binary string instread of
         | 
| 534 577 | 
             
                  # hex-encoded string. (Since ':chunk-signature' requires
         | 
| @@ -896,6 +939,18 @@ module Aws | |
| 896 939 | 
             
                      end
         | 
| 897 940 | 
             
                    end
         | 
| 898 941 |  | 
| 942 | 
            +
                    # @api private
         | 
| 943 | 
            +
                    def normalize_path(uri)
         | 
| 944 | 
            +
                      normalized_path = Pathname.new(uri.path).cleanpath.to_s
         | 
| 945 | 
            +
                      # Pathname is probably not correct to use. Empty paths will
         | 
| 946 | 
            +
                      # resolve to "." and should be disregarded
         | 
| 947 | 
            +
                      normalized_path = '' if normalized_path == '.'
         | 
| 948 | 
            +
                      # Ensure trailing slashes are correctly preserved
         | 
| 949 | 
            +
                      if uri.path.end_with?('/') && !normalized_path.end_with?('/')
         | 
| 950 | 
            +
                        normalized_path << '/'
         | 
| 951 | 
            +
                      end
         | 
| 952 | 
            +
                      uri.path = normalized_path
         | 
| 953 | 
            +
                    end
         | 
| 899 954 | 
             
                  end
         | 
| 900 955 | 
             
                end
         | 
| 901 956 | 
             
              end
         | 
    
        data/lib/aws-sigv4.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: aws-sigv4
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.9.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Amazon Web Services
         | 
| 8 | 
            -
            autorequire: | 
| 8 | 
            +
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2024-07-23 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: aws-eventstream
         | 
| @@ -32,7 +32,7 @@ dependencies: | |
| 32 32 | 
             
                    version: 1.0.2
         | 
| 33 33 | 
             
            description: Amazon Web Services Signature Version 4 signing library. Generates sigv4
         | 
| 34 34 | 
             
              signature for HTTP requests.
         | 
| 35 | 
            -
            email: | 
| 35 | 
            +
            email:
         | 
| 36 36 | 
             
            executables: []
         | 
| 37 37 | 
             
            extensions: []
         | 
| 38 38 | 
             
            extra_rdoc_files: []
         | 
| @@ -41,6 +41,7 @@ files: | |
| 41 41 | 
             
            - LICENSE.txt
         | 
| 42 42 | 
             
            - VERSION
         | 
| 43 43 | 
             
            - lib/aws-sigv4.rb
         | 
| 44 | 
            +
            - lib/aws-sigv4/asymmetric_credentials.rb
         | 
| 44 45 | 
             
            - lib/aws-sigv4/credentials.rb
         | 
| 45 46 | 
             
            - lib/aws-sigv4/errors.rb
         | 
| 46 47 | 
             
            - lib/aws-sigv4/request.rb
         | 
| @@ -52,7 +53,7 @@ licenses: | |
| 52 53 | 
             
            metadata:
         | 
| 53 54 | 
             
              source_code_uri: https://github.com/aws/aws-sdk-ruby/tree/version-3/gems/aws-sigv4
         | 
| 54 55 | 
             
              changelog_uri: https://github.com/aws/aws-sdk-ruby/tree/version-3/gems/aws-sigv4/CHANGELOG.md
         | 
| 55 | 
            -
            post_install_message: | 
| 56 | 
            +
            post_install_message:
         | 
| 56 57 | 
             
            rdoc_options: []
         | 
| 57 58 | 
             
            require_paths:
         | 
| 58 59 | 
             
            - lib
         | 
| @@ -67,8 +68,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 67 68 | 
             
                - !ruby/object:Gem::Version
         | 
| 68 69 | 
             
                  version: '0'
         | 
| 69 70 | 
             
            requirements: []
         | 
| 70 | 
            -
            rubygems_version: 3. | 
| 71 | 
            -
            signing_key: | 
| 71 | 
            +
            rubygems_version: 3.4.10
         | 
| 72 | 
            +
            signing_key:
         | 
| 72 73 | 
             
            specification_version: 4
         | 
| 73 74 | 
             
            summary: AWS Signature Version 4 library.
         | 
| 74 75 | 
             
            test_files: []
         |