Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.rbc
.bundle
.config
.sw?
.yardoc
Gemfile.lock
InstalledFiles
Expand All @@ -15,3 +16,4 @@ spec/reports
test/tmp
test/version_tmp
tmp
vendor
17 changes: 17 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
AllCops:
DisplayCopNames: true
TargetRubyVersion: 2.3

Documentation:
Enabled: false

Metrics/BlockLength:
Exclude:
- spec/**/*

Style/ExpandPathArguments:
Exclude:
- http_signatures.gemspec

Metrics/LineLength:
Max: 110
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
source "https://rubygems.org"
# frozen_string_literal: true

source 'https://rubygems.org'
gemspec
4 changes: 3 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
require "bundler/gem_tasks"
# frozen_string_literal: true

require 'bundler/gem_tasks'
23 changes: 12 additions & 11 deletions http_signatures.gemspec
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
# coding: utf-8
# frozen_string_literal: true

lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'http_signatures/version'

Gem::Specification.new do |spec|
spec.name = "http_signatures"
spec.name = 'http_signatures'
spec.version = HttpSignatures::VERSION
spec.authors = ["Paul Annesley"]
spec.email = ["[email protected]"]
spec.summary = "Sign and verify HTTP messages"
spec.homepage = "https://github.com/99designs/http-signatures-ruby"
spec.license = "MIT"
spec.authors = ['Paul Annesley']
spec.email = ['[email protected]']
spec.summary = 'Sign and verify HTTP messages'
spec.homepage = 'https://github.com/99designs/http-signatures-ruby'
spec.license = 'MIT'

spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec)/})
spec.require_paths = ["lib"]
spec.require_paths = ['lib']

spec.add_development_dependency "bundler", "~> 1.5"
spec.add_development_dependency "rake"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency 'bundler', '~> 1.5'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rspec', '~> 3.0'
end
30 changes: 16 additions & 14 deletions lib/http_signatures.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
require "http_signatures/algorithm"
require "http_signatures/algorithm/hmac"
require "http_signatures/context"
require "http_signatures/header_list"
require "http_signatures/key"
require "http_signatures/key_store"
require "http_signatures/signature"
require "http_signatures/signature_parameters"
require "http_signatures/signature_parameters_parser"
require "http_signatures/signer"
require "http_signatures/signing_string"
require "http_signatures/verification"
require "http_signatures/verifier"
require "http_signatures/version"
# frozen_string_literal: true

require 'http_signatures/algorithm'
require 'http_signatures/algorithm/hmac'
require 'http_signatures/context'
require 'http_signatures/header_list'
require 'http_signatures/key'
require 'http_signatures/key_store'
require 'http_signatures/signature'
require 'http_signatures/signature_parameters'
require 'http_signatures/signature_parameters_parser'
require 'http_signatures/signer'
require 'http_signatures/signing_string'
require 'http_signatures/verification'
require 'http_signatures/verifier'
require 'http_signatures/version'

module HttpSignatures
end
10 changes: 5 additions & 5 deletions lib/http_signatures/algorithm.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# frozen_string_literal: true

module HttpSignatures
module Algorithm

def self.create(name)
case name
when "hmac-sha1" then Hmac.new("sha1")
when "hmac-sha256" then Hmac.new("sha256")
else raise UnknownAlgorithm.new(name)
when 'hmac-sha1' then Hmac.new('sha1')
when 'hmac-sha256' then Hmac.new('sha256')
else raise UnknownAlgorithm, name
end
end

Expand All @@ -14,6 +15,5 @@ def initialize(name)
super("Unknown algorithm name '#{name}'")
end
end

end
end
6 changes: 3 additions & 3 deletions lib/http_signatures/algorithm/hmac.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
require "openssl"
# frozen_string_literal: true

require 'openssl'

module HttpSignatures
module Algorithm
class Hmac

def initialize(digest_name)
@digest_name = digest_name
@digest = OpenSSL::Digest.new(digest_name)
Expand All @@ -16,7 +17,6 @@ def name
def sign(key, data)
OpenSSL::HMAC.digest(@digest, key, data)
end

end
end
end
6 changes: 3 additions & 3 deletions lib/http_signatures/context.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

module HttpSignatures
class Context

def initialize(keys: {}, signing_key_id: nil, algorithm: nil, headers: nil)
@key_store = KeyStore.new(keys)
@signing_key_id = signing_key_id
Expand All @@ -12,7 +13,7 @@ def signer
Signer.new(
key: signing_key,
algorithm: Algorithm.create(@algorithm_name),
header_list: HeaderList.new(@headers),
header_list: HeaderList.new(@headers)
)
end

