#!/usr/bin/ruby require 'net/http' require 'json' require 'base64' require 'json/jwt' def request_directory( uri: ) http = Net::HTTP.new( uri.hostname, uri.port ) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE # http.set_debug_output($stdout) http.get( uri.path ).body end def request_nonce( uri: ) http = Net::HTTP.new( uri.hostname, uri.port ) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE # http.set_debug_output($stdout) res = http.head( uri.path ) res['Replay-Nonce'] end def request_newAccount( uri:, data: ) http = Net::HTTP.new( uri.hostname, uri.port ) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.set_debug_output($stdout) headers = { 'Content-Type': 'application/jose+json' } http.post( uri.path, data, headers ) end private_key = OpenSSL::PKey::EC.generate('prime256v1') puts "private_key" puts private_key puts "" public_key = private_key.public_key puts "public_key" puts public_key puts "" jwk_key = JSON::JWK.new(private_key) puts "jwk_key" puts jwk_key puts "" # jwk_public = JSON::JWK.new(public_key) # puts "public_key" # puts jwk_public # puts "" jwk_normalized = jwk_key.normalize puts "jwk_normalized" puts jwk_normalized puts "" # p JSON::JWK.new(public_key) # params = optional_parameters = { kid: 'foobar', use: 'sig', alg: 'ES256' } # jwk_key = JWT::JWK.new( ecdsa_key, params ) # puts "private jwk_key" # puts jwk_key.export( include_private: true ) # puts "public jwk_key" # puts jwk_key.export # acme_directory_uri = URI('https://acme-staging-v02.api.letsencrypt.org/directory') acme_directory_uri = URI('https://localhost:14000/dir') acme_directory_uri.freeze # acme_directory_json = Net::HTTP.get(acme_directory_uri) acme_directory_json = request_directory( uri: acme_directory_uri ) acme_directory = JSON.parse(acme_directory_json) puts "acme_directory" puts acme_directory puts "" newAccount_uri = URI( acme_directory['newAccount'] ) newNonce_uri = URI( acme_directory['newNonce'] ) nonce = request_nonce( :uri => newNonce_uri ) puts "nonce" puts nonce puts "" stub_account_for_new_account = { contact: [ "mailto:sysadmin@henk.geekmail.org" ], termsOfServiceAgreed: true, onlyReturnExisting: true, } stub_account_for_new_account_json = JSON.generate(stub_account_for_new_account) # puts "stub_account_for_new_account_json" # puts stub_account_for_new_account_json # puts "" stub_account_for_new_account_base64 = Base64.urlsafe_encode64(stub_account_for_new_account_json, padding: false) protected_request_header = { alg: 'ES256', nonce: nonce, url: newAccount_uri, jwk: jwk_normalized } protected_request_header_json = JSON.generate( protected_request_header ) puts "protected_request_header_json" puts protected_request_header_json puts "" protected_request_header_base64 = Base64.urlsafe_encode64( protected_request_header_json, padding: false ) newAccount_header_with_payload = JSON::JWT.new( stub_account_for_new_account) newAccount_header_with_payload.header[:alg] = 'ES256' newAccount_header_with_payload.header[:nonce] = nonce newAccount_header_with_payload.header[:url] = newAccount_uri newAccount_header_with_payload.header[:jwk] = jwk_normalized p newAccount_header_with_payload.header puts "newAccount_header_with_payload" puts newAccount_header_with_payload puts newAccount_header_with_payload.as_json( syntax: :flattened ) puts "" # newAccount_header_with_payload.kid = 'default_key' # #signing_key requires jwt somewhat newer than in debian stable (2.5.0) # stub_account_for_new_account_signature = JWT::Algos::Ecdsa.sign( 'ES256', newAccount_header_with_payload, jwk_key.signing_key ) # stub_account_for_new_account_signature = ecdsa_key.sign( nil, newAccount_header_with_payload ) # stub_account_for_new_account_signature = JWT.encode( newAccount_header_with_payload, jwk_key.signing_key, 'ES256', protected_request_header ).split('.')[-1] stub_account_for_new_account_signature = newAccount_header_with_payload.sign( jwk_key ) # stub_account_for_new_account_signature_base64 = Base64.urlsafe_encode64( stub_account_for_new_account_signature, padding: false ) puts "stub_account_for_new_account_signature" puts stub_account_for_new_account_signature # puts stub_account_for_new_account_signature_base64 puts "stub_account_for_new_account_signature_class" puts stub_account_for_new_account_signature.class puts "" puts "stub_account_for_new_account_signature" puts stub_account_for_new_account_signature puts "stub_account_for_new_account_signature.as_json flattened" puts stub_account_for_new_account_signature.as_json( syntax: :flattened ) # puts stub_account_for_new_account_signature_base64 puts "stub_account_for_new_account_signature.class" puts stub_account_for_new_account_signature.class puts "" # newAccount_request_body = { # :protected => protected_request_header_base64, # :payload => stub_account_for_new_account_base64, # :signature => stub_account_for_new_account_signature # } # # # newAccount_request_body_json = JSON.generate( newAccount_request_body ) # puts "newAccount_request_body_json" # puts newAccount_request_body_json # puts "" puts request_newAccount( :uri => newAccount_uri, :data => stub_account_for_new_account_signature.as_json( syntax: :flattened ) ) # puts request_newAccount( :uri => newAccount_uri, :data => stub_account_for_new_account_signature )