Skip to content

Commit 694ad2b

Browse files
santiagorodriguez96grzuy
authored andcommitted
feat: add support for Ed25519
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
1 parent 658c39a commit 694ad2b

File tree

9 files changed

+103
-1
lines changed

9 files changed

+103
-1
lines changed

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ gem "byebug", "~> 11.0"
1010
gem "rake", "~> 13.0"
1111
gem "rspec", "~> 3.0"
1212
gem "rubocop", "~> 0.80.1"
13+
gem "ed25519", "~> 1.2"
14+
15+
gem "ed25519", "~> 1.2"

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ GEM
1414
ast (2.4.0)
1515
byebug (11.1.1)
1616
diff-lcs (1.3)
17+
ed25519 (1.2.4)
1718
jaro_winkler (1.5.4)
1819
openssl (2.2.0)
1920
parallel (1.19.1)
@@ -53,6 +54,7 @@ PLATFORMS
5354
DEPENDENCIES
5455
appraisal (~> 2.2)
5556
byebug (~> 11.0)
57+
ed25519 (~> 1.2)
5658
openssl-signature_algorithm!
5759
rake (~> 13.0)
5860
rspec (~> 3.0)

gemfiles/openssl_2_0.gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ gem "byebug", "~> 11.0"
77
gem "rake", "~> 13.0"
88
gem "rspec", "~> 3.0"
99
gem "rubocop", "~> 0.80.1"
10+
gem "ed25519", "~> 1.2"
1011
gem "openssl", "~> 2.0.0"
1112

1213
gemspec path: "../"

gemfiles/openssl_2_1.gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ gem "byebug", "~> 11.0"
77
gem "rake", "~> 13.0"
88
gem "rspec", "~> 3.0"
99
gem "rubocop", "~> 0.80.1"
10+
gem "ed25519", "~> 1.2"
1011
gem "openssl", "~> 2.1.0"
1112

1213
gemspec path: "../"

gemfiles/openssl_2_2.gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ gem "byebug", "~> 11.0"
77
gem "rake", "~> 13.0"
88
gem "rspec", "~> 3.0"
99
gem "rubocop", "~> 0.80.1"
10+
gem "ed25519", "~> 1.2"
1011
gem "openssl", "~> 2.2.0"
1112

1213
gemspec path: "../"

lib/openssl/signature_algorithm.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require "openssl/signature_algorithm/ecdsa"
4+
require "openssl/signature_algorithm/eddsa"
45
require "openssl/signature_algorithm/error"
56
require "openssl/signature_algorithm/rsapss"
67
require "openssl/signature_algorithm/rsapkcs1"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
3+
begin
4+
gem "ed25519", ">= 1.0.0"
5+
require "ed25519"
6+
rescue LoadError
7+
warn "OpenSSL-SignatureAlgorithm requires the ed25519 gem, version 1.0 or later. "\
8+
"Please add it to your Gemfile: `gem \"ed25519\", \"~> 1.0\"`"
9+
raise
10+
end
11+
12+
require "openssl/signature_algorithm/base"
13+
14+
module OpenSSL
15+
module SignatureAlgorithm
16+
class EdDSA < Base
17+
class SigningKey < ::Ed25519::SigningKey
18+
def verify_key
19+
VerifyKey.new(keypair[32, 32])
20+
end
21+
end
22+
23+
class VerifyKey < ::Ed25519::VerifyKey
24+
def self.deserialize(key_bytes)
25+
new(key_bytes)
26+
end
27+
28+
def serialize
29+
to_bytes
30+
end
31+
end
32+
33+
def generate_signing_key
34+
@signing_key = SigningKey.generate
35+
end
36+
37+
def sign(data)
38+
signing_key.sign(data)
39+
end
40+
41+
def verify(signature, verification_data)
42+
verify_key.verify(signature, verification_data)
43+
rescue ::Ed25519::VerifyError
44+
raise(OpenSSL::SignatureAlgorithm::SignatureVerificationError, "Signature verification failed")
45+
end
46+
end
47+
end
48+
end

openssl-signature_algorithm.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
99
spec.email = ["gonzalo@cedarcode.com"]
1010
spec.license = "Apache-2.0"
1111

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

1515
spec.homepage = "https://github.com/cedarcode/openssl-signature_algorithm"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# frozen_string_literal: true
2+
3+
require "openssl/signature_algorithm/eddsa"
4+
5+
RSpec.describe "OpenSSL::SignatureAlgorithm::EdDSA" do
6+
let(:to_be_signed) { "to-be-signed" }
7+
let(:signature) do
8+
signing_key
9+
signer_algorithm.sign(to_be_signed)
10+
end
11+
let(:signer_algorithm) { OpenSSL::SignatureAlgorithm::EdDSA.new }
12+
let(:signing_key) { signer_algorithm.generate_signing_key }
13+
let(:verifier_algorithm) { OpenSSL::SignatureAlgorithm::EdDSA.new }
14+
15+
context "when everything is in place" do
16+
it "works" do
17+
# Signer sends verify key to Verifier
18+
verify_key_string = signing_key.verify_key.serialize
19+
20+
# Verifier
21+
verifier_algorithm.verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
22+
expect(verifier_algorithm.verify(signature, to_be_signed)).to be_truthy
23+
end
24+
end
25+
26+
context "when signature is invalid" do
27+
let(:signature) do
28+
signing_key
29+
signature = signer_algorithm.sign(to_be_signed)
30+
signature[63] = 'X' # Change the last byte to make it incorrect
31+
32+
signature
33+
end
34+
35+
it "raises an error" do
36+
# Signer sends verify key to Verifier
37+
verify_key_string = signing_key.verify_key.serialize
38+
39+
# Verifier
40+
verifier_algorithm.verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
41+
expect { verifier_algorithm.verify(signature, to_be_signed) }
42+
.to raise_error(OpenSSL::SignatureAlgorithm::SignatureVerificationError)
43+
end
44+
end
45+
end

0 commit comments

Comments
 (0)