2017-02-04 1 views
0

Je suis en train d'écrire un client ACME Let's Encrypt dans Elixir + escript. Les bases semblent être presque terminées, sauf quand je soumets, je reçois une erreur de retour que la clé est trop grande. J'ai inclus le code source complet ainsi que les résultats de IO.inspect.Clé trop grande - Let's Encrypt + Elixir

code:

defmodule NginxDockerCerts do 

    @base "https://acme-staging.api.letsencrypt.org" 

    def main(_args) do 
    { :ok, %{ body: body } } = HTTPoison.get(@base <> "/directory") 
    endpoints = Poison.decode!(body) 
    response = send_request(
     endpoints["new-reg"], 
     %{ resource: "new-reg", contact: ["mailto:[email protected]"] }) 
    IO.inspect(response) 
    end 


    defp send_request(url, payload) do 
    [private_pem] = File.read!("acme_key/private.key") |> :public_key.pem_decode 
    private_key = :public_key.pem_entry_decode(private_pem) 
    IO.inspect(private_key) 
    header = generate_header(private_key) 
    request = %{ 
     payload: b64(payload), 
     header: header, 
     protected: Map.merge(header, %{ nonce: nonce() }) |> b64 
    } 
    signature = "#{request[:payload]}.#{request[:protected]}" 
     |> :public_key.sign(:sha256, private_key) 
     |> b64 
    request = Map.put(request, :signature, signature) 
    IO.inspect Poison.encode!(request) 
    HTTPoison.post(url, Poison.encode!(request)) 
    end 

    def nonce do 
    { :ok, %{ headers: le_headers } } = HTTPoison.head(@base <> "/directory") 
    %{ "Replay-Nonce" => ret } = Enum.into(le_headers, %{}) 
    ret 
    end 

    # From the erlang docs: 
    # Key = public_key:pem_entry_decode(RSAEntry, "abcd1234"). 
    # 'RSAPrivateKey'{version = 'two-prime', 
    # modulus = 1112355156729921663373...2737107, 
    # publicExponent = 65537, 
    # privateExponent = 58064406231183...2239766033, 
    # prime1 = 11034766614656598484098...7326883017, 
    # prime2 = 10080459293561036618240...77738643771, 
    # exponent1 = 77928819327425934607...22152984217, 
    # exponent2 = 36287623121853605733...20588523793, 
    # coefficient = 924840412626098444...41820968343, 
    # otherPrimeInfos = asn1_NOVALUE} 
    defp generate_header(tuple) do 
    modulus = elem(tuple, 2) |> Integer.to_string |> b64 
    exponent = elem(tuple, 3) |> Integer.to_string |> b64 
    %{ 
     alg: "RS256", 
     jwk: %{ e: exponent, kty: "RSA", n: modulus } 
    } 
    end 

    defp b64(map) when is_map(map) do 
    map |> Poison.encode! |> b64 
    end 

    defp b64(str) when is_binary(str) do 
    Base.url_encode64(str, padding: false) 
    end 

end 

IO.inspect (private_key):

{:RSAPrivateKey, :"two-prime", 
26481417694003873198106692499951294632119767655743036419434387596516366789190701823748669795645320777784137996798720069366288226752787622864701474496474449030506709232606243234272615772772466937031758607350665927756585455359455675325206612466347661342624412526201816026642296038870194629664917766048486662184822018742110266572261560976195129025393833146676682160704214817952205520453818572377683628606127111066471430372867661099887369197771195456883038219184710367619732291239260771178775267372942936652670907351820071078279876378927060202383261106965701867067167942374432028957977689700100770593457365162852102994011, 
65537, 
17914363694762679375590280482557038734074338145129736174308002717419978357245064091366667308389692794651262006012958394118656461740464764327121166238936702897104154200338706284869255844574321706109571964796859390986591027409882468918977602937203771390592387954119924829351148128283413627511087311865963595647490630788471521560987974810414561435248783963374268078499217692971351713183762668005601250077516937260913883929834502151959055904643039470485089018275006363270281504396441774935380614604745759736941304083977023940167676210942357786129557579261694171244151039301867300063202512362347353203092947886172660735393, 
178446771914665404540695905367251634656603255428643793397732858767097609718259368256180025741118899743098924191892492358642536804962239144370164933768905841306132489144152437556760519068703335707439676521498046102518700677420206003309978859591990308609070226460982935297571405985650480509898548679141561783409, 
148399533428755367732844203564110326749419930547476575029427037695010307782491560655098073907520278149390027076214510851700665327903331461330257316301355625227675837876554040085530270141360998128496771695290961076657330075330485591211033119775343431677271581646470921917040927840058534430663755569847957098379, 
173496648605071408699339341045453818586204782529834351152938645769270680587115197307101867039967578203618114203933621017140604584820619131790019979779680353116338191796637764448772807948772568899131006122851732603054596464051422956877924576259853677682245842193987696327661510566545050393063851309736807837969, 
104457312306054806733354226690510299270297554298879135185963633915322955098861989175280059316535971303378417368095146254784372068320316518037537578135981756067227887713555921436525884491068010508044075485229218997318755721273030971941897994237703401844823768755563271113340785238716148920776808645385905807487, 
167919839448914714974178630755108847455535988232500360818424531493548836346962617553207612824957810666270161293456074716336654588650394703385074422991192683242596666041121521405849960615014764544853974028554205453198599086267359147206158727144128096959265897638538959277458154234233457521650291895863656575525, 
:asn1_NOVALUE} 

