Skip to content

Commit

Permalink
feat: add support for Ed25519
Browse files Browse the repository at this point in the history
This commit attempts to close #2.

Used the gem RubyCrypto/ed25519 as we still require ruby/openssl to
expose the required OpenSSL APIs in Ruby, expected to be released as 3.0
– See ruby/openssl#329.
Once OpenSSL Ruby v3.0 is released, we could change the implementation
in a way that users that use this gem alongside that version of OpenSSL
will use the API provided by OpenSSL, but users with an older version of
OpenSSL will still be provided with Ed25519 support with the use of
RubyCrypto/ed25519
  • Loading branch information
santiagorodriguez96 authored and grzuy committed Feb 10, 2021
1 parent 658c39a commit d88f9a8
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 1 deletion.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ gemspec

gem "appraisal", "~> 2.2"
gem "byebug", "~> 11.0"
gem "ed25519", "~> 1.2"
gem "rake", "~> 13.0"
gem "rspec", "~> 3.0"
gem "rubocop", "~> 0.80.1"
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ GEM
ast (2.4.0)
byebug (11.1.1)
diff-lcs (1.3)
ed25519 (1.2.4)
jaro_winkler (1.5.4)
openssl (2.2.0)
parallel (1.19.1)
Expand Down Expand Up @@ -53,6 +54,7 @@ PLATFORMS
DEPENDENCIES
appraisal (~> 2.2)
byebug (~> 11.0)
ed25519 (~> 1.2)
openssl-signature_algorithm!
rake (~> 13.0)
rspec (~> 3.0)
Expand Down
1 change: 1 addition & 0 deletions gemfiles/openssl_2_0.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ gem "byebug", "~> 11.0"
gem "rake", "~> 13.0"
gem "rspec", "~> 3.0"
gem "rubocop", "~> 0.80.1"
gem "ed25519", "~> 1.2"
gem "openssl", "~> 2.0.0"

gemspec path: "../"
1 change: 1 addition & 0 deletions gemfiles/openssl_2_1.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ gem "byebug", "~> 11.0"
gem "rake", "~> 13.0"
gem "rspec", "~> 3.0"
gem "rubocop", "~> 0.80.1"
gem "ed25519", "~> 1.2"
gem "openssl", "~> 2.1.0"

gemspec path: "../"
1 change: 1 addition & 0 deletions gemfiles/openssl_2_2.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ gem "byebug", "~> 11.0"
gem "rake", "~> 13.0"
gem "rspec", "~> 3.0"
gem "rubocop", "~> 0.80.1"
gem "ed25519", "~> 1.2"
gem "openssl", "~> 2.2.0"

gemspec path: "../"
1 change: 1 addition & 0 deletions lib/openssl/signature_algorithm.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "openssl/signature_algorithm/ecdsa"
require "openssl/signature_algorithm/eddsa"
require "openssl/signature_algorithm/error"
require "openssl/signature_algorithm/rsapss"
require "openssl/signature_algorithm/rsapkcs1"
Expand Down
48 changes: 48 additions & 0 deletions lib/openssl/signature_algorithm/eddsa.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

begin
gem "ed25519", ">= 1.0.0"
require "ed25519"
rescue LoadError
warn "OpenSSL::SignatureAlgorithm::EdDSA requires the ed25519 gem, version 1.0 or later. "\
"Please add it to your Gemfile: `gem \"ed25519\", \"~> 1.0\"`"
raise
end

require "openssl/signature_algorithm/base"

module OpenSSL
module SignatureAlgorithm
class EdDSA < Base
class SigningKey < ::Ed25519::SigningKey
def verify_key
VerifyKey.new(keypair[32, 32])
end
end

class VerifyKey < ::Ed25519::VerifyKey
def self.deserialize(key_bytes)
new(key_bytes)
end

def serialize
to_bytes
end
end

def generate_signing_key
@signing_key = SigningKey.generate
end

def sign(data)
signing_key.sign(data)
end

def verify(signature, verification_data)
verify_key.verify(signature, verification_data)
rescue ::Ed25519::VerifyError
raise(OpenSSL::SignatureAlgorithm::SignatureVerificationError, "Signature verification failed")
end
end
end
end
2 changes: 1 addition & 1 deletion openssl-signature_algorithm.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
spec.email = ["[email protected]"]
spec.license = "Apache-2.0"

spec.summary = "ECDSA, RSA-PSS and RSA-PKCS#1 algorithms for ruby"
spec.summary = "ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 algorithms for ruby"
spec.description = spec.summary

spec.homepage = "https://github.com/cedarcode/openssl-signature_algorithm"
Expand Down
45 changes: 45 additions & 0 deletions spec/openssl/signature_algorithm/eddsa_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

require "openssl/signature_algorithm/eddsa"

RSpec.describe "OpenSSL::SignatureAlgorithm::EdDSA" do
let(:to_be_signed) { "to-be-signed" }
let(:signature) do
signing_key
signer_algorithm.sign(to_be_signed)
end
let(:signer_algorithm) { OpenSSL::SignatureAlgorithm::EdDSA.new }
let(:signing_key) { signer_algorithm.generate_signing_key }
let(:verifier_algorithm) { OpenSSL::SignatureAlgorithm::EdDSA.new }

context "when everything is in place" do
it "works" do
# Signer sends verify key to Verifier
verify_key_string = signing_key.verify_key.serialize

# Verifier
verifier_algorithm.verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
expect(verifier_algorithm.verify(signature, to_be_signed)).to be_truthy
end
end

context "when signature is invalid" do
let(:signature) do
signing_key
signature = signer_algorithm.sign(to_be_signed)
signature[63] = 'X' # Change the last byte to make it incorrect

signature
end

it "raises an error" do
# Signer sends verify key to Verifier
verify_key_string = signing_key.verify_key.serialize

# Verifier
verifier_algorithm.verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
expect { verifier_algorithm.verify(signature, to_be_signed) }
.to raise_error(OpenSSL::SignatureAlgorithm::SignatureVerificationError)
end
end
end

0 comments on commit d88f9a8

Please sign in to comment.