Skip to content

Commit 15879ed

Browse files
authored
Merge pull request #3 from cedarcode/add-ed25519-support
Add support for Ed25519
2 parents 658c39a + 2338eaf commit 15879ed

File tree

10 files changed

+121
-1
lines changed

10 files changed

+121
-1
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ gemspec
77

88
gem "appraisal", "~> 2.2"
99
gem "byebug", "~> 11.0"
10+
gem "ed25519", "~> 1.2"
1011
gem "rake", "~> 13.0"
1112
gem "rspec", "~> 3.0"
1213
gem "rubocop", "~> 0.80.1"

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)

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ algorithm.verify_key = verify_key
5252
algorithm.verify(signature, to_be_signed)
5353
```
5454

55+
### EdDSA
56+
57+
```ruby
58+
to_be_signed = "to-be-signed"
59+
60+
# Signer
61+
algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
62+
signing_key = algorithm.generate_signing_key
63+
signature = algorithm.sign(to_be_signed)
64+
65+
# Signer sends verify key to Verifier
66+
verify_key_string = signing_key.verify_key.serialize
67+
68+
# Verifier
69+
verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
70+
algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
71+
algorithm.verify_key = verify_key
72+
algorithm.verify(signature, to_be_signed)
73+
```
74+
5575
### RSA-PSS
5676

5777
```ruby

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::EdDSA requires the ed25519 gem, version 1.0 or higher. "\
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)