Skip to content

Add support for Ed25519 #3

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

Merged
merged 1 commit into from
Feb 11, 2021
Merged
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
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
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ algorithm.verify_key = verify_key
algorithm.verify(signature, to_be_signed)
```

### EdDSA

```ruby
to_be_signed = "to-be-signed"

# Signer
algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
signing_key = algorithm.generate_signing_key
signature = algorithm.sign(to_be_signed)

# Signer sends verify key to Verifier
verify_key_string = signing_key.verify_key.serialize

# Verifier
verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
algorithm.verify_key = verify_key
algorithm.verify(signature, to_be_signed)
```

### RSA-PSS

```ruby
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"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

require "ed25519"
rescue LoadError
warn "OpenSSL::SignatureAlgorithm::EdDSA requires the ed25519 gem, version 1.0 or higher. "\
"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 = ["gonzalo@cedarcode.com"]
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"
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks!

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