aws4_signer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40d14a60591fbacc5974d2146d052a90d6c82e8d
4
+ data.tar.gz: ac94c5b92bf12e4617387070a7616d3f6066365a
5
+ SHA512:
6
+ metadata.gz: a975872efa7da0c5c1bd42f25a132c5213a0c10e7f54196158fb9df615a1a2351645942e697bfeb47dd8a8b0b39279acba2a7bb4078ab994668e1627f3e27f18
7
+ data.tar.gz: 995dbc0117c08c1d96165eb138637164e3422733d80a0f3ad2f56bc80681bff606f4556fb60786118fcf628cc8cf86ad327f0ab034b77a52fca57267238853a3
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - "2.1.1"
5
+ - "2.0.0"
6
+ - "ruby-head"
7
+ matrix:
8
+ allow_failures:
9
+ - rvm:
10
+ - "ruby-head"
11
+ fast_finish: true
12
+ notifications:
13
+ email:
14
+ - travis-ci@sorah.jp
15
+ script: bundle exec rake test
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aws4_signer.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Shota Fukumori (sora_h)
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Aws4Signer - Simple signer module implements AWS4 signature
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ gem 'aws4_signer'
8
+
9
+ And then execute:
10
+
11
+ $ bundle
12
+
13
+ Or install it yourself as:
14
+
15
+ $ gem install aws4_signer
16
+
17
+ ## Usage
18
+
19
+ ```
20
+ bucket, key = 'foo', 'path/to/file'
21
+ signer = Aws4Signer.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"], 'ap-northeast-1', 's3')
22
+ uri = URI("https://s3-ap-northeast-1.amazonaws.com/#{bucket}/#{key}")
23
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
24
+ req = Net::HTTP::Get.new(uri)
25
+ signer.sign_http_request(req)
26
+
27
+ response = http.request(req)
28
+ p response.body
29
+ end
30
+ ```
31
+
32
+ ## Reference
33
+
34
+ - [Authenticating Requests (AWS Signature Version 4) - Amazon Simple Storage Service](http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)
35
+ - [Authenticating Requests by Using the Authorization Header (Compute Checksum of the Entire Payload Prior to Transmission) - Signature Version 4 - Amazon Simple Storage Service](http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html)
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it ( https://github.com/sorah/aws4_signer/fork )
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.pattern= "test/*_spec.rb"
6
+ end
7
+
8
+ task default: :test
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aws4_signer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "aws4_signer"
8
+ spec.version = Aws4Signer::VERSION
9
+ spec.authors = ["Shota Fukumori (sora_h)"]
10
+ spec.email = ["her@sorah.jp"]
11
+ spec.summary = %q{Simple signer module implements AWS4 signature}
12
+ spec.description = nil
13
+ spec.homepage = "https://github.com/sorah/aws4_signer"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest", '~> 5.4.0'
24
+ spec.add_development_dependency 'minitest-reporters', '~> 1.0.5'
25
+ end
@@ -0,0 +1,22 @@
1
+ require 'aws4_signer'
2
+ require 'uri'
3
+ require 'net/http'
4
+ require 'net/https'
5
+
6
+ bucket, key = ARGV
7
+
8
+ unless bucket && key && ENV["AWS_ACCESS_KEY_ID"] && ENV["AWS_SECRET_ACCESS_KEY"] && ENV["AWS_REGION"]
9
+ puts "Usage: #{$0} bucket key"
10
+ puts "Specify AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION via environment variable"
11
+ exit 2
12
+ end
13
+
14
+ signer = Aws4Signer.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"], ENV["AWS_REGION"], 's3')
15
+ uri = URI("https://s3-#{ENV["AWS_REGION"]}.amazonaws.com/#{bucket}/#{key}")
16
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
17
+ req = Net::HTTP::Get.new(uri)
18
+ signer.sign_http_request(req)
19
+
20
+ response = http.request(req)
21
+ puts response.body
22
+ end
@@ -0,0 +1,142 @@
1
+ class Aws4Signer
2
+ class Signature
3
+ def initialize(access_key_id, secret_access_key, region, service, verb, uri, headers, body)
4
+ @access_key_id = access_key_id
5
+ @secret_access_key = secret_access_key
6
+ @region = region
7
+ @service = service
8
+ @verb = verb
9
+ @uri = uri
10
+ @headers = headers.dup
11
+ @body = body
12
+
13
+ @headers.each do |name, value|
14
+ if value.kind_of?(Array)
15
+ @headers[name] = value.first
16
+ end
17
+ end
18
+
19
+ @headers["x-amz-date"] ||= @headers.delete("X-Amz-Date")
20
+ unless @headers["x-amz-date"]
21
+ @date = Time.now.utc
22
+ @headers["x-amz-date"] = @date.strftime("%Y%m%dT%H%M%SZ")
23
+ end
24
+ @headers["Host"] ||= @headers.delete("host") || uri.host
25
+ end
26
+
27
+ attr_reader :region, :service, :verb, :uri, :headers, :body, :access_key_id, :secret_access_key
28
+
29
+ def attach_to_http_request(req)
30
+ headers.each do |name, value|
31
+ req[name.downcase] = value
32
+ end
33
+
34
+ req["x-amz-content-sha256"] = Digest::SHA2.hexdigest(req.body || '', 256)
35
+ req["authorization"] = authorization_header
36
+
37
+ req
38
+ end
39
+
40
+ def authorization_header
41
+ "AWS4-HMAC-SHA256 " \
42
+ "Credential=#{@access_key_id}/#{scope}," \
43
+ "SignedHeaders=#{signed_headers}," \
44
+ "Signature=#{signature}"
45
+ end
46
+
47
+ def date
48
+ @date ||= begin
49
+ time = Time.strptime(headers["x-amz-date"],"%Y%m%dT%H%M%SZ")
50
+ time += time.utc_offset
51
+ time.utc
52
+ end
53
+ end
54
+
55
+ def canonical_headers
56
+ @canonical_headers ||= begin
57
+ signed = []
58
+ hs = headers.sort_by { |name, _| name.downcase }.flat_map { |name, value|
59
+ next if name == "Authorization"
60
+
61
+ signed << name.downcase
62
+ case value
63
+ when Array
64
+ value.each do |v|
65
+ "#{name.downcase}:#{v.to_s.strip}\n"
66
+ end
67
+ else
68
+ "#{name.downcase}:#{value.to_s.strip}\n"
69
+ end
70
+ }.compact.join.freeze
71
+
72
+ @signed_headers = signed.join(";").freeze
73
+ hs
74
+ end
75
+ end
76
+
77
+ def signed_headers
78
+ canonical_headers; @signed_headers
79
+ end
80
+
81
+ def hashed_payload
82
+ @hashed_payload ||= Digest::SHA2.hexdigest(body, 256)
83
+ end
84
+
85
+ def canonical_request
86
+ @canonical_request ||= [
87
+ @verb.upcase,
88
+ @uri.path,
89
+ @uri.query,
90
+ canonical_headers,
91
+ signed_headers,
92
+ hashed_payload,
93
+ ].join("\n")
94
+ end
95
+
96
+ def scope
97
+ "#{date.strftime("%Y%m%d")}/#{@region}/#{service}/aws4_request"
98
+ end
99
+
100
+ def string_to_sign
101
+ @string_to_sign ||= [
102
+ "AWS4-HMAC-SHA256",
103
+ headers["x-amz-date"],
104
+ scope,
105
+ Digest::SHA2.hexdigest(canonical_request, 256),
106
+ ].join("\n")
107
+ end
108
+
109
+ def date_key
110
+ @date_key ||= hmac("AWS4#{@secret_access_key}", date.strftime("%Y%m%d"))
111
+ end
112
+
113
+ def date_region_key
114
+ @date_region_key ||= hmac(date_key, region)
115
+ end
116
+
117
+ def date_region_service_key
118
+ @date_region_service_key ||= hmac(date_region_key, service)
119
+ end
120
+
121
+ def signing_key
122
+ @signing_key ||= hmac(date_region_service_key, 'aws4_request')
123
+ end
124
+
125
+ def signature
126
+ @signature ||= hmac(signing_key, string_to_sign, :hex)
127
+ end
128
+
129
+ private
130
+
131
+ def hmac(key, data, hex = false)
132
+ hm = OpenSSL::HMAC.new(key, OpenSSL::Digest.new('sha256'))
133
+ hm.update(data)
134
+
135
+ if hex
136
+ hm.hexdigest
137
+ else
138
+ hm.digest
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,3 @@
1
+ class Aws4Signer
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,48 @@
1
+ require 'uri'
2
+ require 'time'
3
+ require 'digest/sha2'
4
+ require 'openssl'
5
+
6
+ require 'net/http'
7
+ require 'net/https'
8
+
9
+ require "aws4_signer/version"
10
+ require 'aws4_signer/signature'
11
+
12
+ class Aws4Signer
13
+ # to be exactly follow the AWS documentation, implement by ourselves
14
+ def self.uri_encode(str)
15
+ str.bytes.map do |c|
16
+ if %w[- . _ ~].include?(c) || (?A .. ?Z).cover?(c) || (?a .. ?z).cover?(c) || (?0 .. ?9).cover?(c)
17
+ c
18
+ else
19
+ "%#{c.ord.to_s(16)}"
20
+ end
21
+ end.join
22
+ end
23
+
24
+ def initialize(access_key_id, secret_access_key, region, service)
25
+ @access_key_id = access_key_id
26
+ @secret_access_key = secret_access_key
27
+ @region = region
28
+ @service = service
29
+ end
30
+
31
+ def sign(verb, uri, headers: {}, body: '')
32
+ raise ArgumentError, 'URI must provided' unless uri
33
+ Signature.new(@access_key_id, @secret_access_key, @region, @service, verb, uri, headers, body)
34
+ end
35
+
36
+ def sign_http_request(req, uri = nil)
37
+ sign(
38
+ req.method,
39
+ uri || req.uri,
40
+ headers: req.to_hash,
41
+ body: req.body || '',
42
+ ).tap do |signature|
43
+ signature.attach_to_http_request(req)
44
+ end
45
+ end
46
+ end
47
+
48
+
@@ -0,0 +1,27 @@
1
+ require_relative './test_helper'
2
+ require 'minitest/autorun'
3
+ require 'aws4_signer'
4
+
5
+ require 'uri'
6
+ require 'net/http'
7
+
8
+ describe Aws4Signer do
9
+ let(:signer) { Aws4Signer.new('KEYKEYKEY','THISISSECRET', 'xx-region-1', 'svc') }
10
+ let(:uri) { URI('https://example.org/foo/bar?baz=blah') }
11
+
12
+ describe "#sign" do
13
+ it "returns Signature" do
14
+ signature = signer.sign('PUT', uri, headers: {'foo' => 'bar'}, body: 'hello')
15
+
16
+ assert signature.is_a?(Aws4Signer::Signature)
17
+ assert_equal 'KEYKEYKEY', signature.access_key_id
18
+ assert_equal 'THISISSECRET', signature.secret_access_key
19
+ assert_equal 'xx-region-1', signature.region
20
+ assert_equal 'svc', signature.service
21
+ assert_equal 'PUT', signature.verb
22
+ assert_equal uri, signature.uri
23
+ assert_equal 'hello', signature.body
24
+ assert_equal 'bar', signature.headers['foo']
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,197 @@
1
+ require_relative './test_helper'
2
+ require 'minitest/autorun'
3
+ require 'aws4_signer/signature'
4
+
5
+ require 'uri'
6
+ require 'digest/sha2'
7
+
8
+ describe Aws4Signer::Signature do
9
+ let(:uri) { URI('https://example.org/foo/bar?baz=blah') }
10
+ let(:verb) { 'PUT' }
11
+ let(:headers) do
12
+ {'x-foo' => 'bar'}
13
+ end
14
+ let(:body) { 'hello' }
15
+
16
+ let(:signature) do
17
+ Aws4Signer::Signature.new(
18
+ 'AKID',
19
+ 'SECRET',
20
+ 'xx-region-1',
21
+ 'svc',
22
+ verb,
23
+ uri,
24
+ headers,
25
+ body,
26
+ )
27
+ end
28
+
29
+ describe "headers" do
30
+ describe "without x-amz-date" do
31
+ it "assigns" do
32
+ assert signature.headers['x-amz-date'].is_a?(String)
33
+ end
34
+ end
35
+
36
+ describe "with x-amz-date" do
37
+ before do
38
+ headers['x-amz-date'] = '20140222T070605Z'
39
+ end
40
+
41
+ it "doesn't assign" do
42
+ assert signature.headers['x-amz-date'].is_a?(String)
43
+ assert_equal Time.utc(2014,02,22,07,06,05), signature.date
44
+ end
45
+ end
46
+
47
+ describe "without host" do
48
+ it "assigns" do
49
+ assert_equal 'example.org', signature.headers['Host']
50
+ end
51
+ end
52
+
53
+ describe "with host" do
54
+ before do
55
+ headers['host'] = 'example.com'
56
+ end
57
+
58
+ it "doesn't assign" do
59
+ assert_equal 'example.com', signature.headers['Host']
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#attach_to_http_request" do
65
+ before do
66
+ headers['x-amz-date'] = '20140222T070605Z'
67
+ end
68
+
69
+ it "assigns headers" do
70
+ headers = {}
71
+ class << headers
72
+ def body
73
+ 'hello'
74
+ end
75
+ end
76
+ signature.attach_to_http_request(headers)
77
+
78
+ assert_equal 'example.org', headers['host']
79
+ assert_equal '20140222T070605Z', headers['x-amz-date']
80
+ assert_equal 'bar', headers['x-foo']
81
+ assert_equal signature.authorization_header, headers['authorization']
82
+ assert_equal Digest::SHA2.hexdigest('hello', 256), headers['x-amz-content-sha256']
83
+ end
84
+ end
85
+
86
+ describe "#authorization_header" do
87
+ before do
88
+ headers['x-amz-date'] = '20140222T070605Z'
89
+ end
90
+
91
+ it "returns" do
92
+ assert_equal 'AWS4-HMAC-SHA256 '\
93
+ 'Credential=AKID/20140222/xx-region-1/svc/aws4_request,' \
94
+ 'SignedHeaders=host;x-amz-date;x-foo,' \
95
+ 'Signature=2845eebf2510f52010a9d9e228d4b60d4dd33fb7e9f349fb21bd6a533bfc37b6',
96
+ signature.authorization_header
97
+ end
98
+ end
99
+
100
+ describe "#signature" do
101
+ before do
102
+ headers['x-amz-date'] = '20140222T070605Z'
103
+ end
104
+
105
+ it "return the sign" do
106
+ assert_equal '2845eebf2510f52010a9d9e228d4b60d4dd33fb7e9f349fb21bd6a533bfc37b6', signature.signature
107
+ end
108
+ end
109
+
110
+ describe "#canonical_headers,signed_headers" do
111
+ let(:headers) do
112
+ {
113
+ 'x-test-b' => '2',
114
+ 'X-Test-A' => '1',
115
+ 'x-test-c' => '3',
116
+ 'Authorization' => 'skip',
117
+ }
118
+ end
119
+
120
+ it "ends with return" do
121
+ assert_equal "\n", signature.canonical_headers[-1]
122
+ end
123
+
124
+ it "contains headers" do
125
+ assert signature.canonical_headers.lines.include?("x-test-b:2\n")
126
+ assert signature.canonical_headers.lines.include?("x-test-a:1\n") # downcase
127
+ assert signature.canonical_headers.lines.include?("x-test-c:3\n")
128
+ assert !signature.canonical_headers.lines.include?("Authorization:skip\n")
129
+
130
+ %w(x-test-a x-test-b x-test-c).each do |name|
131
+ assert signature.signed_headers.split(/;/).include?(name)
132
+ end
133
+ end
134
+
135
+ it "sorts headers" do
136
+ assert %w(host x-amz-date x-test-a x-test-b x-test-c),
137
+ signature.canonical_headers.lines.map { |_| _.split(/:/,2).first }
138
+
139
+ assert_equal 'host;x-amz-date;x-test-a;x-test-b;x-test-c', signature.signed_headers
140
+ end
141
+ end
142
+
143
+ describe "#hashed_payload" do
144
+ let(:body) { 'body' }
145
+
146
+ it "returns hashed payloed" do
147
+ assert_equal Digest::SHA2.hexdigest('body', 256), signature.hashed_payload
148
+ end
149
+ end
150
+
151
+ describe "#canonical_request" do
152
+ before do
153
+ headers['x-amz-date'] = '20140222T070605Z'
154
+ end
155
+
156
+ it "returns canonical request" do
157
+ canonical_request = signature.canonical_request
158
+
159
+ assert_equal <<-EXPECTED.chomp, canonical_request
160
+ PUT
161
+ /foo/bar
162
+ baz=blah
163
+ host:example.org
164
+ x-amz-date:20140222T070605Z
165
+ x-foo:bar
166
+
167
+ host;x-amz-date;x-foo
168
+ #{Digest::SHA2.hexdigest('hello', 256)}
169
+ EXPECTED
170
+ end
171
+ end
172
+
173
+ describe "#scope" do
174
+ before do
175
+ headers['x-amz-date'] = '20140222T070605Z'
176
+ end
177
+
178
+ it "returns scope" do
179
+ assert_equal '20140222/xx-region-1/svc/aws4_request', signature.scope
180
+ end
181
+ end
182
+
183
+ describe "#string_to_sign" do
184
+ before do
185
+ headers['x-amz-date'] = '20140222T070605Z'
186
+ end
187
+
188
+ it "returns string to sign" do
189
+ assert_equal <<-EXPECTED.chomp, signature.string_to_sign
190
+ AWS4-HMAC-SHA256
191
+ 20140222T070605Z
192
+ 20140222/xx-region-1/svc/aws4_request
193
+ #{Digest::SHA2.hexdigest(signature.canonical_request, 256)}
194
+ EXPECTED
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,3 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/reporters'
3
+ Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws4_signer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shota Fukumori (sora_h)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 5.4.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 5.4.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.5
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.0.5
69
+ description: ''
70
+ email:
71
+ - her@sorah.jp
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - aws4_signer.gemspec
83
+ - examples/s3_get.rb
84
+ - lib/aws4_signer.rb
85
+ - lib/aws4_signer/signature.rb
86
+ - lib/aws4_signer/version.rb
87
+ - test/aws4_signer_spec.rb
88
+ - test/signature_spec.rb
89
+ - test/test_helper.rb
90
+ homepage: https://github.com/sorah/aws4_signer
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.2
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Simple signer module implements AWS4 signature
114
+ test_files:
115
+ - test/aws4_signer_spec.rb
116
+ - test/signature_spec.rb
117
+ - test/test_helper.rb