Skip to content
This repository has been archived by the owner on Mar 1, 2023. It is now read-only.

Commit

Permalink
Merge 7c97a07 into ca6cf2e
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Greenberg committed Nov 14, 2019
2 parents ca6cf2e + 7c97a07 commit 3c23168
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 16 deletions.
23 changes: 14 additions & 9 deletions lib/nexmo/signature.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'openssl'
require 'digest/md5'
require 'jwt'

Expand All @@ -22,26 +23,30 @@ def initialize(secret)
#
# @see https://developer.nexmo.com/concepts/guides/signing-messages
#
def check(params)
def check(params, signature_method: 'md5hash')
params = params.dup

signature = params.delete('sig')

::JWT::SecurityUtils.secure_compare(signature, digest(params))
::JWT::SecurityUtils.secure_compare(signature, digest(params, signature_method))
end

private

def digest(params)
md5 = Digest::MD5.new

def digest(params, signature_method)
digest_string = ''
params.sort.each do |k, v|
md5.update("&#{k}=#{v}")
v = v.tr('&=', '')
digest_string << "&#{k}=#{v}"
end

md5.update(@secret)

md5.hexdigest
if ['md5', 'sha1', 'sha256', 'sha512'].include? signature_method
digest = OpenSSL::HMAC.hexdigest(signature_method, @secret, digest_string).upcase
elsif signature_method == 'md5hash'
digest = Digest::MD5.hexdigest("#{digest_string}#{@secret}")
else
raise "Unknown signature algorithm: #{signature_method}. Expected: md5hash, md5, sha1, sha256, or sha512."
end
end
end
end
76 changes: 69 additions & 7 deletions test/nexmo/signature_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,87 @@

class NexmoSignatureTest < Minitest::Test
def secret
'secret'
'my_secret_key_for_testing'
end

def params
{'a' => '1', 'b' => '2', 'timestamp' => '1461605396'}
{
'message-timestamp' => '2013-11-21 15:27:30',
'messageId' => '020000001B0FE827',
'msisdn' => '14843472194',
'text' => 'Test again',
'timestamp' => '1385047698',
'to' => '13239877404',
'type' => 'text'
}
end

def params_with_valid_signature
params.merge('sig' => '6af838ef94998832dbfc29020b564830')
def params_with_valid_signature_md5hash
params.merge('sig' => 'd2e7b1dc968737c5998ad624e02f90b7')
end

def params_with_valid_signature_md5
params.merge('sig' => 'DDEBD46008C2D4E93CCE578A332A52D5')
end

def params_with_valid_signature_sha1
params.merge('sig' => '27D0D05C2876C7CB1720DBCDBA4D492E1E55C09A')
end

def params_with_valid_signature_sha256
params.merge('sig' => 'DDB8397C2B90AAC7F3882D306475C9A5058C92322EEF43C92B298B6E0FC0D330')
end

def params_with_valid_signature_sha512
params.merge('sig' => 'E0D3C650F8C9D1A5C174D10DDDBFB003E561F59B265616208B0487C5D819481CD3C311D59CF6165ECD1139622D5BA3A256C0D763AC4A9AD9144B5A426B94FE82')
end

def params_with_invalid_signature
params.merge('sig' => 'xxx')
end

def test_check_instance_method
def test_check_instance_method_with_md5hash
signature = Nexmo::Signature.new(secret)

assert_equal signature.check(params_with_valid_signature), true
assert_equal signature.check(params_with_invalid_signature), false
assert_equal signature.check(params_with_valid_signature_md5hash, signature_method: 'md5hash'), true
assert_equal signature.check(params_with_invalid_signature, signature_method: 'md5hash'), false
end

def test_check_instance_method_with_md5hmac
signature = Nexmo::Signature.new(secret)

assert_equal signature.check(params_with_valid_signature_md5, signature_method: 'md5'), true
assert_equal signature.check(params_with_invalid_signature, signature_method: 'md5'), false
end

def test_check_instance_method_with_sha1
signature = Nexmo::Signature.new(secret)

assert_equal signature.check(params_with_valid_signature_sha1, signature_method: 'sha1'), true
assert_equal signature.check(params_with_invalid_signature, signature_method: 'sha1'), false
end

def test_check_instance_method_with_sha256
signature = Nexmo::Signature.new(secret)

assert_equal signature.check(params_with_valid_signature_sha256, signature_method: 'sha256'), true
assert_equal signature.check(params_with_invalid_signature, signature_method: 'sha256'), false
end

def test_check_instance_method_with_sha512
signature = Nexmo::Signature.new(secret)

assert_equal signature.check(params_with_valid_signature_sha512, signature_method: 'sha512'), true
assert_equal signature.check(params_with_invalid_signature, signature_method: 'sha512'), false
end

def test_check_instance_method_with_unknown_method
signature = Nexmo::Signature.new(secret)

exception = assert_raises RuntimeError do
signature.check(params_with_valid_signature_md5, signature_method: 'xxxx')
end

assert_equal 'Unknown signature algorithm: xxxx. Expected: md5hash, md5, sha1, sha256, or sha512.', exception.message
end
end

0 comments on commit 3c23168

Please sign in to comment.