Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for ED25519 #229

Merged
merged 4 commits into from
Sep 6, 2017
Merged

Support for ED25519 #229

merged 4 commits into from
Sep 6, 2017

Conversation

ab320012
Copy link
Contributor

@ab320012 ab320012 commented Sep 6, 2017

Added support + tests, readme section for eddsa algo ed25519
#217

@sourcelevel-bot
Copy link

Hello, @ab320012! This is your first Pull Request that will be reviewed by Ebert, an automatic Code Review service. It will leave comments on this diff with potential issues and style violations found in the code as you push new commits. You can also see all the issues found on this Pull Request on its review page. Please check our documentation for more information.

def sign_eddsa(algorithm, msg, private_key)
raise EncodeError, "Key given is a #{private_key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey" if private_key.class != RbNaCl::Signatures::Ed25519::SigningKey
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{private_key.primitive} signing key was provided" if algorithm.downcase.to_sym != private_key.primitive
private_key.sign(msg)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace detected.

@@ -17,7 +17,8 @@ module Signature
HMAC_ALGORITHMS = %w[HS256 HS512256 HS384 HS512].freeze
RSA_ALGORITHMS = %w[RS256 RS384 RS512].freeze
ECDSA_ALGORITHMS = %w[ES256 ES384 ES512].freeze

EDDSA_ALGORITHMS = %w[ED25519].freeze

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace detected.

@@ -79,13 +88,16 @@ def sign_hmac(algorithm, msg, key)
OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
end
end

def verify_eddsa(algorithm, public_key,signing_input, signature)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space missing after comma.

@@ -17,7 +17,8 @@ module Signature
HMAC_ALGORITHMS = %w[HS256 HS512256 HS384 HS512].freeze
RSA_ALGORITHMS = %w[RS256 RS384 RS512].freeze
ECDSA_ALGORITHMS = %w[ES256 ES384 ES512].freeze

EDDSA_ALGORITHMS = %w[ED25519].freeze

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%w-literals should be delimited by ( and ).

@@ -79,13 +88,16 @@ def sign_hmac(algorithm, msg, key)
OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
end
end

def verify_eddsa(algorithm, public_key,signing_input, signature)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use empty lines between method definitions.

@@ -70,7 +75,11 @@ def sign_ecdsa(algorithm, msg, private_key)
digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
SecurityUtils.asn1_to_raw(private_key.dsa_sign_asn1(digest.digest(msg)), private_key)
end

def sign_eddsa(algorithm, msg, private_key)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use empty lines between method definitions.

@@ -43,6 +46,8 @@ def verify(algo, key, signing_input, signature)
SecurityUtils.verify_rsa(algo, key, signing_input, signature)
elsif ECDSA_ALGORITHMS.include?(algo)
verify_ecdsa(algo, key, signing_input, signature)
elsif EDDSA_ALGORITHMS.include?(algo)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Align elsif with if.

@@ -79,13 +88,16 @@ def sign_hmac(algorithm, msg, key)
OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
end
end

def verify_eddsa(algorithm, public_key,signing_input, signature)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JWT::Signature takes parameters ['algorithm', 'public_key', 'signature', 'signing_input'] to 3 methods

Read more about it here.

@@ -17,6 +17,7 @@ module Signature
HMAC_ALGORITHMS = %w[HS256 HS512256 HS384 HS512].freeze
RSA_ALGORITHMS = %w[RS256 RS384 RS512].freeze
ECDSA_ALGORITHMS = %w[ES256 ES384 ES512].freeze
EDDSA_ALGORITHMS = %w[ED25519].freeze

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%w-literals should be delimited by ( and ).

@@ -80,12 +91,17 @@ def sign_hmac(algorithm, msg, key)
end
end

def verify_eddsa(algorithm, public_key, signing_input, signature)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JWT::Signature takes parameters ['algorithm', 'public_key', 'signature', 'signing_input'] to 3 methods

Read more about it here.

@sourcelevel-bot
Copy link

Ebert has finished reviewing this Pull Request and has found:

  • 6 possible new issues (including those that may have been commented here).

You can see more details about this review at https://ebertapp.io/github/jwt/ruby-jwt/pulls/229.

@ab320012
Copy link
Contributor Author

ab320012 commented Sep 6, 2017

method length + complexity for verify and arity of sign + verify eddsa methods follow the surrounding code convention. I can probably fix these but would have to modify existing code, let me know if this is ok

Here is a snippet to remove longevity of if statements that doesn't modify the code base much at all.

    ALGOS = [
      {name: :hmac, types: %(HS256 HS512256 HS384 HS512).freeze },
      {name: :rsa, types: %w(RS256 RS384 RS512).freeze }, 
      {name: :ecdsa, types: %w(ES256 ES384 ES512).freeze },
      {name: :eddsa, types: %w(ED25519).freeze }
    ]
    def sign(algorithm, msg, key)
      algo= ALGOS.find{|algo| 
        algo[:types].include? algorithm
      }
      raise NotImplementedError, 'Unsupported signing method'  if algo.nil? 
      self.send("sign_#{algo[:name]}", algorithm, msg, key) 
    end

    def verify(algorithm, key, signing_input, signature)
      algo= ALGOS.find{|algo|
        algo[:types].include? algorithm 
      }
      raise JWT::VerificationError, 'Algorithm not supported' if algo.nil?  
      verified = self.send("verify_#{algo[:name]}", algorithm, key, signing_input, signature)
      raise JWT::VerificationError, 'Signature verification raised' unless verified 
    end

@excpt
Copy link
Member

excpt commented Sep 6, 2017

@ab320012 Thank you for the PR!

Refactoring the code to reduce the arity and other code smells should happen in a different PR. Don't do it in this PR.

Reviewing you code now.

@excpt excpt self-assigned this Sep 6, 2017
@excpt excpt self-requested a review September 6, 2017 19:40
@excpt excpt added this to the Version 2.1.0 milestone Sep 6, 2017
@ab320012
Copy link
Contributor Author

ab320012 commented Sep 6, 2017

@excpt Thanks, will add that one after this one closes. Wondering if class based solution will make more sense.

# lib/jwt/algos/hmac.rb
class Hmac
   # other classes same structure: ecdsa, eddsa, rsa
  TYPES= %w(HS256 HS512256 HS384 HS512).freeze 
 def initialize; end 
 def sign (signing_input); end
 def verify(verifying_input); end 
end

# signing_input and verifying_input will be refactored into a struct 

#lib/signature.rb 
Signed = Struct.new(:algo, :key, :msg) 
Verified = Struct.new(:algorithm, :public_key, :signing_input, :signature)

Let me know if something like this is ok with you for next PR

@excpt
Copy link
Member

excpt commented Sep 6, 2017

@ab320012 That's the way to go. Most important: the two signatures of the main methods JWT.encode and JWT.decode need to stay the same. Everything else is code behind and that should not break anything for the users.

@excpt excpt merged commit ace22c6 into jwt:master Sep 6, 2017
@excpt excpt mentioned this pull request Sep 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants