From cd809a6b69790b48344abfaa294edd8c4d4c7231 Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 30 Aug 2016 23:27:39 -0700 Subject: added acme-client gem --- vendor/acme-client/lib/acme/client/crypto.rb | 98 ++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 vendor/acme-client/lib/acme/client/crypto.rb (limited to 'vendor/acme-client/lib/acme/client/crypto.rb') diff --git a/vendor/acme-client/lib/acme/client/crypto.rb b/vendor/acme-client/lib/acme/client/crypto.rb new file mode 100644 index 0000000..dfa5cdc --- /dev/null +++ b/vendor/acme-client/lib/acme/client/crypto.rb @@ -0,0 +1,98 @@ +class Acme::Client::Crypto + attr_reader :private_key + + def initialize(private_key) + @private_key = private_key + end + + def generate_signed_jws(header:, payload:) + header = { typ: 'JWT', alg: jws_alg, jwk: jwk }.merge(header) + + encoded_header = urlsafe_base64(header.to_json) + encoded_payload = urlsafe_base64(payload.to_json) + signature_data = "#{encoded_header}.#{encoded_payload}" + + signature = private_key.sign digest, signature_data + encoded_signature = urlsafe_base64(signature) + + { + protected: encoded_header, + payload: encoded_payload, + signature: encoded_signature + }.to_json + end + + def thumbprint + urlsafe_base64 digest.digest(jwk.to_json) + end + + def digest + OpenSSL::Digest::SHA256.new + end + + def urlsafe_base64(data) + Base64.urlsafe_encode64(data).sub(/[\s=]*\z/, '') + end + + private + + def jws_alg + { 'RSA' => 'RS256', 'EC' => 'ES256' }.fetch(jwk[:kty]) + end + + def jwk + @jwk ||= case private_key + when OpenSSL::PKey::RSA + rsa_jwk + when OpenSSL::PKey::EC + ec_jwk + else + raise ArgumentError, "Can't handle #{private_key} as private key, only OpenSSL::PKey::RSA and OpenSSL::PKey::EC" + end + end + + def rsa_jwk + { + e: urlsafe_base64(public_key.e.to_s(2)), + kty: 'RSA', + n: urlsafe_base64(public_key.n.to_s(2)) + } + end + + def ec_jwk + { + crv: curve_name, + kty: 'EC', + x: urlsafe_base64(coordinates[:x].to_s(2)), + y: urlsafe_base64(coordinates[:y].to_s(2)) + } + end + + def curve_name + { + 'prime256v1' => 'P-256', + 'secp384r1' => 'P-384', + 'secp521r1' => 'P-521' + }.fetch(private_key.group.curve_name) { raise ArgumentError, 'Unknown EC curve' } + end + + # rubocop:disable Metrics/AbcSize + def coordinates + @coordinates ||= begin + hex = public_key.to_bn.to_s(16) + data_len = hex.length - 2 + hex_x = hex[2, data_len / 2] + hex_y = hex[2 + data_len / 2, data_len / 2] + + { + x: OpenSSL::BN.new([hex_x].pack('H*'), 2), + y: OpenSSL::BN.new([hex_y].pack('H*'), 2) + } + end + end + # rubocop:enable Metrics/AbcSize + + def public_key + @public_key ||= private_key.public_key + end +end -- cgit v1.2.3