IO.inspect Poison.encode (requête):

"{\"signature\":\"bzWgP-iSDaFG1tl0nbm4jfWEeQbwpfPEGqKdyslskweSpZCMXdgP7NPCAYlbX8W5qExPA9wGtI0uR2tfRA-ALE6prvRxAwzh3BfwPNscwgXzTNUy79KLkW78eFMLrUvU8shtkwxXlmmPCxGd2PAMM5vXUHM_ovVhTHKqojdy5ECzpw6u03k2wJZzLIn68o-G4ZuOnThl2HzDky29CCYSZnkDk3uE2L5rt1fyqG2II6DhKYKlXB8fittUSJk4xDr7ufu4kKOlMqXB2JyfR6kpEVigqUsjSzAWCzdP3WXgk-M8A2ElqGuwzXgXiXiOMD04SIOCSxfe1Qu6KFeQBeEgPw\",\"protected\":\"eyJub25jZSI6IkVfUVZLVjlNVklRT29odjRnbG51VDEyem1NNE5sb0tBRUZzUFl6WWJuUXMiLCJqd2siOnsibiI6Ik1qWTBPREUwTVRjMk9UUXdNRE00TnpNeE9UZ3hNRFkyT1RJME9UazVOVEV5T1RRMk16SXhNVGszTmpjMk5UVTNORE13TXpZME1UazBNelF6T0RjMU9UWTFNVFl6TmpZM09Ea3hPVEEzTURFNE1qTTNORGcyTmprM09UVTJORFV6TWpBM056YzNPRFF4TXpjNU9UWTNPVGczTWpBd05qa3pOall5T0RneU1qWTNOVEkzT0RjMk1qSTROalEzTURFME56UTBPVFkwTnpRME5Ea3dNekExTURZM01Ea3lNekkyTURZeU5ETXlNelF5TnpJMk1UVTNOekkzTnpJME5qWTVNemN3TXpFM05UZzJNRGN6TlRBMk5qVTVNamMzTlRZMU9EVTBOVFV6TlRrME5UVTJOelV6TWpVeU1EWTJNVEkwTmpZek5EYzJOakV6TkRJMk1qUTBNVEkxTWpZeU1ERTRNVFl3TWpZMk5ESXlPVFl3TXpnNE56QXhPVFEyTWprMk5qUTVNVGMzTmpZd05EZzBPRFkyTmpJeE9EUTRNakl3TVRnM05ESXhNVEF5TmpZMU56SXlOakUxTmpBNU56WXhPVFV4TWprd01qVXpPVE00TXpNeE5EWTJOelkyT0RJeE5qQTNNRFF5TVRRNE1UYzVOVEl5TURVMU1qQTBOVE00TVRnMU56SXpOemMyT0RNMk1qZzJNRFl4TWpjeE1URXdOalkwTnpFME16QXpOekk0TmpjMk5qRXdPVGs0T0Rjek5qa3hPVGMzTnpFeE9UVTBOVFk0T0RNd016Z3lNVGt4T0RRM01UQXpOamMyTVRrM016SXlPVEV5TXpreU5qQTNOekV4TnpnM056VXlOamN6TnpJNU5ESTVNelkyTlRJMk56QTVNRGN6TlRFNE1qQXdOekV3TnpneU56azROell6TnpnNU1qY3dOakF5TURJek9ETXlOakV4TURZNU5qVTNNREU0Tmpjd05qY3hOamM1TkRJek56UTBNekl3TWpnNU5UYzVOemMyT0RrM01EQXhNREEzTnpBMU9UTTBOVGN6TmpVeE5qSTROVEl4TURJNU9UUXdNVEUiLCJrdHkiOiJSU0EiLCJlIjoiTmpVMU16YyJ9LCJhbGciOiJSUzI1NiJ9\",\"payload\":\"eyJyZXNvdXJjZSI6Im5ldy1yZWciLCJjb250YWN0IjpbIm1haWx0bzpzb21lQGR1ZGUuY29tIl19\",\"header\":{\"jwk\":{\"n\":\"MjY0ODE0MTc2OTQwMDM4NzMxOTgxMDY2OTI0OTk5NTEyOTQ2MzIxMTk3Njc2NTU3NDMwMzY0MTk0MzQzODc1OTY1MTYzNjY3ODkxOTA3MDE4MjM3NDg2Njk3OTU2NDUzMjA3Nzc3ODQxMzc5OTY3OTg3MjAwNjkzNjYyODgyMjY3NTI3ODc2MjI4NjQ3MDE0NzQ0OTY0NzQ0NDkwMzA1MDY3MDkyMzI2MDYyNDMyMzQyNzI2MTU3NzI3NzI0NjY5MzcwMzE3NTg2MDczNTA2NjU5Mjc3NTY1ODU0NTUzNTk0NTU2NzUzMjUyMDY2MTI0NjYzNDc2NjEzNDI2MjQ0MTI1MjYyMDE4MTYwMjY2NDIyOTYwMzg4NzAxOTQ2Mjk2NjQ5MTc3NjYwNDg0ODY2NjIxODQ4MjIwMTg3NDIxMTAyNjY1NzIyNjE1NjA5NzYxOTUxMjkwMjUzOTM4MzMxNDY2NzY2ODIxNjA3MDQyMTQ4MTc5NTIyMDU1MjA0NTM4MTg1NzIzNzc2ODM2Mjg2MDYxMjcxMTEwNjY0NzE0MzAzNzI4Njc2NjEwOTk4ODczNjkxOTc3NzExOTU0NTY4ODMwMzgyMTkxODQ3MTAzNjc2MTk3MzIyOTEyMzkyNjA3NzExNzg3NzUyNjczNzI5NDI5MzY2NTI2NzA5MDczNTE4MjAwNzEwNzgyNzk4NzYzNzg5MjcwNjAyMDIzODMyNjExMDY5NjU3MDE4NjcwNjcxNjc5NDIzNzQ0MzIwMjg5NTc5Nzc2ODk3MDAxMDA3NzA1OTM0NTczNjUxNjI4NTIxMDI5OTQwMTE\",\"kty\":\"RSA\",\"e\":\"NjU1Mzc\"},\"alg\":\"RS256\"}}" 

