%% Copyright 2015-2020 Guillaume Bour %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -module(letsencrypt_jws). -author("Guillaume Bour "). -export([init/1, encode/3, keyauth/2]). % init(Key) % % Initialize a RSA JWS with given private key. % % returns: % JWS -spec init(letsencrypt:ssl_privatekey()) -> letsencrypt:jws(). init(#{b64 := {N,E}}) -> #{ alg => 'RS256', jwk => #{ kty => 'RSA', <<"n">> => N, <<"e">> => E }, nonce => undefined }. % encode(Key, Jws, Payload) % % Build Jws body. % ref: https://www.rfc-editor.org/rfc/rfc8555.html#section-6.2 % % returns: % JwsBody % -spec encode(letsencrypt:ssl_privatekey(), letsencrypt:jws(), map()|empty) -> binary(). encode(#{raw := RSAKey}, Jws, Content) -> Protected = letsencrypt_utils:b64encode(jiffy:encode(Jws)), Payload = case Content of % for POST-as-GET queries, payload is just an empty string empty -> <<"">>; _ -> letsencrypt_utils:b64encode(jiffy:encode(Content)) end, Sign = crypto:sign(rsa, sha256, <>, RSAKey), Sign2 = letsencrypt_utils:b64encode(Sign), jiffy:encode({[ %{header, {[]}}, {protected, Protected}, {payload , Payload}, {signature, Sign2} ]}). % keyauth(Key, Token) % % Build acme key authorization. % ref: https://www.rfc-editor.org/rfc/rfc8555.html#section-8.1 % % returns: % KeyAuthorization % keyauth(#{<<"e">> := E, <<"n">> := N, <<"kty">> := Kty}, Token) -> Thumbprint = jiffy:encode({[ {e, E}, {kty, Kty}, {n, N} ]}, [force_utf8]), <>.