Skip to content

Commit 127bc75

Browse files
Add OpenSSL3 support (#1)
* Fix compatibility with OpenSSL 3 * Fix tests * Further OpenSSL 3 fixes * Use public_to_pem instead of lower-level ASN1 representation
1 parent 061ff9a commit 127bc75

3 files changed

Lines changed: 37 additions & 23 deletions

File tree

lib/webpush/encryption.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ def encrypt(message, p256dh, auth)
1111
group_name = 'prime256v1'
1212
salt = Random.new.bytes(16)
1313

14-
server = OpenSSL::PKey::EC.new(group_name)
15-
server.generate_key
14+
server = OpenSSL::PKey::EC.generate(group_name)
1615
server_public_key_bn = server.public_key.to_bn
1716

1817
group = OpenSSL::PKey::EC::Group.new(group_name)
@@ -74,4 +73,4 @@ def blank?(value)
7473
value.nil? || value.empty?
7574
end
7675
end
77-
end
76+
end

lib/webpush/vapid_key.rb

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ class VapidKey
1010
# @return [Webpush::VapidKey] a VapidKey instance for the given public and private keys
1111
def self.from_keys(public_key, private_key)
1212
key = new
13-
key.public_key = public_key
14-
key.private_key = private_key
13+
key.set_keys!(public_key, private_key)
1514

1615
key
1716
end
@@ -20,19 +19,14 @@ def self.from_keys(public_key, private_key)
2019
#
2120
# @return [Webpush::VapidKey] a VapidKey instance for the given public and private keys
2221
def self.from_pem(pem)
23-
key = new
24-
src = OpenSSL::PKey.read pem
25-
key.curve.public_key = src.public_key
26-
key.curve.private_key = src.private_key
27-
28-
key
22+
new(OpenSSL::PKey.read pem)
2923
end
3024

3125
attr_reader :curve
3226

33-
def initialize
34-
@curve = OpenSSL::PKey::EC.new('prime256v1')
35-
@curve.generate_key
27+
def initialize(pkey = nil)
28+
@curve = pkey
29+
@curve = OpenSSL::PKey::EC.generate('prime256v1') if @curve.nil?
3630
end
3731

3832
# Retrieve the encoded elliptic curve public key for VAPID protocol
@@ -57,11 +51,11 @@ def private_key
5751
end
5852

5953
def public_key=(key)
60-
curve.public_key = OpenSSL::PKey::EC::Point.new(group, to_big_num(key))
54+
set_keys!(key, nil)
6155
end
6256

6357
def private_key=(key)
64-
curve.private_key = to_big_num(key)
58+
set_keys!(nil, key)
6559
end
6660

6761
def curve_name
@@ -78,16 +72,39 @@ def to_h
7872
alias to_hash to_h
7973

8074
def to_pem
81-
public_key = OpenSSL::PKey::EC.new curve
82-
public_key.private_key = nil
83-
84-
curve.to_pem + public_key.to_pem
75+
curve.to_pem + curve.public_to_pem
8576
end
8677

8778
def inspect
8879
"#<#{self.class}:#{object_id.to_s(16)} #{to_h.map { |k, v| ":#{k}=#{v}" }.join(' ')}>"
8980
end
9081

82+
def set_keys!(public_key = nil, private_key = nil)
83+
if public_key.nil?
84+
public_key = curve.public_key
85+
else
86+
public_key = OpenSSL::PKey::EC::Point.new(group, to_big_num(public_key))
87+
end
88+
89+
if private_key.nil?
90+
private_key = curve.private_key
91+
else
92+
private_key = to_big_num(private_key)
93+
end
94+
95+
asn1 = OpenSSL::ASN1::Sequence([
96+
OpenSSL::ASN1::Integer.new(1),
97+
# Not properly padded but OpenSSL doesn't mind
98+
OpenSSL::ASN1::OctetString(private_key.to_s(2)),
99+
OpenSSL::ASN1::ObjectId('prime256v1', 0, :EXPLICIT),
100+
OpenSSL::ASN1::BitString(public_key.to_octet_string(:uncompressed), 1, :EXPLICIT),
101+
])
102+
103+
der = asn1.to_der
104+
105+
@curve = OpenSSL::PKey::EC.new(der)
106+
end
107+
91108
private
92109

93110
def to_big_num(key)

spec/webpush/encryption_spec.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
describe '#encrypt' do
55
let(:curve) do
66
group = 'prime256v1'
7-
curve = OpenSSL::PKey::EC.new(group)
8-
curve.generate_key
9-
curve
7+
OpenSSL::PKey::EC.generate(group)
108
end
119

1210
let(:p256dh) do

0 commit comments

Comments
 (0)