IO.inspect (réponse):

{:ok, 
%HTTPoison.Response{body: "{\n \"type\": \"urn:acme:error:malformed\",\n \"detail\": \"Key too large: 4934 \\u003e 4096\",\n \"status\": 400\n}", 
    headers: [{"Server", "nginx"}, {"Content-Type", "application/problem+json"}, 
    {"Content-Length", "104"}, 
    {"Boulder-Request-Id", "5BbL5f23yYxol0_rHyC7OT88PF5BJle7lY970szFsqg"}, 
    {"Replay-Nonce", "DFPac8kWo7OoL5LSHUI6CZr5nHjZzyeA64eXQdcniVg"}, 
    {"Expires", "Sat, 04 Feb 2017 05:12:57 GMT"}, 
    {"Cache-Control", "max-age=0, no-cache, no-store"}, {"Pragma", "no-cache"}, 
    {"Date", "Sat, 04 Feb 2017 05:12:57 GMT"}, {"Connection", "close"}], 
    status_code: 400}} 
+0

Je sais que je suis annonce des détails sur ma clé privée. Ce n'est pas une clé de développement que je peux facilement remplacer, je m'en fous si ça devient public. – eltiare

+1

Je n'ai pas complètement lu le code mais cette ligne ne fera rien: 'Map.put (requête,: signature, signature)'. Vous devez faire 'request = Map.put (request,: signature, signature)'. – Dogbert

+0

Haha. Oops. Je suis encore trop habitué aux langages OO. Je vais essayer. – eltiare

Répondre

1

Vous convertissez les entiers dans RSAPrivateKey en binaire en utilisant String.to_integer, ce qui crée une représentation ASCII des chiffres en base 10. Vous devez convertir chaque octet du nombre en binaire avec le nombre total d'octets approprié.

Une façon de le faire est de spécifier un size en utilisant la syntaxe <<>>:

iex(1)> n = 0x12345678 
305419896 
iex(2)> <<n::size(32)>> # or just <<n::32>> 
<<18, 52, 86, 120>> 
+0

Comment est-ce qu'on peut déterminer le bon nombre d'octets? – eltiare

+0

Nevermind, compris. C'est la taille de la clé. Dans ce cas, c'est 2048. – eltiare

+0

Oui, 2048 bits, donc 'module = << elem (tuple, 2) :: 2048 >> |> b64'. – Dogbert