From 7fa47ce4ae595a5177083afaaa04fc6203ea9c21 Mon Sep 17 00:00:00 2001 From: Marco Colli Date: Thu, 5 Jan 2023 12:40:38 +0100 Subject: [PATCH] Add support for OpenSSL 3 Co-Authored-By: ClearlyClaire Co-Authored-By: xfalcox --- lib/web_push/encryption.rb | 3 +- lib/web_push/vapid_key.rb | 47 ++++++++++++++++++++++---------- lib/web_push/version.rb | 2 +- spec/web_push/encryption_spec.rb | 4 +-- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/lib/web_push/encryption.rb b/lib/web_push/encryption.rb index 2d33f1d..4fe1dea 100644 --- a/lib/web_push/encryption.rb +++ b/lib/web_push/encryption.rb @@ -10,8 +10,7 @@ def encrypt(message, p256dh, auth) group_name = 'prime256v1' salt = Random.new.bytes(16) - server = OpenSSL::PKey::EC.new(group_name) - server.generate_key + server = OpenSSL::PKey::EC.generate(group_name) server_public_key_bn = server.public_key.to_bn group = OpenSSL::PKey::EC::Group.new(group_name) diff --git a/lib/web_push/vapid_key.rb b/lib/web_push/vapid_key.rb index c69f7aa..8310b86 100644 --- a/lib/web_push/vapid_key.rb +++ b/lib/web_push/vapid_key.rb @@ -10,9 +10,7 @@ class VapidKey # @return [WebPush::VapidKey] a VapidKey instance for the given public and private keys def self.from_keys(public_key, private_key) key = new - key.public_key = public_key - key.private_key = private_key - + key.set_keys! public_key, private_key key end @@ -20,19 +18,14 @@ def self.from_keys(public_key, private_key) # # @return [WebPush::VapidKey] a VapidKey instance for the given public and private keys def self.from_pem(pem) - key = new - src = OpenSSL::PKey.read pem - key.curve.public_key = src.public_key - key.curve.private_key = src.private_key - - key + new(OpenSSL::PKey.read(pem)) end attr_reader :curve - def initialize - @curve = OpenSSL::PKey::EC.new('prime256v1') - @curve.generate_key + def initialize(pkey = nil) + @curve = pkey + @curve = OpenSSL::PKey::EC.generate('prime256v1') if @curve.nil? end # Retrieve the encoded elliptic curve public key for VAPID protocol @@ -57,11 +50,37 @@ def private_key end def public_key=(key) - curve.public_key = OpenSSL::PKey::EC::Point.new(group, to_big_num(key)) + set_keys! key, nil end def private_key=(key) - curve.private_key = to_big_num(key) + set_keys! nil, key + end + + def set_keys!(public_key = nil, private_key = nil) + if public_key.nil? + public_key = curve.public_key + else + public_key = OpenSSL::PKey::EC::Point.new(group, to_big_num(public_key)) + end + + if private_key.nil? + private_key = curve.private_key + else + private_key = to_big_num(private_key) + end + + asn1 = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer.new(1), + # Not properly padded but OpenSSL doesn't mind + OpenSSL::ASN1::OctetString(private_key.to_s(2)), + OpenSSL::ASN1::ObjectId('prime256v1', 0, :EXPLICIT), + OpenSSL::ASN1::BitString(public_key.to_octet_string(:uncompressed), 1, :EXPLICIT), + ]) + + der = asn1.to_der + + @curve = OpenSSL::PKey::EC.new(der) end def curve_name diff --git a/lib/web_push/version.rb b/lib/web_push/version.rb index 574ef9c..f1f27a1 100644 --- a/lib/web_push/version.rb +++ b/lib/web_push/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module WebPush - VERSION = '2.1.0'.freeze + VERSION = '3.0.0'.freeze end diff --git a/spec/web_push/encryption_spec.rb b/spec/web_push/encryption_spec.rb index 19ee27e..3aed2ac 100644 --- a/spec/web_push/encryption_spec.rb +++ b/spec/web_push/encryption_spec.rb @@ -4,9 +4,7 @@ describe '#encrypt' do let(:curve) do group = 'prime256v1' - curve = OpenSSL::PKey::EC.new(group) - curve.generate_key - curve + OpenSSL::PKey::EC.generate(group) end let(:p256dh) do