Expand All @@ -29,6 +30,5 @@ def signing_key
@key_store.only_key
end
end

end
end
22 changes: 9 additions & 13 deletions lib/http_signatures/header_list.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# frozen_string_literal: true

module HttpSignatures
class HeaderList

# cannot sign the signature headers
ILLEGAL = ["authorization", "signature"]
# Cannot sign the signature headers
ILLEGAL = %w[authorization signature].freeze

def self.from_string(string)
new(string.split(" "))
new(string.split(' '))
end

def initialize(names)
Expand All @@ -18,18 +19,14 @@ def to_a
end

def to_str
@names.join(" ")
@names.join(' ')
end

private

def validate_names!
if @names.empty?
raise EmptyHeaderList
end
if illegal_headers_present.any?
raise IllegalHeader, illegal_headers_present
end
raise EmptyHeaderList if @names.empty?
raise IllegalHeader, illegal_headers_present if illegal_headers_present.any?
end

def illegal_headers_present
Expand All @@ -38,12 +35,11 @@ def illegal_headers_present

class IllegalHeader < StandardError
def initialize(names)
names_string = names.map { |n| "'#{n}'" }.join(", ")
names_string = names.map { |n| "'#{n}'" }.join(', ')
super("Header #{names_string} not permitted")
end
end

class EmptyHeaderList < StandardError; end

end
end
8 changes: 4 additions & 4 deletions lib/http_signatures/key.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

module HttpSignatures
class Key

def initialize(id:, secret:)
@id = id
@secret = secret
Expand All @@ -11,9 +12,8 @@ def initialize(id:, secret:)

def ==(other)
self.class == other.class &&
self.id == other.id &&
self.secret == other.secret
id == other.id &&
secret == other.secret
end

end
end
11 changes: 4 additions & 7 deletions lib/http_signatures/key_store.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

module HttpSignatures
class KeyStore

def initialize(key_hash)
@keys = {}
key_hash.each { |id, secret| self[id] = secret }
Expand All @@ -11,18 +12,14 @@ def fetch(id)
end

def only_key
if @keys.one?
@keys.values.first
else
raise KeyError, "Expected 1 key, found #{@keys.size}"
end
return @keys.values.first if @keys.one?
raise KeyError, "Expected 1 key, found #{@keys.size}"
end

private

def []=(id, secret)
@keys[id] = Key.new(id: id, secret: secret)
end

end
end
6 changes: 3 additions & 3 deletions lib/http_signatures/signature.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

module HttpSignatures
class Signature

def initialize(message:, key:, algorithm:, header_list:)
@message = message
@key = key
Expand All @@ -17,9 +18,8 @@ def to_str
def signing_string
SigningString.new(
header_list: @header_list,
message: @message,
message: @message
)
end

end
end
16 changes: 8 additions & 8 deletions lib/http_signatures/signature_parameters.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require "base64"
# frozen_string_literal: true

require 'base64'

module HttpSignatures
class SignatureParameters

def initialize(key:, algorithm:, header_list:, signature:)
@key = key
@algorithm = algorithm
Expand All @@ -11,23 +12,22 @@ def initialize(key:, algorithm:, header_list:, signature:)
end

def to_str
parameter_components.join(",")
parameter_components.join(',')
end

private

def parameter_components
pc = []
pc << 'keyId="%s"' % @key.id
pc << 'algorithm="%s"' % @algorithm.name
pc << 'headers="%s"' % @header_list.to_str
pc << 'signature="%s"' % signature_base64
pc << "keyId=\"#{@key.id}\""
pc << "algorithm=\"#{@algorithm.name}\""
pc << "headers=\"#{@header_list.to_str}\""
pc << "signature=\"#{signature_base64}\""
pc
end

def signature_base64
Base64.strict_encode64(@signature.to_str)
end

end
end
8 changes: 4 additions & 4 deletions lib/http_signatures/signature_parameters_parser.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

module HttpSignatures
class SignatureParametersParser

def initialize(string)
@string = string
end
Expand All @@ -16,7 +17,7 @@ def array_of_pairs
end

def segments
@string.split(",")
@string.split(',')
end

def pair(segment)
Expand All @@ -26,10 +27,9 @@ def pair(segment)
end

def segment_pattern
%r{\A(keyId|algorithm|headers|signature)="(.*)"\z}
/\A(keyId|algorithm|headers|signature)="(.*)"\z/
end

class Error < StandardError; end

end
end
Loading