From 26f4182c1828aa6c213fb73d0d501ca76ad5b377 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 13:33:47 -0400 Subject: [PATCH 01/95] adds config to %eyre state, %rule gift to update, %born includes host/ips --- sys/vane/eyre.hoon | 55 +++++++++++++++++++++++++++++++++++++++++++--- sys/vane/gall.hoon | 1 + sys/zuse.hoon | 17 +++++++++++--- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/sys/vane/eyre.hoon b/sys/vane/eyre.hoon index 0f201ea17..0e3d8b13f 100644 --- a/sys/vane/eyre.hoon +++ b/sys/vane/eyre.hoon @@ -86,6 +86,9 @@ |% :: models ++ bolo :: eyre state $: $0 :: version + dom/(set (list @t)) :: domain names + fig/http-config :: config + por/{clr/@ud sek/(unit @ud)} :: live ports gub/@t :: random identity hov/(unit ship) :: master for remote top/beam :: ford serve prefix @@ -637,12 +640,50 @@ =. p.top our :: XX necessary? ?- -.kyz $born + :: XX capture IPs too + =/ mod/(set (list @t)) + %- ~(gas in *(set (list @t))) + %+ turn + (skim p.kyz |=(a=host ?=(%& -.a))) + |=(a=host ?>(?=(%& -.a) p.a)) + =/ dif/(set (list @t)) (~(dif in mod) dom) + =? dom ?=(^ dif) (~(uni in dom) mod) + ~& [%eyre %acme-order dom] + :: =? mow ?=(^ dif) + :: =/ cmd [%acme %poke `cage`[%acme-order !>(dom)]] + :: [[hen %pass ~ %g %deal [our our] cmd] mow] %= +>.$ ged hen :: register external - mow :_(mow [hen [%give %form [~ ?=(%king our) & &]]]) + mow :_(mow [hen [%give %form fig]]) == :: - $live +>.$ :: XX save ports + $live + +>.$(clr.por p.kyz, sek.por q.kyz) + :: + $rule + ?- -.p.kyz + $cert + ?: =(secure.fig p.p.kyz) +>.$ + %= +>.$ + secure.fig p.p.kyz + mow :_(mow [hen [%give %form fig]]) + == + :: + $turf + =/ mod/(set (list @t)) + ?: ?=(%put p.p.kyz) + (~(put in dom) q.p.kyz) + (~(del in dom) q.p.kyz) + ?: =(dom mod) +>.$ + ~& [%eyre %acme-order dom] + :: =. mow + :: =/ cmd [%acme %poke `cage`[%acme-order !>(dom)]] + :: [[hen %pass ~ %g %deal [our our] cmd] mow] + %= +>.$ + dom mod + mow :_(mow [hen [%give %form fig]]) + == + == :: $serv =< ~&([%serving (en-beam top)] .) @@ -653,6 +694,7 @@ :: $init :: register ownership =. our ?~(hov p.kyz (min u.hov p.kyz)) + =. fig [~ ?=(%king our) & &] +>.$(hov [~ our], top [[our %home ud+0] /web]) :: ?($chis $this) :: inbound request @@ -2124,7 +2166,14 @@ ?+ p.lot [~ ~] {$tas $fake} ``[& [~ 8.443] %& /localhost] :: XX from unix {$tas $real} - ``~(our-host ye [`duct`~[/] [now eny our sky] ~] bol) + =/ hot=host [%& ?^(dom n.dom /localhost)] + =/ sek=? &(?=(^ sek.por) !?=(hoke hot)) + =/ por=(unit @ud) + ?. sek + ?:(=(80 clr.por) ~ `clr.por) + ?> ?=(^ sek.por) + ?:(=(443 u.sek.por) ~ sek.por) + ``[sek por hot] == == :: diff --git a/sys/vane/gall.hoon b/sys/vane/gall.hoon index 7df29af95..5f70ed0fb 100644 --- a/sys/vane/gall.hoon +++ b/sys/vane/gall.hoon @@ -1222,6 +1222,7 @@ $nuke `%a $ogre `%c $perm `%c + $rule `%e $serv `%e $tend `%a $them `%e diff --git a/sys/zuse.hoon b/sys/zuse.hoon index 58e61ab73..82feec619 100644 --- a/sys/zuse.hoon +++ b/sys/zuse.hoon @@ -677,11 +677,12 @@ [%velo p=@t q=@t] :: drop-through == :: += task :: in request ->$ - $% [%born ~] :: new unix process + $% [%born p=(list host)] :: new unix process [%crud p=@tas q=(list tank)] :: XX rethink [%hiss p=(unit user) q=mark r=cage] :: outbound user req [%init p=@p] :: report install [%live p=@ud q=(unit @ud)] :: http/s ports + [%rule p=http-rule] :: update config [%serv p=$@(desk beam)] :: set serving root [%them p=(unit hiss)] :: outbound request [%they p=@ud q=httr] :: inbound response @@ -743,9 +744,9 @@ :: +http-config: full http-server configuration :: += http-config - $: :: secure: PEM-encoded RSA private key and certificate chain + $: :: secure: PEM-encoded RSA private key and cert or cert chain :: - secure=(unit [key=wain certificate=wain]) + secure=(unit [key=wain cert=wain]) :: proxy: reverse TCP proxy HTTP(s) :: proxy=? @@ -758,6 +759,16 @@ :: redirect=? == + :: +http-rule: update configuration + :: + += http-rule + $% :: %cert: set or clear certificate and keypair + :: + [%cert p=(unit [key=wain cert=wain])] + :: %turf: add or remove established dns binding + :: + [%turf p=?(%put %del) q=(list @t)] + == ++ httq :: raw http request $: p/meth :: method q/@t :: unparsed url From d358548223271ee4e686bd07f40296a6b35adc9f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 14 May 2018 23:48:29 -0400 Subject: [PATCH 02/95] implements .well-known in %eyre --- sys/vane/eyre.hoon | 31 +++++++++++++++++++++++++++++++ sys/vane/gall.hoon | 1 + sys/zuse.hoon | 1 + 3 files changed, 33 insertions(+) diff --git a/sys/vane/eyre.hoon b/sys/vane/eyre.hoon index 0e3d8b13f..867a46337 100644 --- a/sys/vane/eyre.hoon +++ b/sys/vane/eyre.hoon @@ -89,6 +89,7 @@ dom/(set (list @t)) :: domain names fig/http-config :: config por/{clr/@ud sek/(unit @ud)} :: live ports + wel/wank :: .well-known gub/@t :: random identity hov/(unit ship) :: master for remote top/beam :: ford serve prefix @@ -176,6 +177,9 @@ {$html p/manx} :: successful page {$htme p/manx} :: authentication fail == +:: +++ wank :: .well-known ankh + {p/(unit mime) q/(map @ta wank)} -- :: |% ++ eat-headers @@ -225,6 +229,25 @@ ^- wall (zing (turn tan |=(a/tank (wash 0^wid a)))) :: +++ yank :: get .well-known + |= [wel=wank pat=path] + ^- (unit mime) + ?~ pat p.wel + =/ wan (~(get by q.wel) i.pat) + ?~ wan ~ + $(wel u.wan, pat t.pat) +:: +++ dank :: put/del .well-known + |= [wel=wank pat=path mim=(unit mime)] + ^- wank + ?~ pat wel(p mim) + =/ wan (~(get by q.wel) i.pat) + ?: &(?=(~ wan) ?=(~ mim)) + wel + :- p.wel + %+ ~(put by q.wel) + i.pat + $(wel ?~(wan *wank u.wan), pat t.pat) :: ++ add-cookies |= {cug/(list @t) hit/httr} ^- httr @@ -781,6 +804,9 @@ ?~ p.lid +>.^$ (del-deps:$(p.lid t.p.lid) i.p.lid %& hen) == + :: + $well + +>.$(wel (dank wel p.kyz q.kyz)) :: $went :: this won't happen until we send responses. @@ -1270,6 +1296,11 @@ :~ 'User-agent: *' 'Disallow: ' == + :: + {@tas $'.well-known' ^} :: XX file extension? + =/ mim (yank wel (tail q.pok)) + ?~ mim ~ + `(resp 200 p.u.mim q.q.u.mim) == :: ++ is-spur |(?~(q.pok & ((sane %ta) i.q.pok))) diff --git a/sys/vane/gall.hoon b/sys/vane/gall.hoon index 5f70ed0fb..9bf2e86df 100644 --- a/sys/vane/gall.hoon +++ b/sys/vane/gall.hoon @@ -1229,6 +1229,7 @@ $wait `%b $want `%a $warp `%c + $well `%e $wipe `%f :: XX cache clear == -- diff --git a/sys/zuse.hoon b/sys/zuse.hoon index 82feec619..6bea60e09 100644 --- a/sys/zuse.hoon +++ b/sys/zuse.hoon @@ -690,6 +690,7 @@ [%this p=? q=clip r=httq] :: inbound request [%thud ~] :: inbound cancel [%wegh ~] :: report memory + [%well p=path q=(unit mime)] :: put/del .well-known [%went p=sack q=path r=@ud s=coop] :: response confirm [%west p=sack q=[path *]] :: network request [%wise p=@p q=@ud r=?] :: proxy notification From 2f6fc2493d65a8ce132e4903db379f2a306d2ffe Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 13:40:33 -0400 Subject: [PATCH 03/95] updates %eyre state adaptation in +load --- sys/vane/eyre.hoon | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/vane/eyre.hoon b/sys/vane/eyre.hoon index 867a46337..a37fc76c2 100644 --- a/sys/vane/eyre.hoon +++ b/sys/vane/eyre.hoon @@ -85,7 +85,7 @@ -- :: |% :: models ++ bolo :: eyre state - $: $0 :: version + $: $1 :: version dom/(set (list @t)) :: domain names fig/http-config :: config por/{clr/@ud sek/(unit @ud)} :: live ports @@ -2166,10 +2166,14 @@ ~ :: ++ load :: take previous state - ::|= * %. (bolo +<) - |= old/?(bolo) ^+ ..^$ + => |% + ++ bolo-old (cork bolo |=(bolo [%0 |5.+<])) + -- + |= old/?(bolo-old bolo) + ^+ ..^$ ?- -.old - $0 ..^$(+>- old) + $0 $(old [%1 ~ *http-config [8.080 ~] [~ ~] +.old]) + $1 ..^$(+>- old) == :: ++ scry From 3a6e8c6f7b34024b0c65d0b9ce4ee2e29d0a434d Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 19 Apr 2018 02:27:55 -0400 Subject: [PATCH 04/95] adds :acme work-in-progress demo app :acme %test (base64 json variation failures atm) :acme %init (new account fails due to jws parse or rsa prime issues) --- app/acme.hoon | 512 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 512 insertions(+) create mode 100644 app/acme.hoon diff --git a/app/acme.hoon b/app/acme.hoon new file mode 100644 index 000000000..211c874a6 --- /dev/null +++ b/app/acme.hoon @@ -0,0 +1,512 @@ +/+ tester +=, tester:tester +=, purl:eyre +:: +:::: libraries +:: +|% +++ rsa :: unpadded! + |% + += key [p=@ux q=@ux n=@ux e=@ux d=@ux] + ++ elcm + |= [a=@ b=@] + (div (mul a b) d:(egcd a b)) + :: + ++ new-key + |= [wid=@ eny=@] + ^- key + =/ diw (rsh 0 1 wid) + =/ p=@ux (ramp:number diw [3 5 ~] eny) + =/ q=@ux (ramp:number diw [3 5 ~] +(eny)) + =/ n=@ux (mul p q) + =/ e `@ux`65.537 + =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) + [p q n e d] + :: + ++ en + |= [m=@ k=key] + ~| %rsa-len + ?> (lte (met 0 m) (met 0 n.k)) + (~(exp fo n.k) e.k m) + :: + ++ de + |= [m=@ k=key] + :: XX assert rsa-len here too? + =/ fu (fu:number p.k q.k) + (out.fu (exp.fu d.k (sit.fu m))) + -- +:: +++ rs256 + |_ k=key:rsa + ++ sign |=(m=@ (de:rsa (shax m) k)) + ++ verify + |= [s=@ m=@] + =((shax m) (en:rsa s k)) + -- +:: +++ en-json-sort :: print json + |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) + :: :: ++apex:en-json:html + ++ apex + =, en-json:html + |= {val/json sor/$-(^ ?) rez/tape} + ^- tape + ?~ val (weld "null" rez) + ?- -.val + $a + :- '[' + =. rez [']' rez] + !. + ?~ p.val rez + |- + ?~ t.p.val ^$(val i.p.val) + ^$(val i.p.val, rez [',' $(p.val t.p.val)]) + :: + $b (weld ?:(p.val "true" "false") rez) + $n (weld (trip p.val) rez) + $s + :- '"' + =. rez ['"' rez] + =+ viz=(trip p.val) + !. + |- ^- tape + ?~ viz rez + =+ hed=(jesc i.viz) + ?: ?=({@ $~} hed) + [i.hed $(viz t.viz)] + (weld hed $(viz t.viz)) + :: + $o + :- '{' + =. rez ['}' rez] + =/ viz + %+ sort ~(tap by p.val) + |=((pair) (sor (head p) (head q))) + ?~ viz rez + !. + |- ^+ rez + ?~ t.viz ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)]) + =. rez [',' $(viz t.viz)] + ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)]) + == + -- +:: +++ en-base64url :: rfc4648 section-5 + |= tig=@ :: padding omitted + ^- tape :: per rfc7515 + =/ poc (~(dif fo 3) 0 (met 3 tig)) + =/ pad (lsh 3 poc (swp 3 tig)) + =/ cha 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' + %- flop + %+ slag poc + |- ^- tape + ?~ pad ~ + =/ d (end 3 3 pad) + :* (cut 3 [(cut 0 [0 6] d) 1] cha) + (cut 3 [(cut 0 [6 6] d) 1] cha) + (cut 3 [(cut 0 [12 6] d) 1] cha) + (cut 3 [(cut 0 [18 6] d) 1] cha) + $(pad (rsh 3 3 pad)) + == +:: +++ de-base64url + =- |=(a/cord (rash a fel)) + =< fel=(cook |~(a/@ `@t`(swp 3 a)) (bass 64 .)) + =- (cook welp ;~(plug (plus siw) (stun 0^2 (cold %0 tis)))) + ^= siw + ;~ pose + (cook |=(a/@ (sub a 'A')) (shim 'A' 'Z')) + (cook |=(a/@ (sub a 'G')) (shim 'a' 'z')) + (cook |=(a/@ (add a 4)) (shim '0' '9')) + (cold 62 (just '-')) + (cold 63 (just '_')) + == +:: +++ jwk + |_ k=key:rsa + ++ pass + ^- json + :- %o %- my :~ + kty+s+'RSA' + n+s+(crip (en-base64url n.k)) + e+s+(crip (en-base64url e.k)) + == + ++ ring !! + -- +++ thumbprint + |= jon=json + :: XX restrict keys to canonical set + (en-base64url (shax `@`(crip `tape`(en-json-sort aor jon)))) +:: +++ from-json + =, dejs:format + =/ json-purl (su auri:de-purl:html) + %- ot + :~ ['newAccount' json-purl] + ['newNonce' json-purl] + ['newOrder' json-purl] + ['revokeCert' json-purl] + ['keyChange' json-purl] + == +-- +:: +:::: acme state +:: +|% ++= move [bone card] ++= card $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] + == +:: ++= nonce @t +:: ++= directory :: ACME v2 + $: reg/purl :: newAccount + non/purl :: newNonce + der/purl :: newOrder + rev/purl :: revokeCert + rek/purl :: keyChange + == +:: ++= state + $: dir=directory + non=nonce + kid=(unit @t) + key=(unit key:rsa) + == +-- +:: +:::: acme app +:: +=/ url=tape "https://acme-staging-v02.api.letsencrypt.org/directory" +=/ bas=purl (scan url auri:de-purl:html) +=| mov=(list move) +|_ [bow=bowl:gall state] +:: +++ this . :: XX #712 +:: +++ emit + |= car=card + this(mov [[ost.bow car] mov]) +:: +++ abet + [(flop mov) this(mov ~)] +:: +++ jws-body + |= [url=purl bod=json] + ^- octs + =* enc (corl en-base64url (corl crip (cury en-json-sort aor))) + =/ payload=tape (enc bod) + =/ protect=tape + %- enc + :- %o %- my :~ + alg+s+'RS256' + nonce+s+non + url+s+(crip (en-purl:html url)) + ?^ kid + kid+s+u.kid + ?> ?=(^ key) + jwk+~(pass jwk u.key) + == + %- (corl as-octt:mimes:html en-json:html) + ^- json + :- %o %- my :~ + protected+s+(crip protect) + payload+s+(crip payload) + :+ %signature %s + %- crip %- en-base64url + ?> ?=(^ key) + %- ~(sign rs256 u.key) + (crip :(welp protect "." payload)) + == +:: +++ request + |= [wir=wire url=purl bod=(unit json)] + =/ lod + ?~ bod + [%get ~ ~] + =/ hed (my content-type+['application/jose+json' ~] ~) + [%post hed `(jws-body url u.bod)] + (emit [%hiss wir [~ ~] %httr %hiss url lod]) +:: +++ initialize + =? key ?=(~ key) `(new-key:rsa 2.048 eny.bow) + (request /acme/init/(scot %p our.bow) bas ~) +:: +++ nonce + (request /acme/non/(scot %p our.bow) non.dir ~) +:: +++ register + %^ request /acme/reg/(scot %p our.bow) + reg.dir + `[%o (my [['termsOfServiceAgreed' b+&] ~])] +:: +++ authorize + :+ request + der.dir ::aut.dir + ^- json + :- %o %- my :~ + resource+s+'new-authz' + :- %identifier + :- %o %- my :~ + type+s+'dns' + value+s+(crip (welp +:(scow %p our.bow) ".urbit.org")) + == + == +:: +++ poke-noun + |= a=* + ^- (quip move _this) + ?+ a ~& +<+.this + [~ this] + %init abet:initialize + %test test + == +:: +++ sigh-httr + |= [wir=wire rep=httr:eyre] + ^- (quip move _this) + ~& [wir rep] + ?> ?=([%acme ^] wir) + ?. ?=(%2 (div p.rep 100)) + ~& %lack-of-success + [~ +>] + ?+ i.t.wir !! + %init + =< abet:nonce + this(dir (from-json (need (de-json:html q:(need r.rep))))) + :: + %non + =< abet:register + this(non q:(head (skim q.rep |=((pair @t @t) ?=(%replay-nonce p))))) + == +:: +++ prep _[~ this] +:: +++ test + =/ eny eny.bow + :: non-deterministic for now + :: 0vhu.gp79o.hi7at.smp8u.g5hhr.u3rff.st8ms.q4dc2.hv5ls.tp5cp.10qds. + :: h9bpt.vlmm7.lh375.f6u9n.krqv8.5jcml.cujkr.v1uqv.cjhe5.nplta + |^ =/ out=wall + ;: weld + testen-base64url + testrsakey + testrsa + testjwkthumbprint + testjws + == + ?~ out abet + ((slog (turn `wall`out |=(a=tape leaf+a))) abet) + :: + ++ testen-base64url + =/ jon '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' + ;: weld + %- expect-eq !> + :- "AQAB" + (en-base64url 65.537) + %- expect-eq !> + ~& (en-base64:mimes:html jon) + :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + (en-base64url jon) + == + :: + ++ testrsakey + =/ primes=(list @) + :~ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 + 47 53 59 61 67 71 73 79 83 89 97 101 103 107 + 109 113 127 131 137 139 149 151 157 163 167 173 179 181 + 191 193 197 199 211 223 227 229 233 239 241 251 257 263 + 269 271 277 281 283 293 307 311 313 317 331 337 347 349 + 353 359 367 373 379 383 389 397 401 409 419 421 431 433 + 439 443 449 457 461 463 467 479 487 491 499 503 509 521 + 523 541 547 557 563 569 571 577 587 593 599 601 607 613 + 617 619 631 641 643 647 653 659 661 673 677 683 691 701 + 709 719 727 733 739 743 751 + == + =/ k1 (new-key:rsa 2.048 eny) + :: + =/ k2 + =/ p 0x1837.be57.1286.bf6a.3cf8.4716.634f.ef85.f947.c654.da6e.e222. + 5654.9466.0ab0.a2ef.1985.1095.e3c3.9e74.9478.e3f3.ee92.f885.ec3c. + 84c3.6b3c.9731.65f9.9d1d.f743.646f.37d7.82d8.3f4a.856c.6453.b2c8. + 28d5.d720.145e.c7ab.4ba9.a9c2.6b8e.8819.7aa8.69b3.420f.dbfa.1ddb. + 4d1a.9c2e.e25a.d4de.d351.945f.d7ca.74a4.815d.5f0e.9f44.df64.39bd + =/ q 0xf1bc.ec8f.d238.32d9.afb8.8083.76b3.82da.6274.f56e.1b5b.662b. + ab1b.1e01.fbd5.86c5.ba98.b246.b621.f190.2425.25ea.b39f.efa2.4fb8. + 0d6b.c3c4.460d.e7df.d2f5.6604.51e0.415b.db60.db5a.6601.16c7.46ec. + 5e67.9195.f3c9.80d3.47c5.fe24.fbfd.43c3.380a.40bd.c4f5.d65e.b93b. + 60ca.5f26.4ed7.9c64.d26d.b0fe.985d.7be3.1308.34dd.b8c5.4d7c.d8a5 + =/ n (mul p q) + =/ e 0x1.0001 + =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) + (key:rsa [p q n e d]) + :: + |^ ^- wall + ;: weld + (check-primes k1) + (check-primes k2) + == + ++ check-primes + =, number + |= k=key:rsa + %+ roll primes + |= [p=@ a=wall] + ?^ a a + ?: =(0 (mod n.k p)) + :~ "n.key (prime? {(scow %f (pram n.k))}) divisible by {(scow %ud p)}:" + "{(scow %ux n.k)}" + == + ?: =(0 (mod p.k p)) + :~ "p.key (prime? {(scow %f (pram p.k))}) divisible by {(scow %ud p)}:" + "{(scow %ux p.k)}" + == + ?: =(0 (mod q.k p)) + :~ "q.key (prime? {(scow %f (pram q.k))}) divisible by {(scow %ud p)}:" + "{(scow %ux q.k)}" + == + ~ + -- + :: + ++ testrsa + =/ k1 + =/ p 61 + =/ q 53 + =/ e 17 + =/ n (mul p q) + =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) + (key:rsa [p q n e d]) + :: + =/ k2 (key:rsa [11 13 143 7 103]) + :: + =/ k3 + =/ p + 12.131.072.439.211.271.897.323.671.531.612.440.428.472.427.633.701.410. + 925.634.549.312.301.964.373.042.085.619.324.197.365.322.416.866.541. + 017.057.361.365.214.171.711.713.797.974.299.334.871.062.829.803.541 + =/ q + 12.027.524.255.478.748.885.956.220.793.734.512.128.733.387.803.682.075. + 433.653.899.983.955.179.850.988.797.899.869.146.900.809.131.611.153. + 346.817.050.832.096.022.160.146.366.346.391.812.470.987.105.415.233 + =/ n (mul p q) + =/ e 65.537 + =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) + (key:rsa [p q n e d]) + =/ m3 (swp 3 'attack at dawn') + =/ c3 + 35.052.111.338.673.026.690.212.423.937.053.328.511.880.760.811.579.981. + 620.642.802.346.685.810.623.109.850.235.943.049.080.973.386.241.113. + 784.040.794.704.193.978.215.378.499.765.413.083.646.438.784.740.952. + 306.932.534.945.195.080.183.861.574.225.226.218.879.827.232.453.912. + 820.596.886.440.377.536.082.465.681.750.074.417.459.151.485.407.445. + 862.511.023.472.235.560.823.053.497.791.518.928.820.272.257.787.786 + :: + ;: weld + %- expect-eq !> + [413 d.k1] + %- expect-eq !> + [2.790 (en:rsa 65 k1)] + %- expect-eq !> + [65 (de:rsa 2.790 k1)] + :: + %- expect-eq !> + [48 (en:rsa 9 k2)] + %- expect-eq !> + [9 (de:rsa 48 k2)] + :: + %- expect-eq !> + [c3 (en:rsa m3 k3)] + %- expect-eq !> + [m3 (de:rsa c3 k3)] + == + -- + :: + ++ testjwkthumbprint + =/ n=(list @t) + :~ '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2' + 'aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCi' + 'FV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65Y' + 'GjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n' + '91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_x' + 'BniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw' + == + =/ k=json + :- %o %- my :~ + e+s+'AQAB' + kty+s+'RSA' + n+s+(reel n (cury cat 3)) + == + :: + %- expect-eq !> + :- "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" + (thumbprint k) + ++ testjws + ^- wall + =/ pt=@t + %+ reel + ^- (list @t) + :~ '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi' + 'YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG' + 'BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc' + == + (cury cat 3) + =/ qt=@t + %+ reel + ^- (list @t) + :~ 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa' + 'ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA' + '-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc' + == + (cury cat 3) + =/ nt=@t + %+ reel + ^- (list @t) + :~ 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx' + 'HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs' + 'D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH' + 'SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV' + 'MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8' + 'NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ' + == + (cury cat 3) + =/ dt=@t + %+ reel + ^- (list @t) + :~ 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I' + 'jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0' + 'BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn' + '439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT' + 'CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh' + 'BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ' + == + (cury cat 3) + =/ p (de-base64url pt) + =/ q (de-base64url qt) + =/ n (de-base64url nt) + =/ d (de-base64url dt) + =/ e 65.537 + =/ k (key:rsa [p q n e d]) + =/ hed=json o+(my alg+s+'RS256' ~) + =/ lod=json + :- %o %- my :~ + iss+s+'joe' + exp+n+'1300819380' + ['http://example.com/is_root' %b &] + == + =/ lod-order + =/ keys=(list @t) ['iss' 'exp' 'http://example.com/is_root' ~] + |= [a=* b=*] + =/ fa (find ~[a] keys) + =/ fb (find ~[b] keys) + ?~ fa | + ?~ fb | + (lte u.fa u.fb) + ;: weld + %- expect-eq !> + :- "eyJhbGciOiJSUzI1NiJ9" + (en-base64url (crip (en-json-sort aor hed))) + %- expect-eq !> + :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + (en-base64url (crip (en-json-sort lod-order lod))) + == +-- + From d0d9ac3bf3d4e392e03df8967dd2c05025ef0e48 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 11 May 2018 15:19:26 -0400 Subject: [PATCH 05/95] updates test-runner to print tangs --- app/acme.hoon | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 211c874a6..055f77bae 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -287,7 +287,7 @@ :: non-deterministic for now :: 0vhu.gp79o.hi7at.smp8u.g5hhr.u3rff.st8ms.q4dc2.hv5ls.tp5cp.10qds. :: h9bpt.vlmm7.lh375.f6u9n.krqv8.5jcml.cujkr.v1uqv.cjhe5.nplta - |^ =/ out=wall + |^ =/ out=tang ;: weld testen-base64url testrsakey @@ -295,8 +295,7 @@ testjwkthumbprint testjws == - ?~ out abet - ((slog (turn `wall`out |=(a=tape leaf+a))) abet) + ?~(out abet ((slog out) abet)) :: ++ testen-base64url =/ jon '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' @@ -341,7 +340,7 @@ =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) (key:rsa [p q n e d]) :: - |^ ^- wall + |^ ^- tang ;: weld (check-primes k1) (check-primes k2) @@ -350,19 +349,28 @@ =, number |= k=key:rsa %+ roll primes - |= [p=@ a=wall] + |= [p=@ a=tang] ?^ a a ?: =(0 (mod n.k p)) - :~ "n.key (prime? {(scow %f (pram n.k))}) divisible by {(scow %ud p)}:" - "{(scow %ux n.k)}" + :~ leaf+"{(scow %ux n.k)}" + :- %leaf + %+ weld + "n.key (prime? {(scow %f (pram n.k))})" + " divisible by {(scow %ud p)}:" == ?: =(0 (mod p.k p)) - :~ "p.key (prime? {(scow %f (pram p.k))}) divisible by {(scow %ud p)}:" - "{(scow %ux p.k)}" + :~ leaf+"{(scow %ux p.k)}" + :- %leaf + %+ weld + "p.key (prime? {(scow %f (pram p.k))})" + " divisible by {(scow %ud p)}:" == ?: =(0 (mod q.k p)) - :~ "q.key (prime? {(scow %f (pram q.k))}) divisible by {(scow %ud p)}:" - "{(scow %ux q.k)}" + :~ leaf+"{(scow %ux q.k)}" + :- %leaf + %+ weld + "q.key (prime? {(scow %f (pram q.k))})" + " divisible by {(scow %ud p)}:" == ~ -- From de7bd9c661f6b861f7d082a586de6b522ddffaf2 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 24 Apr 2018 01:49:21 -0400 Subject: [PATCH 06/95] better base64 --- app/acme.hoon | 222 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 150 insertions(+), 72 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 055f77bae..eae305fc1 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -91,12 +91,13 @@ == -- :: -++ en-base64url :: rfc4648 section-5 +++ en-base64url :: rfc4648 section-5 |= tig=@ :: padding omitted - ^- tape :: per rfc7515 + ^- cord :: per rfc7515 =/ poc (~(dif fo 3) 0 (met 3 tig)) =/ pad (lsh 3 poc (swp 3 tig)) =/ cha 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' + %- crip %- flop %+ slag poc |- ^- tape @@ -110,17 +111,24 @@ == :: ++ de-base64url - =- |=(a/cord (rash a fel)) - =< fel=(cook |~(a/@ `@t`(swp 3 a)) (bass 64 .)) - =- (cook welp ;~(plug (plus siw) (stun 0^2 (cold %0 tis)))) - ^= siw - ;~ pose - (cook |=(a/@ (sub a 'A')) (shim 'A' 'Z')) - (cook |=(a/@ (sub a 'G')) (shim 'a' 'z')) - (cook |=(a/@ (add a 4)) (shim '0' '9')) - (cold 62 (just '-')) - (cold 63 (just '_')) - == + |= a=cord + ^- @ + %+ rash a + %+ cook |~(a/@ (swp 3 a)) + %+ bass 64 + %+ cook welp + ;~ plug + %- plus + ;~ pose + (cook |=(a=@ (sub a 'A')) (shim 'A' 'Z')) + (cook |=(a=@ (sub a 'G')) (shim 'a' 'z')) + (cook |=(a=@ (add a 4)) (shim '0' '9')) + (cold 62 (just '-')) + (cold 63 (just '_')) + == + =/ b (~(dif fo 4) 0 (met 3 a)) + (cold (reap b %0) (easy ~)) + == :: ++ jwk |_ k=key:rsa @@ -128,8 +136,8 @@ ^- json :- %o %- my :~ kty+s+'RSA' - n+s+(crip (en-base64url n.k)) - e+s+(crip (en-base64url e.k)) + n+s+(en-base64url n.k) + e+s+(en-base64url e.k) == ++ ring !! -- @@ -186,6 +194,7 @@ :: ++ emit |= car=card + ~& [%emit car] this(mov [[ost.bow car] mov]) :: ++ abet @@ -195,8 +204,8 @@ |= [url=purl bod=json] ^- octs =* enc (corl en-base64url (corl crip (cury en-json-sort aor))) - =/ payload=tape (enc bod) - =/ protect=tape + =/ payload=cord (enc bod) + =/ protect=cord %- enc :- %o %- my :~ alg+s+'RS256' @@ -210,13 +219,13 @@ %- (corl as-octt:mimes:html en-json:html) ^- json :- %o %- my :~ - protected+s+(crip protect) - payload+s+(crip payload) + protected+s+protect + payload+s+payload :+ %signature %s - %- crip %- en-base64url + %- en-base64url ?> ?=(^ key) %- ~(sign rs256 u.key) - (crip :(welp protect "." payload)) + (rap 3 ~[protect '.' payload]) == :: ++ request @@ -289,10 +298,10 @@ :: h9bpt.vlmm7.lh375.f6u9n.krqv8.5jcml.cujkr.v1uqv.cjhe5.nplta |^ =/ out=tang ;: weld - testen-base64url - testrsakey - testrsa - testjwkthumbprint + :: testen-base64url + :: testrsakey + :: testrsa + :: testjwkthumbprint testjws == ?~(out abet ((slog out) abet)) @@ -303,10 +312,11 @@ %- expect-eq !> :- "AQAB" (en-base64url 65.537) - %- expect-eq !> - ~& (en-base64:mimes:html jon) - :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" - (en-base64url jon) + :: expected value includes newlines + :: %- expect-eq !> + :: ~& (en-base64:mimes:html jon) + :: :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + :: (en-base64url jon) == :: ++ testrsakey @@ -429,7 +439,7 @@ -- :: ++ testjwkthumbprint - =/ n=(list @t) + =/ n :~ '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2' 'aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCi' 'FV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65Y' @@ -441,56 +451,80 @@ :- %o %- my :~ e+s+'AQAB' kty+s+'RSA' - n+s+(reel n (cury cat 3)) + n+s+(rap 3 n) == :: %- expect-eq !> :- "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" (thumbprint k) + :: ++ testjws ^- wall =/ pt=@t - %+ reel - ^- (list @t) - :~ '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi' - 'YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG' - 'BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc' - == - (cury cat 3) + %+ rap 3 + :~ '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi' + 'YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG' + 'BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc' + == =/ qt=@t - %+ reel - ^- (list @t) - :~ 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa' - 'ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA' - '-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc' - == - (cury cat 3) + %+ rap 3 + :~ 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa' + 'ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA' + '-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc' + == =/ nt=@t - %+ reel - ^- (list @t) - :~ 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx' - 'HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs' - 'D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH' - 'SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV' - 'MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8' - 'NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ' - == - (cury cat 3) + %+ rap 3 + :~ 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx' + 'HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs' + 'D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH' + 'SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV' + 'MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8' + 'NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ' + == =/ dt=@t - %+ reel - ^- (list @t) - :~ 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I' - 'jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0' - 'BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn' - '439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT' - 'CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh' - 'BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ' - == - (cury cat 3) - =/ p (de-base64url pt) - =/ q (de-base64url qt) - =/ n (de-base64url nt) - =/ d (de-base64url dt) + %+ rap 3 + :~ 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I' + 'jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0' + 'BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn' + '439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT' + 'CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh' + 'BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ' + == + =/ p :: (de-base64url pt) + 0x4719.f070.d9b2.3fe7.d5a0.f842.57b6.e083.80c1.9484.ea75.faa7. + f286.556d.c1dd.11e7.5009.d5dc.22ef.6d8e.05c6.739a.dca0.2876.e6a2. + fb09.713c.f634.c9d4.254f.2e3f.3f7c.d001.d06b.13e4.2928.1a2a.3714. + f079.59b3.6c17.a82b.2676.54f7.b5c4.f92e.907e.1a31.b7dd.f078.0748. + fe1f.d1a9.a674.b772.b8a0.6dbb.a40a.4d46.545d.65a6.48eb.10c4.1ce0 + =/ q :: (de-base64url qt) + 0xd759.513f.1303.9270.e3da.f3ba.5e78.5e2a.0781.12d4.7512.b5e5. + d4e5.2f09.cdc3.595e.ed12.b1c8.5782.db78.fa40.704e.7e50.1ebf.979a. + 036c.ebad.ae0f.30f6.0f99.072d.de38.eda5.ab0b.fb78.60c5.bc7b.5256. + a72c.b68c.c001.1eb0.a7c5.9909.60fc.645a.a97a.a042.1bc6.297e.b4a6. + 927a.dcee.dfc7.e93a.5f5d.1499.c1f3.b12c.53f4.32b6.9509.7ec4.03b9 + =/ n :: (de-base64url nt) + :: (mul p q) + 0xa1e9.e5ca.5654.e021.9e6f.606f.4d03.073c.3639.9375.cf2e. + 0c59.84ad.67ab.fcd8.189a.d887.7f8f.7240.c317.9d8b.9a8d.35f8.0af5. + 1657.2c87.86b6.1f49.1922.39f2.ebd3.821b.641f.2a70.96a3.827a.6f6f. + 5c66.838b.6350.3031.55d7.9a6c.9ceb.3a78.a49a.6047.b6c6.10c1.64ed. + e844.f992.0375.c1a5.f85e.0f2c.2c85.055b.c7c4.de9a.cfb9.d49d.9774. + 485a.4ade.fa27.6dfe.e22c.34c8.38fb.bf8d.b301.f768.c6a0.ec8e.67a3. + bdd2.bd6e.df9b.6ebc.9603.134f.9462.bf55.0f2c.d380.42ea.4b59.6977. + 85e4.4f91.ec2f.2584.77b8.19d0.ed53.3f33.c13c.8969.4bdc.9a08.8f8a. + fbb0.56f9.2974.7ce6.1177.dd63.eab6.c597.34d9.8be3.36a1.90cc.2516. + fc77.24f0.e129.be7d.922b.3663.6265.2d8d.ce65.b4c9.e3e2.0a16.f8a1 + =/ d :: (de-base64url dt) + 0x9d73.8a3a.6e54.39e1.50a7.754f.41f4.3473.e768.7992.65c8. + 50f4.4792.5df2.bdc4.e181.18b8.9feb.9d4e.102e.a18b.a4fd.5064.d5f0. + 70dc.3d4e.e31f.ff25.656c.3c3c.e513.5468.058a.895d.563b.943b.d65b. + 2851.d022.5cfa.1a08.13d6.841e.de5e.2f64.539d.3b06.2534.1f47.46ff. + 558a.7246.07a8.f880.0beb.a961.498f.2c51.fa81.755e.fd0c.7df5.377e. + 92e3.ac92.cced.4a9b.3bc7.5db5.4134.714b.4df1.2564.5fde.9f4e.2d98. + 5605.a3e1.bba0.4045.95b2.d927.51a1.c644.06b4.5327.56ea.3bc6.6f21. + 797f.8b2e.abe3.5e02.a0ce.d5d8.255a.c1d8.ee13.521f.6797.377d.2fc8. + 280b.9b43.c6bf.03e5.88ec.bdd3.2c2f.cf3f.1e40.3c96.7ca5.0b9d.0f59. + 627b.7049.e964.1d75.611d.1f57.0045.6c52.7ec3.2b0a.cd69.a471.ae12 =/ e 65.537 =/ k (key:rsa [p q n e d]) =/ hed=json o+(my alg+s+'RS256' ~) @@ -508,13 +542,57 @@ ?~ fa | ?~ fb | (lte u.fa u.fb) + =/ inp=@t + :: %+ swp 3 + %- crip + ;: weld + "eyJhbGciOiJSUzI1NiJ9" + "." + "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + == + =/ exp=@t + %+ rap 3 + :~ 'cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7' + 'AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4' + 'BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K' + '0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv' + 'hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB' + 'p0igcN_IoypGlUPQGe77Rw' + == ;: weld %- expect-eq !> - :- "eyJhbGciOiJSUzI1NiJ9" + :- 'eyJhbGciOiJSUzI1NiJ9' (en-base64url (crip (en-json-sort aor hed))) %- expect-eq !> - :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" - (en-base64url (crip (en-json-sort lod-order lod))) + [pt p=(en-base64url p)] + %- expect-eq !> + [p p=(de-base64url pt)] + %- expect-eq !> + [qt q=(en-base64url q)] + %- expect-eq !> + [nt n=(en-base64url n)] + %- expect-eq !> + [dt d=(en-base64url d)] + %- expect-eq !> + [`@ux`n check-math=`n=@ux`(mul p q)] + %- expect-eq !> + [`@ux`d check-math=`d=@ux`(~(inv fo (elcm:rsa (dec p) (dec q))) e)] + %- expect-eq !> + :- exp + =/ sig (~(sign rs256 k) inp) + :: ~& inp+(rip 3 (swp 3 inp)) + :: ~& :* [pt (de-base64url pt) (en-base64url (de-base64url pt))] + :: [qt (de-base64url qt) (en-base64url (de-base64url qt))] + :: [nt (de-base64url nt) (en-base64url (de-base64url nt))] + :: [dt (de-base64url dt) (en-base64url (de-base64url dt))] + :: == + :: ~& ~(pass jwk k) + `@ux`sig + :: (en-base64url sig) + :: expected value has newlines + :: %- expect-eq !> + :: :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + :: (en-base64url (crip (en-json-sort lod-order lod))) == -- From 0928fe50e194d4b1e1154c6da6c576e1a3b85479 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 27 Apr 2018 16:31:18 -0400 Subject: [PATCH 07/95] implements initial asn1 serialization (for sha-256 digests) --- app/acme.hoon | 82 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index eae305fc1..90a769acb 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1,6 +1,5 @@ /+ tester -=, tester:tester -=, purl:eyre +=, eyre :: :::: libraries :: @@ -36,6 +35,59 @@ (out.fu (exp.fu d.k (sit.fu m))) -- :: +++ asn1 :: at least, a little + => |% + += spec + $% [%oct p=@] + [%nul ~] + [%obj p=@] + [%seq p=(list spec)] + == + :: + ++ obj :: constants (rfc4055) + |% :: + ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 + -- + -- + :: + |_ pec=spec + ++ ren :: bytes + ^- (list @) + =/ a lem + [tag (weld (len a) a)] + :: + ++ tag :: type tag + ^- @ + ?- pec + [%oct *] 4 + [%nul *] 5 + [%obj *] 6 + [%seq *] 48 :: (con 0x20 16) + == + :: + ++ lem :: element bytes + ^- (list @) + ?- pec + [%oct *] (rip 3 p.pec) + [%nul *] ~ + [%obj *] (rip 3 p.pec) + [%seq *] %- zing + |- ^- (list (list @)) + ?~ p.pec ~ + :- ren:.(pec i.p.pec) + $(p.pec t.p.pec) + == + :: + ++ len :: length bytes + |= a=(list @) + ^- (list @) + =/ b (lent a) + ?: (lte b 127) + [b ~] + :: XX not right + [(met 3 b) (rip 3 b)] + -- +:: ++ rs256 |_ k=key:rsa ++ sign |=(m=@ (de:rsa (shax m) k)) @@ -292,6 +344,7 @@ ++ prep _[~ this] :: ++ test + =, tester:tester =/ eny eny.bow :: non-deterministic for now :: 0vhu.gp79o.hi7at.smp8u.g5hhr.u3rff.st8ms.q4dc2.hv5ls.tp5cp.10qds. @@ -301,8 +354,9 @@ :: testen-base64url :: testrsakey :: testrsa + test-asn1 :: testjwkthumbprint - testjws + :: testjws == ?~(out abet ((slog out) abet)) :: @@ -436,7 +490,26 @@ %- expect-eq !> [m3 (de:rsa c3 k3)] == - -- + :: + ++ test-asn1 + =/ nul=spec:asn1 [%nul ~] + =/ obj=spec:asn1 [%obj sha-256:obj:asn1] + =/ oct=spec:asn1 [%oct (shax 'hello\0a')] + =/ seq=spec:asn1 [%seq [%seq obj nul ~] oct ~] + ;: weld + %- expect-eq !> + :- [0x5 0x0 ~] + ~(ren asn1 nul) + %- expect-eq !> + :- [0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1 ~] + ~(ren asn1 obj) + %- expect-eq !> + :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 + `@ux`(swp 3 (rep 3 ~(ren asn1 oct))) + %- expect-eq !> + :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 + `@ux`(swp 3 (rep 3 ~(ren asn1 seq))) + == :: ++ testjwkthumbprint =/ n @@ -594,5 +667,6 @@ :: :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" :: (en-base64url (crip (en-json-sort lod-order lod))) == + -- -- From 91ec568fdaa5883910e4f856db08c090b5ee2c42 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 27 Apr 2018 23:52:15 -0400 Subject: [PATCH 08/95] re-enables and corrects some failing tests --- app/acme.hoon | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 90a769acb..a44d3e0fc 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -351,11 +351,11 @@ :: h9bpt.vlmm7.lh375.f6u9n.krqv8.5jcml.cujkr.v1uqv.cjhe5.nplta |^ =/ out=tang ;: weld - :: testen-base64url - :: testrsakey - :: testrsa + testen-base64url + testrsakey + testrsa test-asn1 - :: testjwkthumbprint + testjwkthumbprint :: testjws == ?~(out abet ((slog out) abet)) @@ -364,7 +364,7 @@ =/ jon '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' ;: weld %- expect-eq !> - :- "AQAB" + :- 'AQAB' (en-base64url 65.537) :: expected value includes newlines :: %- expect-eq !> @@ -528,7 +528,7 @@ == :: %- expect-eq !> - :- "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" + :- 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs' (thumbprint k) :: ++ testjws From 6edf321e3635cf45857f8dbf659affda766f28f1 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 27 Apr 2018 23:52:52 -0400 Subject: [PATCH 09/95] adds asn1 digests to +rs256 (WIP - still failing) --- app/acme.hoon | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index a44d3e0fc..545fc618c 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -90,10 +90,21 @@ :: ++ rs256 |_ k=key:rsa - ++ sign |=(m=@ (de:rsa (shax m) k)) + ++ digest + |= m=@ + ^- @ + =/ pec=spec:asn1 + :~ %seq + [%seq [%obj sha-256:obj:asn1] [%nul ~] ~] + [%oct (shax m)] + == + (rep 3 ~(ren asn1 pec)) + :: + ++ sign |=(m=@ (de:rsa (digest m) k)) + :: ++ verify |= [s=@ m=@] - =((shax m) (en:rsa s k)) + =((digest m) (en:rsa s k)) -- :: ++ en-json-sort :: print json From 78b379b00d3ec8b3d5413d71b01ca99e92a07f4e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sat, 28 Apr 2018 00:15:22 -0400 Subject: [PATCH 10/95] adds (partial) asn1 parser, tests --- app/acme.hoon | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 545fc618c..321bd879d 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -84,8 +84,38 @@ =/ b (lent a) ?: (lte b 127) [b ~] - :: XX not right - [(met 3 b) (rip 3 b)] + [(con 0x80 (met 3 b)) (rip 3 b)] + :: + ++ decode + %+ cook |*(a=* `spec:asn1`a) + ;~ pose + (stag %oct (boss 256 ;~(pfix (just `@`4) till))) + (stag %nul (cold ~ ;~(plug (just `@`5) (just `@`0)))) + (stag %obj (boss 256 ;~(pfix (just `@`6) till))) + %+ stag %seq + %+ sear + |=(a=(list @) (rust a (star decode))) :: XX plus? curr? + ;~(pfix (just `@`48) till) + == + :: + ++ till :: length-prefixed bytes + |= tub/nail + ^- (like (list @D)) + ?~ q.tub + (fail tub) + =* fuz i.q.tub + =+ ^- [nex=@ len=@] + =/ faz (end 0 7 fuz) + ?: =(0 (cut 0 [7 1] fuz)) + [0 faz] + =/ fiz (rep 3 (scag faz t.q.tub)) + ?. =(faz (met 3 fiz)) !! :: XX + [faz fiz] + =/ zuf (scag len (slag nex t.q.tub)) + ?. =(len (lent zuf)) + (fail tub) + =/ zaf [p.p.tub (add +(nex) q.p.tub)] + [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] -- :: ++ rs256 @@ -511,15 +541,23 @@ %- expect-eq !> :- [0x5 0x0 ~] ~(ren asn1 nul) + %- expect-eq !> + [nul (scan ~(ren asn1 nul) decode:asn1)] %- expect-eq !> :- [0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1 ~] ~(ren asn1 obj) + %- expect-eq !> + [obj (scan ~(ren asn1 obj) decode:asn1)] %- expect-eq !> :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 `@ux`(swp 3 (rep 3 ~(ren asn1 oct))) + %- expect-eq !> + [oct (scan ~(ren asn1 oct) decode:asn1)] %- expect-eq !> :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 `@ux`(swp 3 (rep 3 ~(ren asn1 seq))) + %- expect-eq !> + [seq (scan ~(ren asn1 seq) decode:asn1)] == :: ++ testjwkthumbprint From dd201b9ab0cf4e42d5ec37ddb906ab011d044781 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 30 Apr 2018 12:19:21 -0400 Subject: [PATCH 11/95] wraps long lines --- app/acme.hoon | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 321bd879d..8176782c9 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -410,7 +410,9 @@ :: expected value includes newlines :: %- expect-eq !> :: ~& (en-base64:mimes:html jon) - :: :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + :: :- %+ weld + :: "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo" + :: "gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" :: (en-base64url jon) == :: @@ -549,12 +551,14 @@ %- expect-eq !> [obj (scan ~(ren asn1 obj) decode:asn1)] %- expect-eq !> - :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 + :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb. + d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 `@ux`(swp 3 (rep 3 ~(ren asn1 oct))) %- expect-eq !> [oct (scan ~(ren asn1 oct) decode:asn1)] %- expect-eq !> - :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 + :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5. + df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 `@ux`(swp 3 (rep 3 ~(ren asn1 seq))) %- expect-eq !> [seq (scan ~(ren asn1 seq) decode:asn1)] @@ -670,7 +674,8 @@ ;: weld "eyJhbGciOiJSUzI1NiJ9" "." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo" + "gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" == =/ exp=@t %+ rap 3 @@ -713,7 +718,9 @@ :: (en-base64url sig) :: expected value has newlines :: %- expect-eq !> - :: :- "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + :: :- %+ weld + :: "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo" + :: "gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" :: (en-base64url (crip (en-json-sort lod-order lod))) == -- From 94bef066a812bfeab5db3426d564c007aa331cd5 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 30 Apr 2018 14:51:56 -0400 Subject: [PATCH 12/95] refactors rsa keys in tests --- app/acme.hoon | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 8176782c9..6ed182857 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -431,7 +431,7 @@ == =/ k1 (new-key:rsa 2.048 eny) :: - =/ k2 + =/ k2=key:rsa =/ p 0x1837.be57.1286.bf6a.3cf8.4716.634f.ef85.f947.c654.da6e.e222. 5654.9466.0ab0.a2ef.1985.1095.e3c3.9e74.9478.e3f3.ee92.f885.ec3c. 84c3.6b3c.9731.65f9.9d1d.f743.646f.37d7.82d8.3f4a.856c.6453.b2c8. @@ -445,7 +445,7 @@ =/ n (mul p q) =/ e 0x1.0001 =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) - (key:rsa [p q n e d]) + [p q n e d] :: |^ ^- tang ;: weld @@ -483,17 +483,17 @@ -- :: ++ testrsa - =/ k1 - =/ p 61 - =/ q 53 - =/ e 17 + =/ k1=key:rsa + =/ p `@ux`61 + =/ q `@ux`53 + =/ e `@ux`17 =/ n (mul p q) =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) - (key:rsa [p q n e d]) + [p q n e d] :: - =/ k2 (key:rsa [11 13 143 7 103]) + =/ k2=key:rsa [`@ux`11 `@ux`13 `@ux`143 `@ux`7 `@ux`103] :: - =/ k3 + =/ k3=key:rsa =/ p 12.131.072.439.211.271.897.323.671.531.612.440.428.472.427.633.701.410. 925.634.549.312.301.964.373.042.085.619.324.197.365.322.416.866.541. @@ -505,7 +505,7 @@ =/ n (mul p q) =/ e 65.537 =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) - (key:rsa [p q n e d]) + [`@ux`p `@ux`q `@ux`n `@ux`e `@ux`d] =/ m3 (swp 3 'attack at dawn') =/ c3 35.052.111.338.673.026.690.212.423.937.053.328.511.880.760.811.579.981. @@ -651,8 +651,8 @@ 797f.8b2e.abe3.5e02.a0ce.d5d8.255a.c1d8.ee13.521f.6797.377d.2fc8. 280b.9b43.c6bf.03e5.88ec.bdd3.2c2f.cf3f.1e40.3c96.7ca5.0b9d.0f59. 627b.7049.e964.1d75.611d.1f57.0045.6c52.7ec3.2b0a.cd69.a471.ae12 - =/ e 65.537 - =/ k (key:rsa [p q n e d]) + =/ e `@ux`65.537 + =/ k=key:rsa [p q n e d] =/ hed=json o+(my alg+s+'RS256' ~) =/ lod=json :- %o %- my :~ From ea9dd4be119744a7373e525777b743848a736686 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 30 Apr 2018 14:53:58 -0400 Subject: [PATCH 13/95] makes rsa public exponent configurable, moves +rsa --- app/acme.hoon | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 6ed182857..114aabf91 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -4,37 +4,6 @@ :::: libraries :: |% -++ rsa :: unpadded! - |% - += key [p=@ux q=@ux n=@ux e=@ux d=@ux] - ++ elcm - |= [a=@ b=@] - (div (mul a b) d:(egcd a b)) - :: - ++ new-key - |= [wid=@ eny=@] - ^- key - =/ diw (rsh 0 1 wid) - =/ p=@ux (ramp:number diw [3 5 ~] eny) - =/ q=@ux (ramp:number diw [3 5 ~] +(eny)) - =/ n=@ux (mul p q) - =/ e `@ux`65.537 - =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) - [p q n e d] - :: - ++ en - |= [m=@ k=key] - ~| %rsa-len - ?> (lte (met 0 m) (met 0 n.k)) - (~(exp fo n.k) e.k m) - :: - ++ de - |= [m=@ k=key] - :: XX assert rsa-len here too? - =/ fu (fu:number p.k q.k) - (out.fu (exp.fu d.k (sit.fu m))) - -- -:: ++ asn1 :: at least, a little => |% += spec @@ -118,6 +87,37 @@ [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] -- :: +++ rsa :: unpadded! + |% + += key [p=@ux q=@ux n=@ux e=@ux d=@ux] + ++ elcm + |= [a=@ b=@] + (div (mul a b) d:(egcd a b)) + :: + ++ new-key + =/ e `@ux`65.537 + |= [wid=@ eny=@] + ^- key + =/ diw (rsh 0 1 wid) + =/ p=@ux (ramp:number diw [3 5 ~] eny) + =/ q=@ux (ramp:number diw [3 5 ~] +(eny)) + =/ n=@ux (mul p q) + =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) + [p q n e d] + :: + ++ en + |= [m=@ k=key] + ~| %rsa-len + ?> (lte (met 0 m) (met 0 n.k)) + (~(exp fo n.k) e.k m) + :: + ++ de + |= [m=@ k=key] + :: XX assert rsa-len here too? + =/ fu (fu:number p.k q.k) + (out.fu (exp.fu d.k (sit.fu m))) + -- +:: ++ rs256 |_ k=key:rsa ++ digest From 7162b69a46833d35d6759585223f85905cddac64 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 30 Apr 2018 12:17:53 -0400 Subject: [PATCH 14/95] updates base64 en/de-coding to optionally support padding and url-safety --- app/acme.hoon | 103 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 41 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 114aabf91..2aefb9e7e 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -4,6 +4,62 @@ :::: libraries :: |% +++ base64 :: rfc4648 + =+ [pad=& url=|] :: section 4 or 5 + |% + ++ en :: encode base64 + |= tig=@ + ^- cord + =/ poc (~(dif fo 3) 0 (met 3 tig)) + =/ pad (lsh 3 poc (swp 3 tig)) + =/ cha + ?: url + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + %- crip + %- flop + %+ weld + ?.(^pad ~ (reap poc '=')) + %+ slag poc + |- ^- tape + ?~ pad ~ + =/ d (end 3 3 pad) + :* (cut 3 [(cut 0 [0 6] d) 1] cha) + (cut 3 [(cut 0 [6 6] d) 1] cha) + (cut 3 [(cut 0 [12 6] d) 1] cha) + (cut 3 [(cut 0 [18 6] d) 1] cha) + $(pad (rsh 3 3 pad)) + == + :: + ++ de :: decode base64 + |= a=cord + ^- (unit @) + %+ rush a + %+ cook (cury swp 3) + %+ bass 64 + %+ cook welp + ;~ plug + %- plus + ;~ pose + (cook |=(a=@ (sub a 'A')) (shim 'A' 'Z')) + (cook |=(a=@ (sub a 'G')) (shim 'a' 'z')) + (cook |=(a=@ (add a 4)) (shim '0' '9')) + (cold 62 (just ?:(url '-' '+'))) + (cold 63 (just ?:(url '_' '/'))) + == + ?: pad + (stun 0^2 (cold %0 tis)) + =/ b (~(dif fo 4) 0 (met 3 a)) + (cold (reap b %0) (easy ~)) + == + -- +:: +++ en-base64url :: padding omitted + ~(en base64 | &) :: per rfc7515 +:: +++ de-base64url + ~(de base64 | &) +:: ++ asn1 :: at least, a little => |% += spec @@ -184,45 +240,6 @@ == -- :: -++ en-base64url :: rfc4648 section-5 - |= tig=@ :: padding omitted - ^- cord :: per rfc7515 - =/ poc (~(dif fo 3) 0 (met 3 tig)) - =/ pad (lsh 3 poc (swp 3 tig)) - =/ cha 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' - %- crip - %- flop - %+ slag poc - |- ^- tape - ?~ pad ~ - =/ d (end 3 3 pad) - :* (cut 3 [(cut 0 [0 6] d) 1] cha) - (cut 3 [(cut 0 [6 6] d) 1] cha) - (cut 3 [(cut 0 [12 6] d) 1] cha) - (cut 3 [(cut 0 [18 6] d) 1] cha) - $(pad (rsh 3 3 pad)) - == -:: -++ de-base64url - |= a=cord - ^- @ - %+ rash a - %+ cook |~(a/@ (swp 3 a)) - %+ bass 64 - %+ cook welp - ;~ plug - %- plus - ;~ pose - (cook |=(a=@ (sub a 'A')) (shim 'A' 'Z')) - (cook |=(a=@ (sub a 'G')) (shim 'a' 'z')) - (cook |=(a=@ (add a 4)) (shim '0' '9')) - (cold 62 (just '-')) - (cold 63 (just '_')) - == - =/ b (~(dif fo 4) 0 (met 3 a)) - (cold (reap b %0) (easy ~)) - == -:: ++ jwk |_ k=key:rsa ++ pass @@ -392,21 +409,25 @@ :: h9bpt.vlmm7.lh375.f6u9n.krqv8.5jcml.cujkr.v1uqv.cjhe5.nplta |^ =/ out=tang ;: weld - testen-base64url + test-base64 testrsakey testrsa test-asn1 + test-rsapem testjwkthumbprint :: testjws == ?~(out abet ((slog out) abet)) :: - ++ testen-base64url + ++ test-base64 =/ jon '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' ;: weld %- expect-eq !> :- 'AQAB' (en-base64url 65.537) + %- expect-eq !> + :- 65.537 + (need (de-base64url 'AQAB')) :: expected value includes newlines :: %- expect-eq !> :: ~& (en-base64:mimes:html jon) From b0b8e3f1d75edc2930fe905e3c84708a3adc1b31 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 30 Apr 2018 14:00:39 -0400 Subject: [PATCH 15/95] adds %int to asn.1 en/de-code --- app/acme.hoon | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/acme.hoon b/app/acme.hoon index 2aefb9e7e..e34901d47 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -63,7 +63,8 @@ ++ asn1 :: at least, a little => |% += spec - $% [%oct p=@] + $% [%int p=@] + [%oct p=@] [%nul ~] [%obj p=@] [%seq p=(list spec)] @@ -84,6 +85,7 @@ ++ tag :: type tag ^- @ ?- pec + [%int *] 2 [%oct *] 4 [%nul *] 5 [%obj *] 6 @@ -93,9 +95,14 @@ ++ lem :: element bytes ^- (list @) ?- pec + [%int *] ?: (lte p.pec 127) :: XX unsigned only! + [p.pec ~] + [0 (rip 3 p.pec)] + :: [%oct *] (rip 3 p.pec) [%nul *] ~ [%obj *] (rip 3 p.pec) + :: [%seq *] %- zing |- ^- (list (list @)) ?~ p.pec ~ @@ -114,9 +121,16 @@ ++ decode %+ cook |*(a=* `spec:asn1`a) ;~ pose + %+ stag %int + %+ boss 256 + %+ cook + |=(a=(list @) ?:(?=([@ @ *] a) t.a a)) + ;~(pfix (just `@`2) till) + :: (stag %oct (boss 256 ;~(pfix (just `@`4) till))) (stag %nul (cold ~ ;~(plug (just `@`5) (just `@`0)))) (stag %obj (boss 256 ;~(pfix (just `@`6) till))) + :: %+ stag %seq %+ sear |=(a=(list @) (rust a (star decode))) :: XX plus? curr? @@ -557,6 +571,7 @@ :: ++ test-asn1 =/ nul=spec:asn1 [%nul ~] + =/ int=spec:asn1 [%int 187] =/ obj=spec:asn1 [%obj sha-256:obj:asn1] =/ oct=spec:asn1 [%oct (shax 'hello\0a')] =/ seq=spec:asn1 [%seq [%seq obj nul ~] oct ~] @@ -566,6 +581,11 @@ ~(ren asn1 nul) %- expect-eq !> [nul (scan ~(ren asn1 nul) decode:asn1)] + %- expect-eq !> + :- [0x2 0x2 0x0 0xbb ~] + ~(ren asn1 int) + %- expect-eq !> + [int (scan ~(ren asn1 int) decode:asn1)] %- expect-eq !> :- [0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1 ~] ~(ren asn1 obj) From e31d6f1db95bc16684bb28b97ad2bc1ebe919b34 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 30 Apr 2018 22:15:57 -0400 Subject: [PATCH 16/95] adds DER and PEM encoding for RSA private keys --- app/acme.hoon | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/app/acme.hoon b/app/acme.hoon index e34901d47..aa8cc902e 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -175,6 +175,51 @@ =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) [p q n e d] :: + ++ der + |% + ++ en + |% + ++ pass !! + ++ ring + |= k=key + ^- @ux + =; pec + (rep 3 ~(ren asn1 pec)) + :~ %seq + [%int 0] + [%int n.k] + [%int e.k] + [%int d.k] + [%int p.k] + [%int q.k] + [%int (mod d.k (dec p.k))] + [%int (mod d.k (dec q.k))] + [%int (~(inv fo p.k) q.k)] + == + -- + ++ de + !! + -- + :: + ++ pem + |% + ++ en + |% + ++ pass !! + ++ ring + |= k=key + ^- wain + :- '-----BEGIN RSA PRIVATE KEY-----' + =/ a (en:base64 (ring:en:der k)) + |- ^- wain + ?~ a + ['-----END RSA PRIVATE KEY-----' ~] + [(end 3 64 a) $(a (rsh 3 64 a))] + -- + ++ de + !! + -- + :: ++ en |= [m=@ k=key] ~| %rsa-len @@ -517,6 +562,16 @@ ~ -- :: + ++ test-rsapem + =/ k=key:rsa [`@ux`17 `@ux`11 `@ux`187 `@ux`7 `@ux`23] + =/ exp=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MBwCAQACAgC7AgEHAgEXAgERAgELAgEHAgEDAgEO' + '-----END RSA PRIVATE KEY-----' + == + %- expect-eq !> + [exp (ring:en:pem:rsa k)] + :: ++ testrsa =/ k1=key:rsa =/ p `@ux`61 From 7f6adc57595e162ca55aa454d4b4fec0a8b15c57 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 30 Apr 2018 23:37:58 -0400 Subject: [PATCH 17/95] adds PEM and DER decoding for RSA private keys --- app/acme.hoon | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index aa8cc902e..7113d620c 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -198,7 +198,31 @@ == -- ++ de - !! + |% + ++ pass !! + ++ ring + |= a=@ + ^- (unit key) + =/ b (rush a decode:asn1) + ?~ b ~ + ?. ?=([%seq *] u.b) ~ + ?. ?= $: [%int *] + [%int *] + [%int *] + [%int *] + [%int *] + [%int *] + * + == + p.u.b + ~ + =* n p.i.t.p.u.b + =* e p.i.t.t.p.u.b + =* d p.i.t.t.t.p.u.b + =* p p.i.t.t.t.t.p.u.b + =* q p.i.t.t.t.t.t.p.u.b + `[p q n e d] + -- -- :: ++ pem @@ -217,7 +241,19 @@ [(end 3 64 a) $(a (rsh 3 64 a))] -- ++ de - !! + |% + ++ pass !! + ++ ring + |= mep=wain + ^- (unit key) + =/ a (sub (lent mep) 2) + ?~ mep ~ + ?. =('-----BEGIN RSA PRIVATE KEY-----' i.mep) ~ + ?. =('-----END RSA PRIVATE KEY-----' (snag a t.mep)) ~ + =/ b (de:base64 (rap 3 (scag a t.mep))) + ?~ b ~ + (ring:de:der u.b) + -- -- :: ++ en @@ -569,8 +605,12 @@ 'MBwCAQACAgC7AgEHAgEXAgERAgELAgEHAgEDAgEO' '-----END RSA PRIVATE KEY-----' == - %- expect-eq !> - [exp (ring:en:pem:rsa k)] + ;: weld + %- expect-eq !> + [exp (ring:en:pem:rsa k)] + %- expect-eq !> + [k (need (ring:de:pem:rsa exp))] + == :: ++ testrsa =/ k1=key:rsa From 2b0836a815ae00b64e19369e0390cee7a09d6b12 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 1 May 2018 00:01:00 -0400 Subject: [PATCH 18/95] cleans up +till:asn1 (length-prefixed byte parser) --- app/acme.hoon | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 7113d620c..81ce00af5 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -147,10 +147,12 @@ =/ faz (end 0 7 fuz) ?: =(0 (cut 0 [7 1] fuz)) [0 faz] - =/ fiz (rep 3 (scag faz t.q.tub)) - ?. =(faz (met 3 fiz)) !! :: XX - [faz fiz] - =/ zuf (scag len (slag nex t.q.tub)) + [faz (rep 3 (scag faz t.q.tub))] + ?: ?& !=(0 nex) + !=(nex (met 3 len)) + == + (fail tub) + =/ zuf (swag [nex len] t.q.tub) ?. =(len (lent zuf)) (fail tub) =/ zaf [p.p.tub (add +(nex) q.p.tub)] From 5388900d034898a67521d0d9d2c1e93540a45bf9 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 7 May 2018 19:00:56 -0400 Subject: [PATCH 19/95] fixes ASN.1 DER multi-byte length prefix en/de-coding --- app/acme.hoon | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 81ce00af5..2f4c54ba3 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -116,7 +116,7 @@ =/ b (lent a) ?: (lte b 127) [b ~] - [(con 0x80 (met 3 b)) (rip 3 b)] + [(con 0x80 (met 3 b)) (flop (rip 3 b))] :: ++ decode %+ cook |*(a=* `spec:asn1`a) @@ -137,7 +137,7 @@ ;~(pfix (just `@`48) till) == :: - ++ till :: length-prefixed bytes + ++ till :: len-prefixed bytes |= tub/nail ^- (like (list @D)) ?~ q.tub @@ -147,7 +147,7 @@ =/ faz (end 0 7 fuz) ?: =(0 (cut 0 [7 1] fuz)) [0 faz] - [faz (rep 3 (scag faz t.q.tub))] + [faz (rep 3 (flop (scag faz t.q.tub)))] ?: ?& !=(0 nex) !=(nex (met 3 len)) == From 340d7da6183fafa4b38286397d9c5cfffb5df526 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 7 May 2018 19:00:22 -0400 Subject: [PATCH 20/95] fixes ASN.1 DER unsigned integer en/de-coding --- app/acme.hoon | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 2f4c54ba3..0b34ac15e 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -95,9 +95,9 @@ ++ lem :: element bytes ^- (list @) ?- pec - [%int *] ?: (lte p.pec 127) :: XX unsigned only! - [p.pec ~] - [0 (rip 3 p.pec)] + [%int *] =/ a (flop (rip 3 p.pec)) :: XX unsigned only! + ?~ a [0 ~] + ?:((lte i.a 127) a [0 a]) :: [%oct *] (rip 3 p.pec) [%nul *] ~ @@ -122,9 +122,14 @@ %+ cook |*(a=* `spec:asn1`a) ;~ pose %+ stag %int - %+ boss 256 - %+ cook - |=(a=(list @) ?:(?=([@ @ *] a) t.a a)) + %+ bass 256 + %+ sear + |= a=(list @) + ^- (unit (list @)) + ?~ a ~ + ?: ?=([@ ~] a) `a + ?. =(0 i.a) `a + ?.((gth i.t.a 127) ~ `t.a) ;~(pfix (just `@`2) till) :: (stag %oct (boss 256 ;~(pfix (just `@`4) till))) From aefb6dff4d49c26d4a64999d4d35991ad25dcca6 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 7 May 2018 20:50:00 -0400 Subject: [PATCH 21/95] adds additional RSA PEM/DER test cases, reorders tests --- app/acme.hoon | 138 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 40 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 0b34ac15e..7d2fd7545 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -512,10 +512,11 @@ |^ =/ out=tang ;: weld test-base64 + test-asn1 testrsakey testrsa - test-asn1 test-rsapem + test-rs256 testjwkthumbprint :: testjws == @@ -539,6 +540,42 @@ :: (en-base64url jon) == :: + ++ test-asn1 + =/ nul=spec:asn1 [%nul ~] + =/ int=spec:asn1 [%int 187] + =/ obj=spec:asn1 [%obj sha-256:obj:asn1] + =/ oct=spec:asn1 [%oct (shax 'hello\0a')] + =/ seq=spec:asn1 [%seq [%seq obj nul ~] oct ~] + ;: weld + %- expect-eq !> + :- [0x5 0x0 ~] + ~(ren asn1 nul) + %- expect-eq !> + [nul (scan ~(ren asn1 nul) decode:asn1)] + %- expect-eq !> + :- [0x2 0x2 0x0 0xbb ~] + ~(ren asn1 int) + %- expect-eq !> + [int (scan ~(ren asn1 int) decode:asn1)] + %- expect-eq !> + :- [0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1 ~] + ~(ren asn1 obj) + %- expect-eq !> + [obj (scan ~(ren asn1 obj) decode:asn1)] + %- expect-eq !> + :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb. + d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 + `@ux`(swp 3 (rep 3 ~(ren asn1 oct))) + %- expect-eq !> + [oct (scan ~(ren asn1 oct) decode:asn1)] + %- expect-eq !> + :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5. + df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 + `@ux`(swp 3 (rep 3 ~(ren asn1 seq))) + %- expect-eq !> + [seq (scan ~(ren asn1 seq) decode:asn1)] + == + :: ++ testrsakey =/ primes=(list @) :~ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 @@ -606,17 +643,71 @@ -- :: ++ test-rsapem - =/ k=key:rsa [`@ux`17 `@ux`11 `@ux`187 `@ux`7 `@ux`23] - =/ exp=wain + =/ k1=key:rsa [`@ux`17 `@ux`11 `@ux`187 `@ux`7 `@ux`23] + =/ kpem1=wain :~ '-----BEGIN RSA PRIVATE KEY-----' 'MBwCAQACAgC7AgEHAgEXAgERAgELAgEHAgEDAgEO' '-----END RSA PRIVATE KEY-----' == + =/ k2=key:rsa + :* p=`@ux`4.140.273.707 + q=`@ux`3.922.198.019 + n=`@ux`16.238.973.331.713.186.433 + e=`@ux`65.537 + d=`@ux`3.298.243.342.098.580.397 + == + =/ kpem2=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MEACAQACCQDhXGw1Gc5agQIDAQABAggtxbbYRJVDrQIFAPbHkCsCBQDpx/4DAgUA' + '23X55QIFAIpPROsCBQC56nYF' + '-----END RSA PRIVATE KEY-----' + == + =/ kpem3=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MIIEowIBAAKCAQEA2jJp8dgAKy5cSzDE4D+aUbKZsQoMhIWI2IFlE+AO0GCBMig5' + 'qxx2IIAPVIcSi5fjOLtTHnuIZYw+s06qeb8QIKRvkZaIwnA3Lz5UUrxgh96sezdX' + 'CCSG7FndIFskcT+zG00JL+fPRdlPjt1Vg2b3kneo5aAKMIPyOTzcY590UTc+luQ3' + 'HhgSiNF3n5YQh24d3kS2YOUoSXQ13+YRljxNfBgXbV+C7/gO8mFxpkafhmgkIGNe' + 'WlqT9oAIRa+gOx13uPAg+Jb/8lPV9bGaFqGvxvBMp3xUASlzYHiDntcB5MiOPRW6' + 'BoIGI5qDFSYRZBky9crE7WAYgqtPtg21zvxwFwIDAQABAoIBAH0q7GGisj4TIziy' + '6k1lzwXMuaO4iwO+gokIeU5UessIgTSfpK1G73CnZaPstDPF1r/lncHfxZfTQuij' + 'WOHsO7kt+x5+R0ebDd0ZGVA45fsrPrCUR2XRZmDRECuOfTJGA13G7F1B0kJUbfIb' + 'gAGYIK8x236WNyIrntk804SGpTgstCsZ51rK5GL6diZVQbeU806oP1Zhx/ye//NR' + 'mS5G0iil//H41pV5WGomOX0mq9/HYBZqCncqzLki6FFdmXykjz8snvXUR40S8B+a' + '0F/LN+549PSe2dp9h0Hx4HCJOsL9CyCQimqqqE8KPQ4BUz8q3+Mhx1xEyaxIlNH9' + 'ECgo1CECgYEA+mi7vQRzstYJerbhCtaeFrOR/n8Dft7FyFN+5IV7H2omy6gf0zr1' + 'GWjmph5R0sMPgL8uVRGANUrkuZZuCr35iY6zQpdCFB4D9t+zbTvTmrxt2oVaE16/' + 'dIJ6b8cHzR2QrEh8uw5/rEKzWBCHNS8FvXHPvXvnacTZ5LZRK0ssshECgYEA3xGQ' + 'nDlmRwyVto/1DQMLnjIMazQ719qtCO/pf4BHeqcDYnIwYb5zLBj2nPV8D9pqM1pG' + 'OVuOgcC9IimrbHeeGwp1iSTH4AvxDIj6Iyrmbz2db3lGdHVk9xLvTiYzn2KK2sYx' + 'mFl3DRBFutFQ2YxddqHbE3Ds96Y/uRXhqj7I16cCgYEA1AVNwHM+i1OS3yZtUUH6' + 'xPnySWu9x/RTvpSDwnYKk8TLaHDH0Y//6y3Y7RqK6Utjmv1E+54/0d/B3imyrsG/' + 'wWrj+SQdPO9VJ/is8XZQapnU4cs7Q19b+AhqJq58un2n+1e81J0oGPC47X3BHZTc' + '5VSyMpvwiqu0WmTMQT37cCECgYACMEbt8XY6bjotz13FIemERNNwXdPUe1XFR61P' + 'ze9lmavj1GD7JIY2wYvx4Eq2URtHo7QarfZI+Z4hbq065DWN6F1c2hqH7TYRPGrP' + '24TlRIJ97H+vdtNlxS7J4oARKUNZgCZOa1pKq4UznwgfCkyEdHQUzb/VcjEf3MIZ' + 'DIKl8wKBgBrsIjiDvpkfnpmQ7fehEJIi+V4SGskLxFH3ZTvngFFoYry3dL5gQ6mF' + 'sDfrn4igIcEy6bMpJQ3lbwStyzcWZLMJgdI23FTlPXTEG7PclZSuxBpQpvg3MiVO' + 'zqVTrhnY+TemcScSx5O6f32aDfOUWWCzmw/gzvJxUYlJqjqd7dlT' + '-----END RSA PRIVATE KEY-----' + == + =/ kder3=@ux + (need (de:base64 (rap 3 (swag [1 (sub (lent kpem3) 2)] kpem3)))) + =/ k3=key:rsa + (need (ring:de:pem:rsa kpem3)) ;: weld %- expect-eq !> - [exp (ring:en:pem:rsa k)] + [kpem1 (ring:en:pem:rsa k1)] %- expect-eq !> - [k (need (ring:de:pem:rsa exp))] + [k1 (need (ring:de:pem:rsa kpem1))] + %- expect-eq !> + [kpem2 (ring:en:pem:rsa k2)] + %- expect-eq !> + [k2 (need (ring:de:pem:rsa kpem2))] + %- expect-eq !> + [kpem3 (ring:en:pem:rsa k3)] + %- expect-eq !> + [kder3 (ring:en:der:rsa k3)] == :: ++ testrsa @@ -671,41 +762,8 @@ [m3 (de:rsa c3 k3)] == :: - ++ test-asn1 - =/ nul=spec:asn1 [%nul ~] - =/ int=spec:asn1 [%int 187] - =/ obj=spec:asn1 [%obj sha-256:obj:asn1] - =/ oct=spec:asn1 [%oct (shax 'hello\0a')] - =/ seq=spec:asn1 [%seq [%seq obj nul ~] oct ~] - ;: weld - %- expect-eq !> - :- [0x5 0x0 ~] - ~(ren asn1 nul) - %- expect-eq !> - [nul (scan ~(ren asn1 nul) decode:asn1)] - %- expect-eq !> - :- [0x2 0x2 0x0 0xbb ~] - ~(ren asn1 int) - %- expect-eq !> - [int (scan ~(ren asn1 int) decode:asn1)] - %- expect-eq !> - :- [0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1 ~] - ~(ren asn1 obj) - %- expect-eq !> - [obj (scan ~(ren asn1 obj) decode:asn1)] - %- expect-eq !> - :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb. - d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 - `@ux`(swp 3 (rep 3 ~(ren asn1 oct))) - %- expect-eq !> - [oct (scan ~(ren asn1 oct) decode:asn1)] - %- expect-eq !> - :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5. - df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 - `@ux`(swp 3 (rep 3 ~(ren asn1 seq))) - %- expect-eq !> - [seq (scan ~(ren asn1 seq) decode:asn1)] - == + ++ test-rs256 + ~ :: ++ testjwkthumbprint =/ n From dce78a303aef90b4239c55886f1764a4cdfcbc16 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 8 May 2018 14:02:56 -0400 Subject: [PATCH 22/95] implements EMSA-PKCS1-v1_5 for RSA signatures finally compatible with openssl! --- app/acme.hoon | 102 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 7d2fd7545..f4af12961 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -278,21 +278,27 @@ :: ++ rs256 |_ k=key:rsa - ++ digest + ++ emsa :: EMSA-PKCS1-v1_5 |= m=@ - ^- @ + =/ emlen (met 3 n.k) =/ pec=spec:asn1 :~ %seq [%seq [%obj sha-256:obj:asn1] [%nul ~] ~] [%oct (shax m)] == - (rep 3 ~(ren asn1 pec)) + =/ t=(list @) ~(ren asn1 pec) + =/ tlen (lent t) + ?: (lth emlen (add 11 tlen)) + ~|(%emsa-too-short !!) + =/ ps (reap (sub emlen (add 3 tlen)) 0xff) + %+ rep 3 + (flop (weld [0x0 0x1 ps] [0x0 t])) :: - ++ sign |=(m=@ (de:rsa (digest m) k)) + ++ sign |=(m=@ (de:rsa (emsa m) k)) :: ++ verify |= [s=@ m=@] - =((digest m) (en:rsa s k)) + =((emsa m) (en:rsa s k)) -- :: ++ en-json-sort :: print json @@ -763,7 +769,91 @@ == :: ++ test-rs256 - ~ + =/ k1=key:rsa + :* 0xf7ef.37e6.7fa6.685a.c178.8b01.cf38.da20.ca4b.de5d.8b01.a71b.d28c. + 65b4.09c3.6e4d + 0xc882.5760.3fb8.a5e2.5e9d.db55.3a73.b647.a3ec.a6e9.abc6.c440.dbc7. + 05f8.2ed4.da6b + 0xc231.1fc5.fa31.d333.a409.bb4c.e95b.20d2.1cfc.e375.3871.7256.53a2. + 8425.af6d.e97d.f202.0b23.633f.458d.f12a.6362.7121.bff4.e23c.e578. + 7e07.7898.0578.61d1.ae60.ac2f + 0x1.0001 + 0xd91.6719.eb10.3e24.768a.a386.8d2b.6bd0.a26b.dcec.9cc3.f86c.25ad. + ce33.dfdc.fb1a.4d50.3e07.3d7f.f5fd.748e.43f8.df02.a60e.d730.5314. + 3e59.1e70.8df7.2c27.93e2.2b69 + == + =/ inp1 0x302.0101 + =/ exp1 + 0x575c.8a41.09ed.6ea2.a708.6338.d150.a5bb.8205.142e.7785.47b5.0cc6.0198. + 6807.0243.bf49.de7c.6039.0160.e392.faca.18f4.a05d.3a7a.88a4.de86.dd99. + f030.eb4a.a755.d7ce + =/ kpem2=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MIIEowIBAAKCAQEA2jJp8dgAKy5cSzDE4D+aUbKZsQoMhIWI2IFlE+AO0GCBMig5' + 'qxx2IIAPVIcSi5fjOLtTHnuIZYw+s06qeb8QIKRvkZaIwnA3Lz5UUrxgh96sezdX' + 'CCSG7FndIFskcT+zG00JL+fPRdlPjt1Vg2b3kneo5aAKMIPyOTzcY590UTc+luQ3' + 'HhgSiNF3n5YQh24d3kS2YOUoSXQ13+YRljxNfBgXbV+C7/gO8mFxpkafhmgkIGNe' + 'WlqT9oAIRa+gOx13uPAg+Jb/8lPV9bGaFqGvxvBMp3xUASlzYHiDntcB5MiOPRW6' + 'BoIGI5qDFSYRZBky9crE7WAYgqtPtg21zvxwFwIDAQABAoIBAH0q7GGisj4TIziy' + '6k1lzwXMuaO4iwO+gokIeU5UessIgTSfpK1G73CnZaPstDPF1r/lncHfxZfTQuij' + 'WOHsO7kt+x5+R0ebDd0ZGVA45fsrPrCUR2XRZmDRECuOfTJGA13G7F1B0kJUbfIb' + 'gAGYIK8x236WNyIrntk804SGpTgstCsZ51rK5GL6diZVQbeU806oP1Zhx/ye//NR' + 'mS5G0iil//H41pV5WGomOX0mq9/HYBZqCncqzLki6FFdmXykjz8snvXUR40S8B+a' + '0F/LN+549PSe2dp9h0Hx4HCJOsL9CyCQimqqqE8KPQ4BUz8q3+Mhx1xEyaxIlNH9' + 'ECgo1CECgYEA+mi7vQRzstYJerbhCtaeFrOR/n8Dft7FyFN+5IV7H2omy6gf0zr1' + 'GWjmph5R0sMPgL8uVRGANUrkuZZuCr35iY6zQpdCFB4D9t+zbTvTmrxt2oVaE16/' + 'dIJ6b8cHzR2QrEh8uw5/rEKzWBCHNS8FvXHPvXvnacTZ5LZRK0ssshECgYEA3xGQ' + 'nDlmRwyVto/1DQMLnjIMazQ719qtCO/pf4BHeqcDYnIwYb5zLBj2nPV8D9pqM1pG' + 'OVuOgcC9IimrbHeeGwp1iSTH4AvxDIj6Iyrmbz2db3lGdHVk9xLvTiYzn2KK2sYx' + 'mFl3DRBFutFQ2YxddqHbE3Ds96Y/uRXhqj7I16cCgYEA1AVNwHM+i1OS3yZtUUH6' + 'xPnySWu9x/RTvpSDwnYKk8TLaHDH0Y//6y3Y7RqK6Utjmv1E+54/0d/B3imyrsG/' + 'wWrj+SQdPO9VJ/is8XZQapnU4cs7Q19b+AhqJq58un2n+1e81J0oGPC47X3BHZTc' + '5VSyMpvwiqu0WmTMQT37cCECgYACMEbt8XY6bjotz13FIemERNNwXdPUe1XFR61P' + 'ze9lmavj1GD7JIY2wYvx4Eq2URtHo7QarfZI+Z4hbq065DWN6F1c2hqH7TYRPGrP' + '24TlRIJ97H+vdtNlxS7J4oARKUNZgCZOa1pKq4UznwgfCkyEdHQUzb/VcjEf3MIZ' + 'DIKl8wKBgBrsIjiDvpkfnpmQ7fehEJIi+V4SGskLxFH3ZTvngFFoYry3dL5gQ6mF' + 'sDfrn4igIcEy6bMpJQ3lbwStyzcWZLMJgdI23FTlPXTEG7PclZSuxBpQpvg3MiVO' + 'zqVTrhnY+TemcScSx5O6f32aDfOUWWCzmw/gzvJxUYlJqjqd7dlT' + '-----END RSA PRIVATE KEY-----' + == + =/ k2=key:rsa + (need (ring:de:pem:rsa kpem2)) + =/ inp2=cord 'hello\0a' + =/ exp2=@ux + 0x2920.bba3.cb38.bca6.3768.6345.c95e.0717.81bf.6c61.4006.6070.a7b5.e609. + f3b4.7f48.878b.d1f8.1882.8852.1db6.b6b5.a5fd.c23b.e764.b910.5a3f.fda9. + 9d3a.e8bd.060a.ac06.58f1.487a.b50d.dee2.e161.0b74.4d3b.e6e3.7004.c721. + 4f32.5c95.ce68.a008.b1e9.788b.375f.d389.0fa4.4012.c07a.8319.a183.02d5. + e2b8.10df.6ff7.f64a.6b85.3c7d.de80.19cf.ab6d.e588.40cb.0ea4.c436.8d8b. + 47f7.cce6.b9bf.097d.3275.c128.147a.628d.2b7c.3912.3950.ef68.87b2.180d. + ba01.3b05.285d.3dfd.09ee.2f38.3111.9e4c.92c6.bf66.a91b.5762.3cdf.f8b7. + 8281.81a2.8324.5330.43c1.035a.56c3.71b8.eb85.e660.c3a4.28b4.8af7.c16f. + 7d7d.87cc.036d.aeb2.c757.30f5.f194.c90d.6bb4.5e5c.f95f.8e28.0fbc.5fb4. + b21a.e6fe + =/ exp2b64=cord + %+ rap 3 + :~ 'KSC7o8s4vKY3aGNFyV4HF4G/bGFABmBwp7XmCfO0f0iHi9H4GIKIUh22trWl/cI752S5' + 'EFo//amdOui9BgqsBljxSHq1Dd7i4WELdE075uNwBMchTzJclc5ooAix6XiLN1/TiQ+k' + 'QBLAeoMZoYMC1eK4EN9v9/ZKa4U8fd6AGc+rbeWIQMsOpMQ2jYtH98zmub8JfTJ1wSgU' + 'emKNK3w5EjlQ72iHshgNugE7BShdPf0J7i84MRGeTJLGv2apG1diPN/4t4KBgaKDJFMw' + 'Q8EDWlbDcbjrheZgw6QotIr3wW99fYfMA22ussdXMPXxlMkNa7ReXPlfjigPvF+0shrm' + '/g==' + == + =/ sig=@ux (~(sign rs256 k2) inp2) + ;: weld + %- expect-eq !> + [exp1 (~(sign rs256 k1) inp1)] + %- expect-eq !> + [& (~(verify rs256 k1) exp1 inp1)] + %- expect-eq !> + [& (~(verify rs256 k2) sig inp2)] + %- expect-eq !> + [exp2 sig] + :: save kpem2 to private.pem + :: echo "hello" | openssl dgst -sha256 -sign private.pem | base64 + %- expect-eq !> + [exp2b64 (en:base64 (swp 3 sig))] + == :: ++ testjwkthumbprint =/ n From 8fdfa71a8ddb1ab3cd51e0752106179af961c90e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 8 May 2018 16:13:38 -0400 Subject: [PATCH 23/95] adds some base64 en/de-coding tests --- app/acme.hoon | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index f4af12961..295e3cf02 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -529,21 +529,21 @@ ?~(out abet ((slog out) abet)) :: ++ test-base64 - =/ jon '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' ;: weld %- expect-eq !> - :- 'AQAB' - (en-base64url 65.537) + ['AQAB' (en-base64url 65.537)] %- expect-eq !> - :- 65.537 - (need (de-base64url 'AQAB')) - :: expected value includes newlines - :: %- expect-eq !> - :: ~& (en-base64:mimes:html jon) - :: :- %+ weld - :: "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo" - :: "gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" - :: (en-base64url jon) + [65.537 (need (de-base64url 'AQAB'))] + :: echo "hello" | base64 + %- expect-eq !> + ['aGVsbG8K' (en:base64 'hello\0a')] + %- expect-eq !> + ['hello\0a' (need (de:base64 'aGVsbG8K'))] + :: echo -n -e "\x01\x01\x02\x03" | base64 + %- expect-eq !> + ['AQECAw==' (en:base64 (swp 3 0x101.0203))] + %- expect-eq !> + [0x302.0101 (need (de:base64 'AQECAw=='))] == :: ++ test-asn1 From fd95b950d1f5b92912bbe8ec95b6cd7eebde1d56 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 8 May 2018 19:56:56 -0400 Subject: [PATCH 24/95] cleans up tests, adds comments with sources for most test parameters --- app/acme.hoon | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 295e3cf02..ef6eac906 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -519,11 +519,11 @@ ;: weld test-base64 test-asn1 - testrsakey - testrsa + test-rsakey + test-rsa test-rsapem test-rs256 - testjwkthumbprint + test-jwkthumbprint :: testjws == ?~(out abet ((slog out) abet)) @@ -582,7 +582,7 @@ [seq (scan ~(ren asn1 seq) decode:asn1)] == :: - ++ testrsakey + ++ test-rsakey =/ primes=(list @) :~ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 @@ -649,6 +649,7 @@ -- :: ++ test-rsapem + :: ex from https://stackoverflow.com/a/19855935 =/ k1=key:rsa [`@ux`17 `@ux`11 `@ux`187 `@ux`7 `@ux`23] =/ kpem1=wain :~ '-----BEGIN RSA PRIVATE KEY-----' @@ -662,12 +663,14 @@ e=`@ux`65.537 d=`@ux`3.298.243.342.098.580.397 == + :: openssl genrsa -out private.pem 64 =/ kpem2=wain :~ '-----BEGIN RSA PRIVATE KEY-----' 'MEACAQACCQDhXGw1Gc5agQIDAQABAggtxbbYRJVDrQIFAPbHkCsCBQDpx/4DAgUA' '23X55QIFAIpPROsCBQC56nYF' '-----END RSA PRIVATE KEY-----' == + :: openssl genrsa -out private.pem 2048 =/ kpem3=wain :~ '-----BEGIN RSA PRIVATE KEY-----' 'MIIEowIBAAKCAQEA2jJp8dgAKy5cSzDE4D+aUbKZsQoMhIWI2IFlE+AO0GCBMig5' @@ -697,8 +700,6 @@ 'zqVTrhnY+TemcScSx5O6f32aDfOUWWCzmw/gzvJxUYlJqjqd7dlT' '-----END RSA PRIVATE KEY-----' == - =/ kder3=@ux - (need (de:base64 (rap 3 (swag [1 (sub (lent kpem3) 2)] kpem3)))) =/ k3=key:rsa (need (ring:de:pem:rsa kpem3)) ;: weld @@ -712,11 +713,9 @@ [k2 (need (ring:de:pem:rsa kpem2))] %- expect-eq !> [kpem3 (ring:en:pem:rsa k3)] - %- expect-eq !> - [kder3 (ring:en:der:rsa k3)] == :: - ++ testrsa + ++ test-rsa =/ k1=key:rsa =/ p `@ux`61 =/ q `@ux`53 @@ -727,6 +726,7 @@ :: =/ k2=key:rsa [`@ux`11 `@ux`13 `@ux`143 `@ux`7 `@ux`103] :: + :: ex from http://doctrina.org/How-RSA-Works-With-Examples.html =/ k3=key:rsa =/ p 12.131.072.439.211.271.897.323.671.531.612.440.428.472.427.633.701.410. @@ -769,6 +769,7 @@ == :: ++ test-rs256 + :: ex from https://stackoverflow.com/a/41448118 =/ k1=key:rsa :* 0xf7ef.37e6.7fa6.685a.c178.8b01.cf38.da20.ca4b.de5d.8b01.a71b.d28c. 65b4.09c3.6e4d @@ -787,6 +788,10 @@ 0x575c.8a41.09ed.6ea2.a708.6338.d150.a5bb.8205.142e.7785.47b5.0cc6.0198. 6807.0243.bf49.de7c.6039.0160.e392.faca.18f4.a05d.3a7a.88a4.de86.dd99. f030.eb4a.a755.d7ce + =/ emsa1 + 0x1.ffff.ffff.ffff.ffff.ffff.0030.3130.0d06.0960.8648.0165.0304.0201.0500. + 0420.9184.abd2.bb31.8731.d717.e972.0572.40ea.e26c.ca20.2a8d.35db.e9d2. + 176f.5268.86a0 =/ kpem2=wain :~ '-----BEGIN RSA PRIVATE KEY-----' 'MIIEowIBAAKCAQEA2jJp8dgAKy5cSzDE4D+aUbKZsQoMhIWI2IFlE+AO0GCBMig5' @@ -845,6 +850,8 @@ [exp1 (~(sign rs256 k1) inp1)] %- expect-eq !> [& (~(verify rs256 k1) exp1 inp1)] + %- expect-eq !> + [emsa1 `@ux`(~(emsa rs256 k1) inp1)] %- expect-eq !> [& (~(verify rs256 k2) sig inp2)] %- expect-eq !> @@ -855,7 +862,8 @@ [exp2b64 (en:base64 (swp 3 sig))] == :: - ++ testjwkthumbprint + ++ test-jwkthumbprint + :: rfc7638 section 3.1 =/ n :~ '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2' 'aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCi' @@ -875,7 +883,7 @@ :- 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs' (thumbprint k) :: - ++ testjws + ++ test-jws ^- wall =/ pt=@t %+ rap 3 From d8d1f36eaac4c8addc4f2b9804a9ed3d57b83626 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 9 May 2018 00:03:51 -0400 Subject: [PATCH 25/95] refactors +jwk, corrects decoding, implements encoding --- app/acme.hoon | 59 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index ef6eac906..2979bb979 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -349,16 +349,36 @@ -- :: ++ jwk - |_ k=key:rsa - ++ pass - ^- json - :- %o %- my :~ - kty+s+'RSA' - n+s+(en-base64url n.k) - e+s+(en-base64url e.k) - == - ++ ring !! + |% + ++ en + |% + ++ pass + |= k=key:rsa + ^- json + :- %o %- my :~ + kty+s+'RSA' + n+s+(en-base64url (swp 3 n.k)) + e+s+(en-base64url (swp 3 e.k)) + == + ++ ring !! + -- + ++ de + |% + ++ pass + =, dejs-soft:format + %+ ci + |= a=[kty=@t n=(unit @) e=(unit @)] + ^- (unit [n=@ux e=@ux]) :: XX RSA pubkey model + (both (bind n.a (cury swp 3)) (bind e.a (cury swp 3))) + %- ot :~ + kty+(su (jest 'RSA')) + n+(cu de-base64url so) + e+(cu de-base64url so) + == + ++ ring !! + -- -- +:: ++ thumbprint |= jon=json :: XX restrict keys to canonical set @@ -432,7 +452,7 @@ ?^ kid kid+s+u.kid ?> ?=(^ key) - jwk+~(pass jwk u.key) + jwk+(pass:en:jwk u.key) == %- (corl as-octt:mimes:html en-json:html) ^- json @@ -523,7 +543,7 @@ test-rsa test-rsapem test-rs256 - test-jwkthumbprint + test-jwk :: testjws == ?~(out abet ((slog out) abet)) @@ -862,7 +882,7 @@ [exp2b64 (en:base64 (swp 3 sig))] == :: - ++ test-jwkthumbprint + ++ test-jwk :: rfc7638 section 3.1 =/ n :~ '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2' @@ -872,16 +892,21 @@ '91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_x' 'BniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw' == - =/ k=json + =/ jk=json :- %o %- my :~ e+s+'AQAB' kty+s+'RSA' n+s+(rap 3 n) == - :: - %- expect-eq !> - :- 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs' - (thumbprint k) + =/ k (need (pass:de:jwk jk)) + ;: weld + %- expect-eq !> + :- jk + (pass:en:jwk [0x0 0x0 n.k e.k 0x0]) + %- expect-eq !> + :- 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs' + (thumbprint jk) + == :: ++ test-jws ^- wall From d952b368cbc2ffa3dde6a98e2f7b18d4b13b8586 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 9 May 2018 00:04:26 -0400 Subject: [PATCH 26/95] tests for pkcs1 version number in DER decoding --- app/acme.hoon | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 2979bb979..c63f9ea15 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -182,7 +182,7 @@ =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) [p q n e d] :: - ++ der + ++ der :: pkcs1 |% ++ en |% @@ -213,7 +213,7 @@ =/ b (rush a decode:asn1) ?~ b ~ ?. ?=([%seq *] u.b) ~ - ?. ?= $: [%int *] + ?. ?= $: [%int %0] [%int *] [%int *] [%int *] @@ -232,7 +232,7 @@ -- -- :: - ++ pem + ++ pem :: pkcs1 |% ++ en |% From f2fe13bf73187dcf3ef4135ef0bee7df19ccc541 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 9 May 2018 13:45:39 -0400 Subject: [PATCH 27/95] implements jwk en/de-coding for RSA private keys, fixes JWS tests (and jws-body) --- app/acme.hoon | 184 ++++++++++++++++++++++++-------------------------- 1 file changed, 88 insertions(+), 96 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index c63f9ea15..29a17eefa 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -360,22 +360,57 @@ n+s+(en-base64url (swp 3 n.k)) e+s+(en-base64url (swp 3 e.k)) == - ++ ring !! + ++ ring + |= k=key:rsa + ^- json + :- %o %- my :~ + kty+s+'RSA' + p+s+(en-base64url (swp 3 p.k)) + q+s+(en-base64url (swp 3 q.k)) + n+s+(en-base64url (swp 3 n.k)) + e+s+(en-base64url (swp 3 e.k)) + d+s+(en-base64url (swp 3 d.k)) + == -- ++ de |% ++ pass =, dejs-soft:format %+ ci - |= a=[kty=@t n=(unit @) e=(unit @)] + |= [kty=@t n=(unit @) e=(unit @)] ^- (unit [n=@ux e=@ux]) :: XX RSA pubkey model - (both (bind n.a (cury swp 3)) (bind e.a (cury swp 3))) + (both (bind n (cury swp 3)) (bind e (cury swp 3))) %- ot :~ kty+(su (jest 'RSA')) n+(cu de-base64url so) e+(cu de-base64url so) == - ++ ring !! + ++ ring + =, dejs-soft:format + %+ ci + |= $: kty=@t + p=(unit @) + q=(unit @) + n=(unit @) + e=(unit @) + d=(unit @) + == + ^- (unit key:rsa) + ;: both + (bind p (cury swp 3)) + (bind q (cury swp 3)) + (bind n (cury swp 3)) + (bind e (cury swp 3)) + (bind d (cury swp 3)) + == + %- ot :~ + kty+(su (jest 'RSA')) + p+(cu de-base64url so) + q+(cu de-base64url so) + n+(cu de-base64url so) + e+(cu de-base64url so) + d+(cu de-base64url so) + == -- -- :: @@ -384,6 +419,12 @@ :: XX restrict keys to canonical set (en-base64url (shax `@`(crip `tape`(en-json-sort aor jon)))) :: +++ eor :: explicit order + |= [com=$-([@ @] ?) lit=(list)] + |= [a=* b=*] + ^- ? + (fall (bind (both (find ~[a] lit) (find ~[b] lit)) com) |) +:: ++ from-json =, dejs:format =/ json-purl (su auri:de-purl:html) @@ -441,6 +482,7 @@ ++ jws-body |= [url=purl bod=json] ^- octs + ?> ?=(^ key) =* enc (corl en-base64url (corl crip (cury en-json-sort aor))) =/ payload=cord (enc bod) =/ protect=cord @@ -451,7 +493,6 @@ url+s+(crip (en-purl:html url)) ?^ kid kid+s+u.kid - ?> ?=(^ key) jwk+(pass:en:jwk u.key) == %- (corl as-octt:mimes:html en-json:html) @@ -461,9 +502,8 @@ payload+s+payload :+ %signature %s %- en-base64url - ?> ?=(^ key) - %- ~(sign rs256 u.key) - (rap 3 ~[protect '.' payload]) + %+ swp 3 + (~(sign rs256 u.key) (rap 3 ~[protect '.' payload])) == :: ++ request @@ -544,7 +584,7 @@ test-rsapem test-rs256 test-jwk - :: testjws + test-jws == ?~(out abet ((slog out) abet)) :: @@ -894,9 +934,9 @@ == =/ jk=json :- %o %- my :~ - e+s+'AQAB' kty+s+'RSA' n+s+(rap 3 n) + e+s+'AQAB' == =/ k (need (pass:de:jwk jk)) ;: weld @@ -909,6 +949,7 @@ == :: ++ test-jws + :: rfc7515 appendix 2 ^- wall =/ pt=@t %+ rap 3 @@ -940,68 +981,38 @@ 'CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh' 'BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ' == - =/ p :: (de-base64url pt) - 0x4719.f070.d9b2.3fe7.d5a0.f842.57b6.e083.80c1.9484.ea75.faa7. - f286.556d.c1dd.11e7.5009.d5dc.22ef.6d8e.05c6.739a.dca0.2876.e6a2. - fb09.713c.f634.c9d4.254f.2e3f.3f7c.d001.d06b.13e4.2928.1a2a.3714. - f079.59b3.6c17.a82b.2676.54f7.b5c4.f92e.907e.1a31.b7dd.f078.0748. - fe1f.d1a9.a674.b772.b8a0.6dbb.a40a.4d46.545d.65a6.48eb.10c4.1ce0 - =/ q :: (de-base64url qt) - 0xd759.513f.1303.9270.e3da.f3ba.5e78.5e2a.0781.12d4.7512.b5e5. - d4e5.2f09.cdc3.595e.ed12.b1c8.5782.db78.fa40.704e.7e50.1ebf.979a. - 036c.ebad.ae0f.30f6.0f99.072d.de38.eda5.ab0b.fb78.60c5.bc7b.5256. - a72c.b68c.c001.1eb0.a7c5.9909.60fc.645a.a97a.a042.1bc6.297e.b4a6. - 927a.dcee.dfc7.e93a.5f5d.1499.c1f3.b12c.53f4.32b6.9509.7ec4.03b9 - =/ n :: (de-base64url nt) - :: (mul p q) - 0xa1e9.e5ca.5654.e021.9e6f.606f.4d03.073c.3639.9375.cf2e. - 0c59.84ad.67ab.fcd8.189a.d887.7f8f.7240.c317.9d8b.9a8d.35f8.0af5. - 1657.2c87.86b6.1f49.1922.39f2.ebd3.821b.641f.2a70.96a3.827a.6f6f. - 5c66.838b.6350.3031.55d7.9a6c.9ceb.3a78.a49a.6047.b6c6.10c1.64ed. - e844.f992.0375.c1a5.f85e.0f2c.2c85.055b.c7c4.de9a.cfb9.d49d.9774. - 485a.4ade.fa27.6dfe.e22c.34c8.38fb.bf8d.b301.f768.c6a0.ec8e.67a3. - bdd2.bd6e.df9b.6ebc.9603.134f.9462.bf55.0f2c.d380.42ea.4b59.6977. - 85e4.4f91.ec2f.2584.77b8.19d0.ed53.3f33.c13c.8969.4bdc.9a08.8f8a. - fbb0.56f9.2974.7ce6.1177.dd63.eab6.c597.34d9.8be3.36a1.90cc.2516. - fc77.24f0.e129.be7d.922b.3663.6265.2d8d.ce65.b4c9.e3e2.0a16.f8a1 - =/ d :: (de-base64url dt) - 0x9d73.8a3a.6e54.39e1.50a7.754f.41f4.3473.e768.7992.65c8. - 50f4.4792.5df2.bdc4.e181.18b8.9feb.9d4e.102e.a18b.a4fd.5064.d5f0. - 70dc.3d4e.e31f.ff25.656c.3c3c.e513.5468.058a.895d.563b.943b.d65b. - 2851.d022.5cfa.1a08.13d6.841e.de5e.2f64.539d.3b06.2534.1f47.46ff. - 558a.7246.07a8.f880.0beb.a961.498f.2c51.fa81.755e.fd0c.7df5.377e. - 92e3.ac92.cced.4a9b.3bc7.5db5.4134.714b.4df1.2564.5fde.9f4e.2d98. - 5605.a3e1.bba0.4045.95b2.d927.51a1.c644.06b4.5327.56ea.3bc6.6f21. - 797f.8b2e.abe3.5e02.a0ce.d5d8.255a.c1d8.ee13.521f.6797.377d.2fc8. - 280b.9b43.c6bf.03e5.88ec.bdd3.2c2f.cf3f.1e40.3c96.7ca5.0b9d.0f59. - 627b.7049.e964.1d75.611d.1f57.0045.6c52.7ec3.2b0a.cd69.a471.ae12 - =/ e `@ux`65.537 - =/ k=key:rsa [p q n e d] + =/ jk=json + :- %o %- my :~ + kty+s+'RSA' + n+s+nt + e+s+'AQAB' + d+s+dt + p+s+pt + q+s+qt + == + =/ k=key:rsa (need (ring:de:jwk jk)) =/ hed=json o+(my alg+s+'RS256' ~) + =/ hedt=@t 'eyJhbGciOiJSUzI1NiJ9' =/ lod=json :- %o %- my :~ iss+s+'joe' exp+n+'1300819380' ['http://example.com/is_root' %b &] == - =/ lod-order - =/ keys=(list @t) ['iss' 'exp' 'http://example.com/is_root' ~] - |= [a=* b=*] - =/ fa (find ~[a] keys) - =/ fb (find ~[b] keys) - ?~ fa | - ?~ fb | - (lte u.fa u.fb) - =/ inp=@t - :: %+ swp 3 - %- crip - ;: weld - "eyJhbGciOiJSUzI1NiJ9" - "." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo" - "gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + =/ lodt=@t + %+ rap 3 + :~ 'eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA' + '6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ' == - =/ exp=@t + :: rfc example includes whitespace in json serialization + =/ lodt-ws=@t + %+ rap 3 + :~ 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo' + 'gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ' + == + =/ inp-ws=@t + (rap 3 [hedt '.' lodt-ws ~]) + =/ exp-ws=@t %+ rap 3 :~ 'cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7' 'AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4' @@ -1010,43 +1021,24 @@ 'hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB' 'p0igcN_IoypGlUPQGe77Rw' == + =/ lod-order=(list @t) ['iss' 'exp' 'http://example.com/is_root' ~] ;: weld %- expect-eq !> - :- 'eyJhbGciOiJSUzI1NiJ9' + [jk (ring:en:jwk k)] + %- expect-eq !> + [n.k `@ux`(mul p.k q.k)] + %- expect-eq !> + [d.k `@ux`(~(inv fo (elcm:rsa (dec p.k) (dec q.k))) e.k)] + %- expect-eq !> + :- hedt (en-base64url (crip (en-json-sort aor hed))) %- expect-eq !> - [pt p=(en-base64url p)] + :- lodt + (en-base64url (crip (en-json-sort (eor lte lod-order) lod))) %- expect-eq !> - [p p=(de-base64url pt)] - %- expect-eq !> - [qt q=(en-base64url q)] - %- expect-eq !> - [nt n=(en-base64url n)] - %- expect-eq !> - [dt d=(en-base64url d)] - %- expect-eq !> - [`@ux`n check-math=`n=@ux`(mul p q)] - %- expect-eq !> - [`@ux`d check-math=`d=@ux`(~(inv fo (elcm:rsa (dec p) (dec q))) e)] - %- expect-eq !> - :- exp - =/ sig (~(sign rs256 k) inp) - :: ~& inp+(rip 3 (swp 3 inp)) - :: ~& :* [pt (de-base64url pt) (en-base64url (de-base64url pt))] - :: [qt (de-base64url qt) (en-base64url (de-base64url qt))] - :: [nt (de-base64url nt) (en-base64url (de-base64url nt))] - :: [dt (de-base64url dt) (en-base64url (de-base64url dt))] - :: == - :: ~& ~(pass jwk k) - `@ux`sig - :: (en-base64url sig) - :: expected value has newlines - :: %- expect-eq !> - :: :- %+ weld - :: "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo" - :: "gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" - :: (en-base64url (crip (en-json-sort lod-order lod))) + :- exp-ws + (en-base64url (swp 3 (~(sign rs256 k) inp-ws))) == - -- + -- -- From 37d5c6edbba26dd1800d89577c56e42c3294fd63 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 9 May 2018 23:34:09 -0400 Subject: [PATCH 28/95] adds auras to +spec:asn1 --- app/acme.hoon | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 29a17eefa..6bd3a9f50 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -63,10 +63,10 @@ ++ asn1 :: at least, a little => |% += spec - $% [%int p=@] - [%oct p=@] + $% [%int p=@u] + [%oct p=@ux] [%nul ~] - [%obj p=@] + [%obj p=@ux] [%seq p=(list spec)] == :: From e4014ca3855a4e361d1b7bd6317c4efab907c6a3 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 10 May 2018 23:13:30 -0400 Subject: [PATCH 29/95] adds pkcs8 encoding for RSA public keys --- app/acme.hoon | 109 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/app/acme.hoon b/app/acme.hoon index 6bd3a9f50..36bee6bdb 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -64,6 +64,7 @@ => |% += spec $% [%int p=@u] + [%bit p=@ux] [%oct p=@ux] [%nul ~] [%obj p=@ux] @@ -72,7 +73,8 @@ :: ++ obj :: constants (rfc4055) |% :: - ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 + ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 + ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 -- -- :: @@ -86,6 +88,7 @@ ^- @ ?- pec [%int *] 2 + [%bit *] 3 [%oct *] 4 [%nul *] 5 [%obj *] 6 @@ -99,6 +102,7 @@ ?~ a [0 ~] ?:((lte i.a 127) a [0 a]) :: + [%bit *] [0 (rip 3 p.pec)] :: XX padding [%oct *] (rip 3 p.pec) [%nul *] ~ [%obj *] (rip 3 p.pec) @@ -132,6 +136,7 @@ ?.((gth i.t.a 127) ~ `t.a) ;~(pfix (just `@`2) till) :: + (stag %bit (boss 256 (cook tail ;~(pfix (just `@`3) till)))) :: XX test (stag %oct (boss 256 ;~(pfix (just `@`4) till))) (stag %nul (cold ~ ;~(plug (just `@`5) (just `@`0)))) (stag %obj (boss 256 ;~(pfix (just `@`6) till))) @@ -301,6 +306,61 @@ =((emsa m) (en:rsa s k)) -- :: +++ pkcs8 :: XX other key types? + |% + ++ der + |% + ++ en + |% + ++ pass + |= k=key:rsa + ^- @ux + =; pec + (rep 3 ~(ren asn1 pec)) + :~ %seq + [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] + :- %bit + =; pec + (rep 3 ~(ren asn1 pec)) + [%seq [[%int n.k] [%int e.k] ~]] + == + :: + ++ ring !! + -- + :: + ++ de + |% + ++ pass !! + :: + ++ ring !! + -- + -- + :: + ++ pem + |% + ++ en + |% + ++ pass + |= k=key:rsa + ^- wain + :- '-----BEGIN PUBLIC KEY-----' + =/ a (en:base64 (pass:en:der k)) + |- ^- wain + ?~ a + ['-----END PUBLIC KEY-----' ~] + [(end 3 64 a) $(a (rsh 3 64 a))] + :: + ++ ring !! + -- + :: + ++ de + |% + ++ pass !! + :: + ++ ring !! + -- + -- + -- ++ en-json-sort :: print json |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) :: :: ++apex:en-json:html @@ -582,6 +642,7 @@ test-rsakey test-rsa test-rsapem + test-rsa-pkcs8 test-rs256 test-jwk test-jws @@ -775,6 +836,52 @@ [kpem3 (ring:en:pem:rsa k3)] == :: + ++ test-rsa-pkcs8 + =/ kpem=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MIIEowIBAAKCAQEA2jJp8dgAKy5cSzDE4D+aUbKZsQoMhIWI2IFlE+AO0GCBMig5' + 'qxx2IIAPVIcSi5fjOLtTHnuIZYw+s06qeb8QIKRvkZaIwnA3Lz5UUrxgh96sezdX' + 'CCSG7FndIFskcT+zG00JL+fPRdlPjt1Vg2b3kneo5aAKMIPyOTzcY590UTc+luQ3' + 'HhgSiNF3n5YQh24d3kS2YOUoSXQ13+YRljxNfBgXbV+C7/gO8mFxpkafhmgkIGNe' + 'WlqT9oAIRa+gOx13uPAg+Jb/8lPV9bGaFqGvxvBMp3xUASlzYHiDntcB5MiOPRW6' + 'BoIGI5qDFSYRZBky9crE7WAYgqtPtg21zvxwFwIDAQABAoIBAH0q7GGisj4TIziy' + '6k1lzwXMuaO4iwO+gokIeU5UessIgTSfpK1G73CnZaPstDPF1r/lncHfxZfTQuij' + 'WOHsO7kt+x5+R0ebDd0ZGVA45fsrPrCUR2XRZmDRECuOfTJGA13G7F1B0kJUbfIb' + 'gAGYIK8x236WNyIrntk804SGpTgstCsZ51rK5GL6diZVQbeU806oP1Zhx/ye//NR' + 'mS5G0iil//H41pV5WGomOX0mq9/HYBZqCncqzLki6FFdmXykjz8snvXUR40S8B+a' + '0F/LN+549PSe2dp9h0Hx4HCJOsL9CyCQimqqqE8KPQ4BUz8q3+Mhx1xEyaxIlNH9' + 'ECgo1CECgYEA+mi7vQRzstYJerbhCtaeFrOR/n8Dft7FyFN+5IV7H2omy6gf0zr1' + 'GWjmph5R0sMPgL8uVRGANUrkuZZuCr35iY6zQpdCFB4D9t+zbTvTmrxt2oVaE16/' + 'dIJ6b8cHzR2QrEh8uw5/rEKzWBCHNS8FvXHPvXvnacTZ5LZRK0ssshECgYEA3xGQ' + 'nDlmRwyVto/1DQMLnjIMazQ719qtCO/pf4BHeqcDYnIwYb5zLBj2nPV8D9pqM1pG' + 'OVuOgcC9IimrbHeeGwp1iSTH4AvxDIj6Iyrmbz2db3lGdHVk9xLvTiYzn2KK2sYx' + 'mFl3DRBFutFQ2YxddqHbE3Ds96Y/uRXhqj7I16cCgYEA1AVNwHM+i1OS3yZtUUH6' + 'xPnySWu9x/RTvpSDwnYKk8TLaHDH0Y//6y3Y7RqK6Utjmv1E+54/0d/B3imyrsG/' + 'wWrj+SQdPO9VJ/is8XZQapnU4cs7Q19b+AhqJq58un2n+1e81J0oGPC47X3BHZTc' + '5VSyMpvwiqu0WmTMQT37cCECgYACMEbt8XY6bjotz13FIemERNNwXdPUe1XFR61P' + 'ze9lmavj1GD7JIY2wYvx4Eq2URtHo7QarfZI+Z4hbq065DWN6F1c2hqH7TYRPGrP' + '24TlRIJ97H+vdtNlxS7J4oARKUNZgCZOa1pKq4UznwgfCkyEdHQUzb/VcjEf3MIZ' + 'DIKl8wKBgBrsIjiDvpkfnpmQ7fehEJIi+V4SGskLxFH3ZTvngFFoYry3dL5gQ6mF' + 'sDfrn4igIcEy6bMpJQ3lbwStyzcWZLMJgdI23FTlPXTEG7PclZSuxBpQpvg3MiVO' + 'zqVTrhnY+TemcScSx5O6f32aDfOUWWCzmw/gzvJxUYlJqjqd7dlT' + '-----END RSA PRIVATE KEY-----' + == + =/ pub=wain + :~ '-----BEGIN PUBLIC KEY-----' + 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2jJp8dgAKy5cSzDE4D+a' + 'UbKZsQoMhIWI2IFlE+AO0GCBMig5qxx2IIAPVIcSi5fjOLtTHnuIZYw+s06qeb8Q' + 'IKRvkZaIwnA3Lz5UUrxgh96sezdXCCSG7FndIFskcT+zG00JL+fPRdlPjt1Vg2b3' + 'kneo5aAKMIPyOTzcY590UTc+luQ3HhgSiNF3n5YQh24d3kS2YOUoSXQ13+YRljxN' + 'fBgXbV+C7/gO8mFxpkafhmgkIGNeWlqT9oAIRa+gOx13uPAg+Jb/8lPV9bGaFqGv' + 'xvBMp3xUASlzYHiDntcB5MiOPRW6BoIGI5qDFSYRZBky9crE7WAYgqtPtg21zvxw' + 'FwIDAQAB' + '-----END PUBLIC KEY-----' + == + =/ k=key:rsa + (need (ring:de:pem:rsa kpem)) + %- expect-eq !> + [pub (pass:en:pem:pkcs8 k)] + :: ++ test-rsa =/ k1=key:rsa =/ p `@ux`61 From e96d0e77d59e10a4be5ce3229d7844c790ab847e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 11 May 2018 00:53:10 -0400 Subject: [PATCH 30/95] adds pkcs10 encoding for Certificate Signing Requests --- app/acme.hoon | 180 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 4 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 36bee6bdb..8dcae9496 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -69,12 +69,19 @@ [%nul ~] [%obj p=@ux] [%seq p=(list spec)] + [%set p=(list spec)] :: XX actual set + [%con p=[p=? q=@udC] q=(list @)] :: XX manual == :: - ++ obj :: constants (rfc4055) - |% :: + ++ obj :: oid constants + |% :: rfc4055 ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 + ++ rsa-sha-256 0xb.0101.0df7.8648.862a :: 1.2.840.113549.1.1.11 + :: rfc2985 + ++ csr-ext 0xe.0901.0df7.8648.862a :: 1.2.840.113549.1.9.14 + :: rfc3280 + ++ sub-alt 0x11.1d55 :: 2.5.29.17 -- -- :: @@ -93,6 +100,8 @@ [%nul *] 5 [%obj *] 6 [%seq *] 48 :: (con 0x20 16) + [%set *] 49 :: (con 0x20 17) + [%con *] :(con q.p.pec 0x80 ?:(p.p.pec 0 0x20)) == :: ++ lem :: element bytes @@ -102,7 +111,7 @@ ?~ a [0 ~] ?:((lte i.a 127) a [0 a]) :: - [%bit *] [0 (rip 3 p.pec)] :: XX padding + [%bit *] [0 (rip 3 p.pec)] :: XX padding [%oct *] (rip 3 p.pec) [%nul *] ~ [%obj *] (rip 3 p.pec) @@ -110,8 +119,16 @@ [%seq *] %- zing |- ^- (list (list @)) ?~ p.pec ~ - :- ren:.(pec i.p.pec) + :- ren(pec i.p.pec) $(p.pec t.p.pec) + :: + [%set *] %- zing :: XX tap/sort + |- ^- (list (list @)) + ?~ p.pec ~ + :- ren(pec i.p.pec) + $(p.pec t.p.pec) + :: + [%con *] q.pec == :: ++ len :: length bytes @@ -145,6 +162,24 @@ %+ sear |=(a=(list @) (rust a (star decode))) :: XX plus? curr? ;~(pfix (just `@`48) till) + :: + %+ stag %set + %+ sear + |=(a=(list @) (rust a (star decode))) :: XX plus? curr? + ;~(pfix (just `@`49) till) + :: + %+ stag %con + ;~ plug + %+ sear + |= a=@ + ^- (unit [? @udC]) + ?. =(1 (cut 0 [7 1] a)) ~ + :+ ~ + =(1 (cut 0 [5 1] a)) + (dis 0x1f a) + next + till + == == :: ++ till :: len-prefixed bytes @@ -361,6 +396,74 @@ -- -- -- +:: +++ pkcs10 :: XX other key types? + |% + ++ der + |% + ++ en + |= [k=key:rsa hot=(list (list @t))] + ^- @ux + =; pec + (rep 3 ~(ren asn1 pec)) + =/ cer=spec:asn1 + :~ %seq + [%int 0] + [%seq ~] + :: XX deduplicate with +pass:en:der:pkcs8 + :~ %seq + [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] + :- %bit + =; pec + (rep 3 ~(ren asn1 pec)) + [%seq [[%int n.k] [%int e.k] ~]] + == + :+ %con [| 0] + =- ~(ren asn1 -) + :~ %seq + [%obj csr-ext:obj:asn1] + :~ %set + :~ %seq + :~ %seq + [%obj sub-alt:obj:asn1] + :- %oct + =; pec + (rep 3 ~(ren asn1 pec)) + :- %seq + %+ turn hot + |=(h=(list @t) [%con [& 2] (rip 3 (need (en-host h)))]) + == + == + == + == + == + :: + ^- spec:asn1 + :~ %seq + cer + [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] + [%bit (swp 3 (~(sign rs256 k) (rep 3 ~(ren asn1 cer))))] + == + :: + ++ de !! + -- + :: + ++ pem + |% + ++ en + |= [k=key:rsa hot=(list (list @t))] + ^- wain + :- '-----BEGIN CERTIFICATE REQUEST-----' + =/ a (en:base64 (en:der k hot)) + |- ^- wain + ?~ a + ['-----END CERTIFICATE REQUEST-----' ~] + [(end 3 64 a) $(a (rsh 3 64 a))] + :: + ++ de !! + -- + -- +:: ++ en-json-sort :: print json |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) :: :: ++apex:en-json:html @@ -485,6 +588,17 @@ ^- ? (fall (bind (both (find ~[a] lit) (find ~[b] lit)) com) |) :: +++ en-host + |= hot=(list @t) + ^- (unit @t) + =| out=(list @t) + ?~ hot ~ + :- ~ + |- ^- @t + ?~ t.hot + (rap 3 [i.hot out]) + $(out ['.' i.hot out], hot t.hot) +:: ++ from-json =, dejs:format =/ json-purl (su auri:de-purl:html) @@ -646,6 +760,7 @@ test-rs256 test-jwk test-jws + test-csr == ?~(out abet ((slog out) abet)) :: @@ -1146,6 +1261,63 @@ :- exp-ws (en-base64url (swp 3 (~(sign rs256 k) inp-ws))) == + :: + ++ test-csr + =/ kpem=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MIIEowIBAAKCAQEA2jJp8dgAKy5cSzDE4D+aUbKZsQoMhIWI2IFlE+AO0GCBMig5' + 'qxx2IIAPVIcSi5fjOLtTHnuIZYw+s06qeb8QIKRvkZaIwnA3Lz5UUrxgh96sezdX' + 'CCSG7FndIFskcT+zG00JL+fPRdlPjt1Vg2b3kneo5aAKMIPyOTzcY590UTc+luQ3' + 'HhgSiNF3n5YQh24d3kS2YOUoSXQ13+YRljxNfBgXbV+C7/gO8mFxpkafhmgkIGNe' + 'WlqT9oAIRa+gOx13uPAg+Jb/8lPV9bGaFqGvxvBMp3xUASlzYHiDntcB5MiOPRW6' + 'BoIGI5qDFSYRZBky9crE7WAYgqtPtg21zvxwFwIDAQABAoIBAH0q7GGisj4TIziy' + '6k1lzwXMuaO4iwO+gokIeU5UessIgTSfpK1G73CnZaPstDPF1r/lncHfxZfTQuij' + 'WOHsO7kt+x5+R0ebDd0ZGVA45fsrPrCUR2XRZmDRECuOfTJGA13G7F1B0kJUbfIb' + 'gAGYIK8x236WNyIrntk804SGpTgstCsZ51rK5GL6diZVQbeU806oP1Zhx/ye//NR' + 'mS5G0iil//H41pV5WGomOX0mq9/HYBZqCncqzLki6FFdmXykjz8snvXUR40S8B+a' + '0F/LN+549PSe2dp9h0Hx4HCJOsL9CyCQimqqqE8KPQ4BUz8q3+Mhx1xEyaxIlNH9' + 'ECgo1CECgYEA+mi7vQRzstYJerbhCtaeFrOR/n8Dft7FyFN+5IV7H2omy6gf0zr1' + 'GWjmph5R0sMPgL8uVRGANUrkuZZuCr35iY6zQpdCFB4D9t+zbTvTmrxt2oVaE16/' + 'dIJ6b8cHzR2QrEh8uw5/rEKzWBCHNS8FvXHPvXvnacTZ5LZRK0ssshECgYEA3xGQ' + 'nDlmRwyVto/1DQMLnjIMazQ719qtCO/pf4BHeqcDYnIwYb5zLBj2nPV8D9pqM1pG' + 'OVuOgcC9IimrbHeeGwp1iSTH4AvxDIj6Iyrmbz2db3lGdHVk9xLvTiYzn2KK2sYx' + 'mFl3DRBFutFQ2YxddqHbE3Ds96Y/uRXhqj7I16cCgYEA1AVNwHM+i1OS3yZtUUH6' + 'xPnySWu9x/RTvpSDwnYKk8TLaHDH0Y//6y3Y7RqK6Utjmv1E+54/0d/B3imyrsG/' + 'wWrj+SQdPO9VJ/is8XZQapnU4cs7Q19b+AhqJq58un2n+1e81J0oGPC47X3BHZTc' + '5VSyMpvwiqu0WmTMQT37cCECgYACMEbt8XY6bjotz13FIemERNNwXdPUe1XFR61P' + 'ze9lmavj1GD7JIY2wYvx4Eq2URtHo7QarfZI+Z4hbq065DWN6F1c2hqH7TYRPGrP' + '24TlRIJ97H+vdtNlxS7J4oARKUNZgCZOa1pKq4UznwgfCkyEdHQUzb/VcjEf3MIZ' + 'DIKl8wKBgBrsIjiDvpkfnpmQ7fehEJIi+V4SGskLxFH3ZTvngFFoYry3dL5gQ6mF' + 'sDfrn4igIcEy6bMpJQ3lbwStyzcWZLMJgdI23FTlPXTEG7PclZSuxBpQpvg3MiVO' + 'zqVTrhnY+TemcScSx5O6f32aDfOUWWCzmw/gzvJxUYlJqjqd7dlT' + '-----END RSA PRIVATE KEY-----' + == + =/ k=key:rsa + (need (ring:de:pem:rsa kpem)) + :: generated with openssl, certbot style + =/ csr-pem=wain + :~ '-----BEGIN CERTIFICATE REQUEST-----' + 'MIICezCCAWMCAQAwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANoy' + 'afHYACsuXEswxOA/mlGymbEKDISFiNiBZRPgDtBggTIoOascdiCAD1SHEouX4zi7' + 'Ux57iGWMPrNOqnm/ECCkb5GWiMJwNy8+VFK8YIferHs3VwgkhuxZ3SBbJHE/sxtN' + 'CS/nz0XZT47dVYNm95J3qOWgCjCD8jk83GOfdFE3PpbkNx4YEojRd5+WEIduHd5E' + 'tmDlKEl0Nd/mEZY8TXwYF21fgu/4DvJhcaZGn4ZoJCBjXlpak/aACEWvoDsdd7jw' + 'IPiW//JT1fWxmhahr8bwTKd8VAEpc2B4g57XAeTIjj0VugaCBiOagxUmEWQZMvXK' + 'xO1gGIKrT7YNtc78cBcCAwEAAaA2MDQGCSqGSIb3DQEJDjEnMCUwIwYDVR0RBBww' + 'GoINem9kLnVyYml0Lm9yZ4IJem9kLnVyYml0MA0GCSqGSIb3DQEBCwUAA4IBAQCu' + 'HdUqIlW8w7G7l3YxXfb0fn1HxD7zHf3QpNqDYZuDq958OhJNXYJ9EjiHBBEW5ySg' + 'e7vyaaWh6UcVIu/RYFGbyVupNVbp4aS4U1LEEiqMQ6vQQnlSt7hVMi04bhf6X6jd' + 'kkTJIB5OlmNh5z/mjvlIOyOCeitK5IMrStsUPE5F8OynMuzmBKq318LiwImO41Fu' + 'S1M6rgPnvoZeqShLxnJduMcu7awHQ0tn2FmjwBpU713/tmNjtCLYYoBxsHM2ptxd' + 'G3zcMSCDZ/CLXWoktkULdWNDED8meCKWQJxYuHjxY4JPIzIVdVN50xRcZEV7Z80l' + 'bPcFaE8op3e2hIxzqi1t' + '-----END CERTIFICATE REQUEST-----' + == + =/ hot1 /org/urbit/zod + =/ hot2 /urbit/zod + %- expect-eq !> + :- csr-pem + (en:pem:pkcs10 k [hot1 hot2 ~]) -- -- From 55b33d8578bb206625e3b3ec99fe72875ed43d70 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 11 May 2018 11:03:56 -0400 Subject: [PATCH 31/95] random cleanup --- app/acme.hoon | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 8dcae9496..054ba8935 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -141,6 +141,7 @@ :: ++ decode %+ cook |*(a=* `spec:asn1`a) + :: ^- $-(nail (like spec:asn1)) ;~ pose %+ stag %int %+ bass 256 @@ -678,8 +679,8 @@ %- en-base64url %+ swp 3 (~(sign rs256 u.key) (rap 3 ~[protect '.' payload])) - == -:: + == +:: ++ request |= [wir=wire url=purl bod=(unit json)] =/ lod @@ -753,7 +754,7 @@ ;: weld test-base64 test-asn1 - test-rsakey + :: test-rsakey test-rsa test-rsapem test-rsa-pkcs8 @@ -1135,7 +1136,7 @@ %- expect-eq !> [emsa1 `@ux`(~(emsa rs256 k1) inp1)] %- expect-eq !> - [& (~(verify rs256 k2) sig inp2)] + [& (~(verify rs256 k2) sig inp2)] %- expect-eq !> [exp2 sig] :: save kpem2 to private.pem @@ -1172,7 +1173,6 @@ :: ++ test-jws :: rfc7515 appendix 2 - ^- wall =/ pt=@t %+ rap 3 :~ '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi' From 854f9aace4bc7f8ab3f387ad71094e5c695b4c6d Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 15 May 2018 00:26:59 -0400 Subject: [PATCH 32/95] adds detailed state structures, parsers, control flow to :acme --- app/acme.hoon | 334 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 274 insertions(+), 60 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 054ba8935..bfff1eebc 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -432,7 +432,7 @@ (rep 3 ~(ren asn1 pec)) :- %seq %+ turn hot - |=(h=(list @t) [%con [& 2] (rip 3 (need (en-host h)))]) + |=(h=(list @t) [%con [& 2] (rip 3 (en-host h))]) == == == @@ -591,58 +591,124 @@ :: ++ en-host |= hot=(list @t) - ^- (unit @t) + ^- @t =| out=(list @t) - ?~ hot ~ - :- ~ + ?> ?=(^ hot) |- ^- @t ?~ t.hot (rap 3 [i.hot out]) $(out ['.' i.hot out], hot t.hot) :: -++ from-json +++ grab =, dejs:format - =/ json-purl (su auri:de-purl:html) - %- ot - :~ ['newAccount' json-purl] - ['newNonce' json-purl] - ['newOrder' json-purl] - ['revokeCert' json-purl] - ['keyChange' json-purl] - == + |% + ++ json-purl (su auri:de-purl:html) + :: + ++ directory + %- ot + :~ ['newAccount' json-purl] + ['newNonce' json-purl] + ['newOrder' json-purl] + ['revokeCert' json-purl] + ['keyChange' json-purl] + == + :: + ++ acct + %- ot + :~ ['id' no] + ['createdAt' so] :: XX (su iso-8601) + ['status' so] + :: ignore key, contact, initialIp + == + :: + ++ order + %- ot + :~ ['authorizations' (ar json-purl)] + ['finalize' json-purl] + ['expires' so] :: XX (su iso-8601) + == + :: + ++ auth + => |% + ++ iden + |= [typ=@t hot=host] + ?>(&(?=(%dns typ) ?=([%& *] hot)) p.hot) + :: + ++ trial + |= a=(list [typ=@t sas=@t url=purl tok=@t]) + ^+ ?>(?=(^ a) i.a) + =/ b + (skim a |=([typ=@t *] ?=(%http-01 typ))) + ?>(?=(^ b) i.b) + -- + %- ot + :~ ['identifier' (cu iden (ot type+so value+(su thos:de-purl:html) ~))] + ['status' so] + ['expires' so] :: XX (su iso-8601) + :- 'challenges' + (cu trial (ar (ot type+so status+so url+json-purl token+so ~))) + == + :: + ++ error + %- ot + :~ ['type' so] + ['detail' so] + == + -- -- :: :::: acme state :: |% -+= move [bone card] -+= card $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] - == -:: -+= nonce @t -:: ++= move [bone card] :: ++= card :: + $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] :: + [%well wire path (unit mime)] :: + == :: += directory :: ACME v2 $: reg/purl :: newAccount non/purl :: newNonce der/purl :: newOrder rev/purl :: revokeCert rek/purl :: keyChange - == -:: -+= state - $: dir=directory - non=nonce - kid=(unit @t) - key=(unit key:rsa) - == --- + == :: ++= acct :: account + [key=key:rsa reg=(unit [wen=@t kid=@t])] :: XX wen=@da ++= turf (list @t) :: domain ++= trial :: challenge + $% [%http cal=purl tok=@t sas=?(%recv %pend %auth)] :: http-only + == :: ++= auth :: authorization + $% [%0 aut=purl] :: received + [%1 aut=purl dom=turf cal=trial] :: in-progress + == :: ++= order :: certificate order + $% [%0 dom=(list turf)] :: initialized + [%1 dom=(list turf) exp=@t fin=purl aut=(map @ud auth)] :: XX exp=@da + [%2 dom=(list turf) exp=@t fin=purl csr=@ux] :: cert requested + == :: ++= config :: finalized config + [key=key:rsa exp=@da cer=@ux] :: ++= history :: isn't over + $: act=(list acct) :: + der=(list order) :: + fig=(list (pair (list turf) config)) :: + == :: ++= acme :: + $: bas=purl :: service base url + dir=directory :: service urls + act=acct :: service account + non=@t :: nonce from last + der=(map @ud order) :: active orders + liv=(map (list turf) config) :: active config + hit=history :: a foreign country + == :: +-- :: :: :::: acme app :: -=/ url=tape "https://acme-staging-v02.api.letsencrypt.org/directory" -=/ bas=purl (scan url auri:de-purl:html) =| mov=(list move) -|_ [bow=bowl:gall state] +|_ [bow=bowl:gall acme] :: ++ this . :: XX #712 :: @@ -657,7 +723,7 @@ ++ jws-body |= [url=purl bod=json] ^- octs - ?> ?=(^ key) + :: ?> ?=(^ key.act) =* enc (corl en-base64url (corl crip (cury en-json-sort aor))) =/ payload=cord (enc bod) =/ protect=cord @@ -666,9 +732,9 @@ alg+s+'RS256' nonce+s+non url+s+(crip (en-purl:html url)) - ?^ kid - kid+s+u.kid - jwk+(pass:en:jwk u.key) + ?^ reg.act + kid+s+kid.u.reg.act + jwk+(pass:en:jwk key.act) == %- (corl as-octt:mimes:html en-json:html) ^- json @@ -678,7 +744,7 @@ :+ %signature %s %- en-base64url %+ swp 3 - (~(sign rs256 u.key) (rap 3 ~[protect '.' payload])) + (~(sign rs256 key.act) (rap 3 ~[protect '.' payload])) == :: ++ request @@ -690,38 +756,107 @@ [%post hed `(jws-body url u.bod)] (emit [%hiss wir [~ ~] %httr %hiss url lod]) :: -++ initialize - =? key ?=(~ key) `(new-key:rsa 2.048 eny.bow) - (request /acme/init/(scot %p our.bow) bas ~) +++ directory + (request /acme/dir/(scot %p our.bow) bas ~) :: ++ nonce - (request /acme/non/(scot %p our.bow) non.dir ~) + |= nex=wire + ^+ this + ?> |(?=(~ nex) ?=([%next *] nex)) + (request (weld `wire`/acme/non nex) non.dir ~) :: ++ register - %^ request /acme/reg/(scot %p our.bow) + %^ request(reg.act ~) /acme/reg/(scot %p our.bow) reg.dir `[%o (my [['termsOfServiceAgreed' b+&] ~])] :: -++ authorize - :+ request - der.dir ::aut.dir +++ order + ^+ this + =< q + %^ spin + (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %0 *] a))) + this + |= [[i=@ud der=^order] b=_this] + ?> ?=([%0 *] der) + :- ~ + ^+ b + %^ request:b /acme/der/(scot %ud i) + der.dir + :- ~ ^- json :- %o %- my :~ - resource+s+'new-authz' - :- %identifier - :- %o %- my :~ - type+s+'dns' - value+s+(crip (welp +:(scow %p our.bow) ".urbit.org")) - == + :- %identifiers + :- %a + %+ turn + dom.der + |=(a=turf [%o (my type+s+'dns' value+s+(en-host a) ~)]) == :: +++ authorize + ^+ this + =/ aut=(list (trel @ud @ud purl)) + %- zing + %+ turn + (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %1 *] a))) + |= [ider=@ud der=^order] + ?> ?=([%1 *] der) + %+ turn + ~(tap by aut.der) + |= [i=@ud aut=auth] + ?> ?=([%0 *] aut) + [i ider aut.aut] + =< q + %^ spin + aut + this + |= [[i=@ud ider=@ud aut=purl] b=_this] + ^+ [~ b] + [~ (request:b /acme/aut/(scot %ud i)/der/(scot %ud ider) aut ~)] +:: +++ challenge + ^+ this + =/ cal=(list (trel @ud @ud trial)) + %- zing + %+ turn + (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %1 *] a))) + |= [ider=@ud der=^order] + ?> ?=([%1 *] der) + %+ turn + ~(tap by aut.der) + |= [i=@ud aut=auth] + ?> ?=([%1 *] aut) + [i ider cal.aut] + =< q + %^ spin + cal + this + |= [[i=@ud ider=@ud cal=trial] b=_this] + =/ mim + :- /text/plain + %- as-octs:mimes:html + (rap 3 [tok.cal '.' (thumbprint (pass:en:jwk key.act)) ~]) + =. b %- emit:b + :+ %well + /acme/wel/(scot %ud i)/der/(scot %ud ider) + [/acme-challenge/[tok.cal] `mim] + =. sas.cal %pend + :: save cal to aut.der + :- ~ + %^ request:b + /acme/cal/(scot %ud i)/der/(scot %ud ider) + cal.cal + `[%o ~] +:: ++ poke-noun |= a=* ^- (quip move _this) ?+ a ~& +<+.this [~ this] - %init abet:initialize - %test test + %init abet:init + %order abet:order + %auth abet:authorize + %trial abet:challenge + %test test == :: ++ sigh-httr @@ -729,20 +864,99 @@ ^- (quip move _this) ~& [wir rep] ?> ?=([%acme ^] wir) + =/ ron (skim q.rep |=((pair @t @t) ?=(%replay-nonce p))) + =? non ?=(^ ron) q.i.ron ?. ?=(%2 (div p.rep 100)) ~& %lack-of-success - [~ +>] + =/ bod=[typ=@t det=@t] + (error:grab (need (de-json:html q:(need r.rep)))) + ?: =('urn:ietf:params:acme:error:badNonce' typ.bod) + =/ nex=wire + ?. ?=(?(%der %aut %cal) i.t.wir) + ~ + /next/[i.t.wir] + abet:(nonce nex) + [~ this] + :: challenge is not pending ?+ i.t.wir !! - %init - =< abet:nonce - this(dir (from-json (need (de-json:html q:(need r.rep))))) - :: + %dir + =< abet:(nonce ~) + =/ bod=^directory + (directory:grab (need (de-json:html q:(need r.rep)))) + this(dir bod) + :: %non - =< abet:register - this(non q:(head (skim q.rep |=((pair @t @t) ?=(%replay-nonce p))))) + =< abet + ?. ?=([%next ^] t.t.wir) + register + ?+ i.t.t.t.wir this + %der order + %aut authorize + %cal challenge + == + :: + %reg + =< abet:order + =/ bod=[id=@t wen=@t sas=@t] :: XX @da + (acct:grab (need (de-json:html q:(need r.rep)))) + =/ loc=@t + q:(head (skim q.rep |=((pair @t @t) ?=(%location p)))) + ?> ?=(%valid sas.bod) + this(reg.act `[wen.bod loc]) + :: + %der + =< abet:authorize + =/ i=@ud (slav %ud (head t.t.wir)) + =/ rod=^order (~(got by der) i) + ?> ?=([%0 *] rod) + =/ bod=[aut=(list purl) fin=purl exp=@t] + (order:grab (need (de-json:html q:(need r.rep)))) + =/ aut %- ~(gas by *(map @ud auth)) + (spun aut.bod |=([a=purl b=@ud] [[b %0 a] +(b)])) + =/ dor=^order [%1 dom.rod exp.bod fin.bod aut] + this(der (~(put by der) i dor)) + :: + %aut + =< abet:challenge + ?> ?=([@ %der @ *] t.t.wir) + =/ i (slav %ud i.t.t.wir) + =/ ider (slav %ud i.t.t.t.t.wir) + =/ rod=^order (~(got by der) ider) + ?> ?=([%1 *] rod) + =/ aut=auth (~(got by aut.rod) i) + ?> ?=([%0 *] aut) + =/ bod=[dom=turf sas=@t exp=@t cal=[typ=@t sas=@t url=purl tok=@t]] + (auth:grab (need (de-json:html q:(need r.rep)))) + =/ cal=trial + [%http url.cal.bod tok.cal.bod %recv] :: XX parse tok? + =/ tau=auth [%1 aut.aut dom.bod cal] + =. rod rod(aut (~(put by aut.rod) i tau)) + this(der (~(put by der) ider rod)) + :: + %cal + abet:this :: XX del .well-known, make csr, poll order == :: -++ prep _[~ this] +++ prep + |= old=(unit acme) + ?~ old + abet:init + [~ this(+<+ u.old)] +:: +++ init + =/ key=key:rsa + =| i=@ + |- ^- key:rsa + =/ k (new-key:rsa 2.048 eny.bow) + =/ m (met 0 n.k) + ?: =(0 (mod m 8)) k + ~& [%init i m] + $(i +(i), eny.bow +(eny.bow)) + =/ dom=turf /org/urbit/(crip +:(scow %p our.bow)) + =/ dor=^order [%0 [dom ~]] + =/ url + (de-purl:html 'https://acme-staging-v02.api.letsencrypt.org/directory') + directory(bas (need url), act `acct`[key ~], der [[0 dor] ~ ~]) :: ++ test =, tester:tester From 09d61ca3d7a1a6c1ebb0c33ee3be3569b4cc4031 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 15 May 2018 16:52:54 -0400 Subject: [PATCH 33/95] finishes basic ACMEv2 flow, refactors multiple event queuing --- app/acme.hoon | 246 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 187 insertions(+), 59 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index bfff1eebc..502e7b98f 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -626,6 +626,16 @@ :~ ['authorizations' (ar json-purl)] ['finalize' json-purl] ['expires' so] :: XX (su iso-8601) + ['status' so] + == + :: + ++ final-order + %- ot + :~ ['authorizations' (ar json-purl)] + ['finalize' json-purl] + ['expires' so] :: XX (su iso-8601) + ['status' so] + ['certificate' json-purl] == :: ++ auth @@ -645,8 +655,15 @@ :~ ['identifier' (cu iden (ot type+so value+(su thos:de-purl:html) ~))] ['status' so] ['expires' so] :: XX (su iso-8601) - :- 'challenges' - (cu trial (ar (ot type+so status+so url+json-purl token+so ~))) + ['challenges' (cu trial (ar challenge))] + == + :: + ++ challenge + %- ot + :~ ['type' so] + ['status' so] + ['url' json-purl] + ['token' so] == :: ++ error @@ -672,8 +689,7 @@ rev/purl :: revokeCert rek/purl :: keyChange == :: -+= acct :: account - [key=key:rsa reg=(unit [wen=@t kid=@t])] :: XX wen=@da ++= acct [key=key:rsa reg=(unit [wen=@t kid=@t])] :: account XX wen=@da += turf (list @t) :: domain += trial :: challenge $% [%http cal=purl tok=@t sas=?(%recv %pend %auth)] :: http-only @@ -684,11 +700,10 @@ == :: += order :: certificate order $% [%0 dom=(list turf)] :: initialized - [%1 dom=(list turf) exp=@t fin=purl aut=(map @ud auth)] :: XX exp=@da - [%2 dom=(list turf) exp=@t fin=purl csr=@ux] :: cert requested + [%1 dom=(list turf) exp=@t der=purl fin=purl aut=(map @ud auth)] :: XX exp=@da + [%2 dom=(list turf) exp=@t der=purl fin=purl key=key:rsa csr=@ux] :: cert requested == :: -+= config :: finalized config - [key=key:rsa exp=@da cer=@ux] :: ++= config [key=key:rsa exp=@da cer=wain] :: finalized config += history :: isn't over $: act=(list acct) :: der=(list order) :: @@ -717,6 +732,10 @@ ~& [%emit car] this(mov [[ost.bow car] mov]) :: +++ emil + |= rac=(list card) + q:(spin rac this |=([a=card b=_this] [~ (emit:b a)])) +:: ++ abet [(flop mov) this(mov ~)] :: @@ -749,38 +768,38 @@ :: ++ request |= [wir=wire url=purl bod=(unit json)] + ^- card =/ lod ?~ bod [%get ~ ~] =/ hed (my content-type+['application/jose+json' ~] ~) [%post hed `(jws-body url u.bod)] - (emit [%hiss wir [~ ~] %httr %hiss url lod]) + [%hiss wir [~ ~] %httr %hiss url lod] :: ++ directory - (request /acme/dir/(scot %p our.bow) bas ~) + (emit (request /acme/dir/(scot %p our.bow) bas ~)) :: ++ nonce |= nex=wire ^+ this ?> |(?=(~ nex) ?=([%next *] nex)) - (request (weld `wire`/acme/non nex) non.dir ~) + (emit (request (weld `wire`/acme/non nex) non.dir ~)) :: ++ register - %^ request(reg.act ~) /acme/reg/(scot %p our.bow) + %- emit(reg.act ~) + %^ request /acme/reg/(scot %p our.bow) reg.dir `[%o (my [['termsOfServiceAgreed' b+&] ~])] :: ++ order ^+ this - =< q - %^ spin - (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %0 *] a))) - this - |= [[i=@ud der=^order] b=_this] + %- emil + %+ turn + (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %0 *] a))) + |= [i=@ud der=^order] + ^- card ?> ?=([%0 *] der) - :- ~ - ^+ b - %^ request:b /acme/der/(scot %ud i) + %^ request /acme/der/(scot %ud i) der.dir :- ~ ^- json @@ -794,6 +813,7 @@ :: ++ authorize ^+ this + %- emil =/ aut=(list (trel @ud @ud purl)) %- zing %+ turn @@ -805,16 +825,14 @@ |= [i=@ud aut=auth] ?> ?=([%0 *] aut) [i ider aut.aut] - =< q - %^ spin - aut - this - |= [[i=@ud ider=@ud aut=purl] b=_this] - ^+ [~ b] - [~ (request:b /acme/aut/(scot %ud i)/der/(scot %ud ider) aut ~)] + %+ turn aut + |= [i=@ud ider=@ud aut=purl] + ^- card + (request /acme/aut/(scot %ud i)/der/(scot %ud ider) aut ~) :: ++ challenge ^+ this + %- emil =/ cal=(list (trel @ud @ud trial)) %- zing %+ turn @@ -826,26 +844,54 @@ |= [i=@ud aut=auth] ?> ?=([%1 *] aut) [i ider cal.aut] - =< q - %^ spin - cal - this - |= [[i=@ud ider=@ud cal=trial] b=_this] - =/ mim - :- /text/plain - %- as-octs:mimes:html - (rap 3 [tok.cal '.' (thumbprint (pass:en:jwk key.act)) ~]) - =. b %- emit:b - :+ %well - /acme/wel/(scot %ud i)/der/(scot %ud ider) - [/acme-challenge/[tok.cal] `mim] - =. sas.cal %pend - :: save cal to aut.der - :- ~ - %^ request:b - /acme/cal/(scot %ud i)/der/(scot %ud ider) - cal.cal - `[%o ~] + %- zing + %+ turn cal + |= [i=@ud ider=@ud cal=trial] + ^- (list card) + :~ :^ %well + /acme/wel/(scot %ud i)/der/(scot %ud ider) + /acme-challenge/[tok.cal] + :+ ~ + /text/plain + %- as-octs:mimes:html + (rap 3 [tok.cal '.' (thumbprint (pass:en:jwk key.act)) ~]) + :: + %^ request + /acme/cal/(scot %ud i)/der/(scot %ud ider) + cal.cal + `[%o ~] + == +:: +++ finalize + ^+ this + %- emil + =/ csr=(list (trel @ud purl @ux)) + %+ turn + (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %2 *] a))) + |= [i=@ud der=^order] + ?> ?=([%2 *] der) + [i fin.der csr.der] + %+ turn csr + |= [i=@ud fin=purl csr=@ux] + ^- card + %^ request + /acme/fin/(scot %ud i) + fin + `[%o (my csr+s+(en-base64url csr) ~)] +:: +++ poll-order + ^+ this + %- emil + =/ url=(list (pair @ud purl)) + %+ turn + (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %2 *] a))) + |= [i=@ud der=^order] + ?> ?=([%2 *] der) + [i der.der] + %+ turn url + |= [i=@ud der=purl] + ^- card + (request /acme/por/(scot %ud i) der ~) :: ++ poke-noun |= a=* @@ -856,6 +902,8 @@ %order abet:order %auth abet:authorize %trial abet:challenge + %final abet:finalize + %poll abet:poll-order %test test == :: @@ -876,8 +924,9 @@ ~ /next/[i.t.wir] abet:(nonce nex) + :: XX challenge is not pending + :: XX order can't be finalized [~ this] - :: challenge is not pending ?+ i.t.wir !! %dir =< abet:(nonce ~) @@ -909,11 +958,14 @@ =/ i=@ud (slav %ud (head t.t.wir)) =/ rod=^order (~(got by der) i) ?> ?=([%0 *] rod) - =/ bod=[aut=(list purl) fin=purl exp=@t] + =/ loc=@t + q:(head (skim q.rep |=((pair @t @t) ?=(%location p)))) + =/ url=purl (need (de-purl:html loc)) + =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] (order:grab (need (de-json:html q:(need r.rep)))) =/ aut %- ~(gas by *(map @ud auth)) (spun aut.bod |=([a=purl b=@ud] [[b %0 a] +(b)])) - =/ dor=^order [%1 dom.rod exp.bod fin.bod aut] + =/ dor=^order [%1 dom.rod exp.bod url fin.bod aut] this(der (~(put by der) i dor)) :: %aut @@ -934,24 +986,100 @@ this(der (~(put by der) ider rod)) :: %cal - abet:this :: XX del .well-known, make csr, poll order + =< abet:finalize + ?> ?=([@ %der @ *] t.t.wir) + =/ i (slav %ud i.t.t.wir) + =/ ider (slav %ud i.t.t.t.t.wir) + =/ rod=^order (~(got by der) ider) + ?> ?=([%1 *] rod) + =/ aut=auth (~(got by aut.rod) i) + ?> ?=([%1 *] aut) + =/ bod=[typ=@t sas=@t url=purl tok=@t] + (challenge:grab (need (de-json:html q:(need r.rep)))) + ?> ?=(%pending sas.bod) + =. sas.cal.aut %pend + =. rod rod(aut (~(put by aut.rod) i aut)) + =. der (~(put by der) ider rod) + =/ fin=(list (pair @ud ^order)) + %+ skim + ~(tap by der) + |= a=[@ud ^order] + ?& ?=([@ %1 *] a) + %+ levy + ~(tap by aut.a) + |= [i=@ud aut=auth] + ?& ?=([%1 *] aut) + ?=(%pend sas.cal.aut) + == == + %= this + der %- ~(gas by der) + %+ turn fin + |= [i=@ud der=^order] + ^+ [i der] + ?> ?=([%1 *] der) + =/ k=key:rsa rekey :: XX reuse + =/ csr=@ux (en:der:pkcs10 k dom.der) + [i %2 dom.der exp.der der.der fin.der k csr] + :: XX save pending authz somewhere instead of just dropping them + == + :: + %fin + =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] + (order:grab (need (de-json:html q:(need r.rep)))) + :: XX check status? (i don't think failures get here) + abet:poll-order + :: + %por + =/ i=@ud (slav %ud (head t.t.wir)) + =/ raw=json + (need (de-json:html q:(need r.rep))) + =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] + (order:grab raw) + ?+ sas.bod + ~&(poll-order-status+sas.bod abet) + %invalid abet :: XX check authz, retry order? + %pending abet:poll-order + %processing abet:poll-order + %valid =< abet + =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t cer=purl] + (final-order:grab raw) :: XX json reparser unit + %- emit :: XX accept hed + (request /acme/cer/(scot %ud i) cer.bod ~) + :: XX del .well-known + == + :: + %cer :: XX send configuration to eyre + =< abet + =/ i=@ud (slav %ud (head t.t.wir)) + =/ rod=^order (~(got by der) i) + =/ cer=wain + (to-wain:format q:(need r.rep)) + ?> ?=([%2 *] rod) + %= this + liv (~(put by liv) dom.rod [key.rod *@da cer]) :: XX exp when? + der (~(del by der) i) + der.hit [rod der.hit] + == == :: +:: ++ prep _[~ this] ++ prep |= old=(unit acme) ?~ old abet:init [~ this(+<+ u.old)] :: +++ rekey :: XX do something about this + =| i=@ + |- ^- key:rsa + =/ k (new-key:rsa 2.048 eny.bow) + =/ m (met 0 n.k) + ?: =(0 (mod m 8)) k + ~& [%key iter=i width=m] + $(i +(i), eny.bow +(eny.bow)) +:: ++ init - =/ key=key:rsa - =| i=@ - |- ^- key:rsa - =/ k (new-key:rsa 2.048 eny.bow) - =/ m (met 0 n.k) - ?: =(0 (mod m 8)) k - ~& [%init i m] - $(i +(i), eny.bow +(eny.bow)) + =/ key=key:rsa rekey =/ dom=turf /org/urbit/(crip +:(scow %p our.bow)) =/ dor=^order [%0 [dom ~]] =/ url From 90d27683586378073f37b05428f48794ff13004c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 16 May 2018 15:38:50 -0400 Subject: [PATCH 34/95] updates rsa-key structure to support public keys --- app/acme.hoon | 156 ++++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 69 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 502e7b98f..80d84b4c9 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -207,7 +207,11 @@ :: ++ rsa :: unpadded! |% - += key [p=@ux q=@ux n=@ux e=@ux d=@ux] + += key + $: pub=[n=@ux e=@ux] + sek=(unit [d=@ux p=@ux q=@ux]) + == + :: ++ elcm |= [a=@ b=@] (div (mul a b) d:(egcd a b)) @@ -221,7 +225,7 @@ =/ q=@ux (ramp:number diw [3 5 ~] +(eny)) =/ n=@ux (mul p q) =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) - [p q n e d] + [[n e] `[d p q]] :: ++ der :: pkcs1 |% @@ -231,18 +235,20 @@ ++ ring |= k=key ^- @ux + ~| %rsa-need-ring + ?> ?=(^ sek.k) =; pec (rep 3 ~(ren asn1 pec)) :~ %seq [%int 0] - [%int n.k] - [%int e.k] - [%int d.k] - [%int p.k] - [%int q.k] - [%int (mod d.k (dec p.k))] - [%int (mod d.k (dec q.k))] - [%int (~(inv fo p.k) q.k)] + [%int n.pub.k] + [%int e.pub.k] + [%int d.u.sek.k] + [%int p.u.sek.k] + [%int q.u.sek.k] + [%int (mod d.u.sek.k (dec p.u.sek.k))] + [%int (mod d.u.sek.k (dec q.u.sek.k))] + [%int (~(inv fo p.u.sek.k) q.u.sek.k)] == -- ++ de @@ -269,7 +275,7 @@ =* d p.i.t.t.t.p.u.b =* p p.i.t.t.t.t.p.u.b =* q p.i.t.t.t.t.t.p.u.b - `[p q n e d] + `[[n e] `[d p q]] -- -- :: @@ -307,21 +313,23 @@ ++ en |= [m=@ k=key] ~| %rsa-len - ?> (lte (met 0 m) (met 0 n.k)) - (~(exp fo n.k) e.k m) + ?> (lte (met 0 m) (met 0 n.pub.k)) + (~(exp fo n.pub.k) e.pub.k m) :: ++ de |= [m=@ k=key] :: XX assert rsa-len here too? - =/ fu (fu:number p.k q.k) - (out.fu (exp.fu d.k (sit.fu m))) + ~| %rsa-need-ring + ?> ?=(^ sek.k) + =/ fu (fu:number p.u.sek.k q.u.sek.k) + (out.fu (exp.fu d.u.sek.k (sit.fu m))) -- :: ++ rs256 |_ k=key:rsa ++ emsa :: EMSA-PKCS1-v1_5 |= m=@ - =/ emlen (met 3 n.k) + =/ emlen (met 3 n.pub.k) =/ pec=spec:asn1 :~ %seq [%seq [%obj sha-256:obj:asn1] [%nul ~] ~] @@ -358,7 +366,7 @@ :- %bit =; pec (rep 3 ~(ren asn1 pec)) - [%seq [[%int n.k] [%int e.k] ~]] + [%seq [[%int n.pub.k] [%int e.pub.k] ~]] == :: ++ ring !! @@ -417,7 +425,7 @@ :- %bit =; pec (rep 3 ~(ren asn1 pec)) - [%seq [[%int n.k] [%int e.k] ~]] + [%seq [[%int n.pub.k] [%int e.pub.k] ~]] == :+ %con [| 0] =- ~(ren asn1 -) @@ -521,19 +529,21 @@ ^- json :- %o %- my :~ kty+s+'RSA' - n+s+(en-base64url (swp 3 n.k)) - e+s+(en-base64url (swp 3 e.k)) + n+s+(en-base64url (swp 3 n.pub.k)) + e+s+(en-base64url (swp 3 e.pub.k)) == ++ ring |= k=key:rsa ^- json + ~| %rsa-need-ring + ?> ?=(^ sek.k) :- %o %- my :~ kty+s+'RSA' - p+s+(en-base64url (swp 3 p.k)) - q+s+(en-base64url (swp 3 q.k)) - n+s+(en-base64url (swp 3 n.k)) - e+s+(en-base64url (swp 3 e.k)) - d+s+(en-base64url (swp 3 d.k)) + n+s+(en-base64url (swp 3 n.pub.k)) + e+s+(en-base64url (swp 3 e.pub.k)) + d+s+(en-base64url (swp 3 d.u.sek.k)) + p+s+(en-base64url (swp 3 p.u.sek.k)) + q+s+(en-base64url (swp 3 q.u.sek.k)) == -- ++ de @@ -542,8 +552,10 @@ =, dejs-soft:format %+ ci |= [kty=@t n=(unit @) e=(unit @)] - ^- (unit [n=@ux e=@ux]) :: XX RSA pubkey model - (both (bind n (cury swp 3)) (bind e (cury swp 3))) + ^- (unit key:rsa) + =/ swp (cury swp 3) + =/ pub (both (bind n swp) (bind e swp)) + ?~(pub ~ `[u.pub ~]) %- ot :~ kty+(su (jest 'RSA')) n+(cu de-base64url so) @@ -553,27 +565,24 @@ =, dejs-soft:format %+ ci |= $: kty=@t - p=(unit @) - q=(unit @) n=(unit @) e=(unit @) d=(unit @) + p=(unit @) + q=(unit @) == ^- (unit key:rsa) - ;: both - (bind p (cury swp 3)) - (bind q (cury swp 3)) - (bind n (cury swp 3)) - (bind e (cury swp 3)) - (bind d (cury swp 3)) - == + =/ swp (cury swp 3) + =/ pub (both (bind n swp) (bind e swp)) + =/ sek :(both (bind d swp) (bind p swp) (bind q swp)) + ?:(|(?=(~ pub) ?=(~ sek)) ~ `[u.pub sek]) %- ot :~ kty+(su (jest 'RSA')) - p+(cu de-base64url so) - q+(cu de-base64url so) n+(cu de-base64url so) e+(cu de-base64url so) d+(cu de-base64url so) + p+(cu de-base64url so) + q+(cu de-base64url so) == -- -- @@ -1073,7 +1082,7 @@ =| i=@ |- ^- key:rsa =/ k (new-key:rsa 2.048 eny.bow) - =/ m (met 0 n.k) + =/ m (met 0 n.pub.k) ?: =(0 (mod m 8)) k ~& [%key iter=i width=m] $(i +(i), eny.bow +(eny.bow)) @@ -1096,7 +1105,7 @@ ;: weld test-base64 test-asn1 - :: test-rsakey + test-rsakey test-rsa test-rsapem test-rsa-pkcs8 @@ -1190,7 +1199,7 @@ =/ n (mul p q) =/ e 0x1.0001 =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) - [p q n e d] + [[n e] `[d p q]] :: |^ ^- tang ;: weld @@ -1200,28 +1209,29 @@ ++ check-primes =, number |= k=key:rsa + ?> ?=(^ sek.k) %+ roll primes |= [p=@ a=tang] ?^ a a - ?: =(0 (mod n.k p)) - :~ leaf+"{(scow %ux n.k)}" + ?: =(0 (mod n.pub.k p)) + :~ leaf+"{(scow %ux n.pub.k)}" :- %leaf %+ weld - "n.key (prime? {(scow %f (pram n.k))})" + "n.pub.key (prime? {(scow %f (pram n.pub.k))})" " divisible by {(scow %ud p)}:" == - ?: =(0 (mod p.k p)) - :~ leaf+"{(scow %ux p.k)}" + ?: =(0 (mod p.u.sek.k p)) + :~ leaf+"{(scow %ux p.u.sek.k)}" :- %leaf %+ weld - "p.key (prime? {(scow %f (pram p.k))})" + "p.u.sek.key (prime? {(scow %f (pram p.u.sek.k))})" " divisible by {(scow %ud p)}:" == - ?: =(0 (mod q.k p)) - :~ leaf+"{(scow %ux q.k)}" + ?: =(0 (mod q.u.sek.k p)) + :~ leaf+"{(scow %ux q.u.sek.k)}" :- %leaf %+ weld - "q.key (prime? {(scow %f (pram q.k))})" + "q.u.sek.key (prime? {(scow %f (pram q.u.sek.k))})" " divisible by {(scow %ud p)}:" == ~ @@ -1229,18 +1239,20 @@ :: ++ test-rsapem :: ex from https://stackoverflow.com/a/19855935 - =/ k1=key:rsa [`@ux`17 `@ux`11 `@ux`187 `@ux`7 `@ux`23] + =/ k1=key:rsa + :- [`@ux`187 `@ux`7] + [~ `@ux`23 `@ux`17 `@ux`11] =/ kpem1=wain :~ '-----BEGIN RSA PRIVATE KEY-----' 'MBwCAQACAgC7AgEHAgEXAgERAgELAgEHAgEDAgEO' '-----END RSA PRIVATE KEY-----' == =/ k2=key:rsa - :* p=`@ux`4.140.273.707 - q=`@ux`3.922.198.019 - n=`@ux`16.238.973.331.713.186.433 - e=`@ux`65.537 + :* [n=`@ux`16.238.973.331.713.186.433 e=`@ux`65.537] + ~ d=`@ux`3.298.243.342.098.580.397 + p=`@ux`4.140.273.707 + q=`@ux`3.922.198.019 == :: openssl genrsa -out private.pem 64 =/ kpem2=wain @@ -1347,9 +1359,11 @@ =/ e `@ux`17 =/ n (mul p q) =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) - [p q n e d] + [[n e] `[d p q]] :: - =/ k2=key:rsa [`@ux`11 `@ux`13 `@ux`143 `@ux`7 `@ux`103] + =/ k2=key:rsa + :- [`@ux`143 `@ux`7] + [~ `@ux`103 `@ux`11 `@ux`13] :: :: ex from http://doctrina.org/How-RSA-Works-With-Examples.html =/ k3=key:rsa @@ -1364,7 +1378,7 @@ =/ n (mul p q) =/ e 65.537 =/ d (~(inv fo (elcm:rsa (dec p) (dec q))) e) - [`@ux`p `@ux`q `@ux`n `@ux`e `@ux`d] + [[`@ux`n `@ux`e] `[`@ux`d `@ux`p `@ux`q]] =/ m3 (swp 3 'attack at dawn') =/ c3 35.052.111.338.673.026.690.212.423.937.053.328.511.880.760.811.579.981. @@ -1374,9 +1388,10 @@ 820.596.886.440.377.536.082.465.681.750.074.417.459.151.485.407.445. 862.511.023.472.235.560.823.053.497.791.518.928.820.272.257.787.786 :: + ?> ?=(^ sek.k1) ;: weld %- expect-eq !> - [413 d.k1] + [413 d.u.sek.k1] %- expect-eq !> [2.790 (en:rsa 65 k1)] %- expect-eq !> @@ -1396,17 +1411,18 @@ ++ test-rs256 :: ex from https://stackoverflow.com/a/41448118 =/ k1=key:rsa - :* 0xf7ef.37e6.7fa6.685a.c178.8b01.cf38.da20.ca4b.de5d.8b01.a71b.d28c. - 65b4.09c3.6e4d - 0xc882.5760.3fb8.a5e2.5e9d.db55.3a73.b647.a3ec.a6e9.abc6.c440.dbc7. - 05f8.2ed4.da6b - 0xc231.1fc5.fa31.d333.a409.bb4c.e95b.20d2.1cfc.e375.3871.7256.53a2. + :* :- n=0xc231.1fc5.fa31.d333.a409.bb4c.e95b.20d2.1cfc.e375.3871.7256.53a2. 8425.af6d.e97d.f202.0b23.633f.458d.f12a.6362.7121.bff4.e23c.e578. 7e07.7898.0578.61d1.ae60.ac2f - 0x1.0001 - 0xd91.6719.eb10.3e24.768a.a386.8d2b.6bd0.a26b.dcec.9cc3.f86c.25ad. + e=0x1.0001 + ~ + d=0xd91.6719.eb10.3e24.768a.a386.8d2b.6bd0.a26b.dcec.9cc3.f86c.25ad. ce33.dfdc.fb1a.4d50.3e07.3d7f.f5fd.748e.43f8.df02.a60e.d730.5314. 3e59.1e70.8df7.2c27.93e2.2b69 + p=0xf7ef.37e6.7fa6.685a.c178.8b01.cf38.da20.ca4b.de5d.8b01.a71b.d28c. + 65b4.09c3.6e4d + q=0xc882.5760.3fb8.a5e2.5e9d.db55.3a73.b647.a3ec.a6e9.abc6.c440.dbc7. + 05f8.2ed4.da6b == =/ inp1 0x302.0101 =/ exp1 @@ -1507,7 +1523,7 @@ ;: weld %- expect-eq !> :- jk - (pass:en:jwk [0x0 0x0 n.k e.k 0x0]) + (pass:en:jwk k) %- expect-eq !> :- 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs' (thumbprint jk) @@ -1586,13 +1602,15 @@ 'p0igcN_IoypGlUPQGe77Rw' == =/ lod-order=(list @t) ['iss' 'exp' 'http://example.com/is_root' ~] + ?> ?=(^ sek.k) ;: weld %- expect-eq !> [jk (ring:en:jwk k)] %- expect-eq !> - [n.k `@ux`(mul p.k q.k)] + [n.pub.k `@ux`(mul p.u.sek.k q.u.sek.k)] %- expect-eq !> - [d.k `@ux`(~(inv fo (elcm:rsa (dec p.k) (dec q.k))) e.k)] + :- d.u.sek.k + `@ux`(~(inv fo (elcm:rsa (dec p.u.sek.k) (dec q.u.sek.k))) e.pub.k) %- expect-eq !> :- hedt (en-base64url (crip (en-json-sort aor hed))) From 39ac62275d58c7c84c1404152ad9902588404502 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 16 May 2018 23:08:15 -0400 Subject: [PATCH 35/95] removes automatic ~ship.urbit.org order initialization --- app/acme.hoon | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 80d84b4c9..7ddbfd327 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -802,6 +802,8 @@ :: ++ order ^+ this + ?~ reg.act + this :: XX pending registration assumed %- emil %+ turn (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %0 *] a))) @@ -902,20 +904,6 @@ ^- card (request /acme/por/(scot %ud i) der ~) :: -++ poke-noun - |= a=* - ^- (quip move _this) - ?+ a ~& +<+.this - [~ this] - %init abet:init - %order abet:order - %auth abet:authorize - %trial abet:challenge - %final abet:finalize - %poll abet:poll-order - %test test - == -:: ++ sigh-httr |= [wir=wire rep=httr:eyre] ^- (quip move _this) @@ -1071,6 +1059,24 @@ == == :: +++ poke-noun + |= a=* + ^- (quip move _this) + ?+ a ~& +<+.this + [~ this] + %init abet:init + %order abet:order + %auth abet:authorize + %trial abet:challenge + %final abet:finalize + %poll abet:poll-order + %our abet:(add-order /org/urbit/(crip +:(scow %p our.bow)) ~) + %test test + == +:: +++ poke-path + |=(a=path (add-order a ~)) +:: :: ++ prep _[~ this] ++ prep |= old=(unit acme) @@ -1088,12 +1094,16 @@ $(i +(i), eny.bow +(eny.bow)) :: ++ init - =/ key=key:rsa rekey - =/ dom=turf /org/urbit/(crip +:(scow %p our.bow)) - =/ dor=^order [%0 [dom ~]] =/ url - (de-purl:html 'https://acme-staging-v02.api.letsencrypt.org/directory') - directory(bas (need url), act `acct`[key ~], der [[0 dor] ~ ~]) + 'https://acme-staging-v02.api.letsencrypt.org/directory' + directory(bas (need (de-purl:html url)), act [rekey ~]) + :: XX wait for DNS binding confirmation? + :: (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) +:: +++ add-order + |= dom=(list turf) + ^+ this + order(der (~(put by der) ~(wyt by der) [%0 dom])) :: ++ test =, tester:tester From 5e0a2fcb95db95424dea5a974344c32a358e69a0 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 17 May 2018 01:40:22 -0400 Subject: [PATCH 36/95] refactors pkcs1, 8, and 10, separating ASN.1 specs from DER encoding also adds pkcs1 RSA public key en/de-coding and tests --- app/acme.hoon | 391 +++++++++++++++++++++++++++----------------------- 1 file changed, 213 insertions(+), 178 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 7ddbfd327..473c1a586 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -227,89 +227,6 @@ =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) [[n e] `[d p q]] :: - ++ der :: pkcs1 - |% - ++ en - |% - ++ pass !! - ++ ring - |= k=key - ^- @ux - ~| %rsa-need-ring - ?> ?=(^ sek.k) - =; pec - (rep 3 ~(ren asn1 pec)) - :~ %seq - [%int 0] - [%int n.pub.k] - [%int e.pub.k] - [%int d.u.sek.k] - [%int p.u.sek.k] - [%int q.u.sek.k] - [%int (mod d.u.sek.k (dec p.u.sek.k))] - [%int (mod d.u.sek.k (dec q.u.sek.k))] - [%int (~(inv fo p.u.sek.k) q.u.sek.k)] - == - -- - ++ de - |% - ++ pass !! - ++ ring - |= a=@ - ^- (unit key) - =/ b (rush a decode:asn1) - ?~ b ~ - ?. ?=([%seq *] u.b) ~ - ?. ?= $: [%int %0] - [%int *] - [%int *] - [%int *] - [%int *] - [%int *] - * - == - p.u.b - ~ - =* n p.i.t.p.u.b - =* e p.i.t.t.p.u.b - =* d p.i.t.t.t.p.u.b - =* p p.i.t.t.t.t.p.u.b - =* q p.i.t.t.t.t.t.p.u.b - `[[n e] `[d p q]] - -- - -- - :: - ++ pem :: pkcs1 - |% - ++ en - |% - ++ pass !! - ++ ring - |= k=key - ^- wain - :- '-----BEGIN RSA PRIVATE KEY-----' - =/ a (en:base64 (ring:en:der k)) - |- ^- wain - ?~ a - ['-----END RSA PRIVATE KEY-----' ~] - [(end 3 64 a) $(a (rsh 3 64 a))] - -- - ++ de - |% - ++ pass !! - ++ ring - |= mep=wain - ^- (unit key) - =/ a (sub (lent mep) 2) - ?~ mep ~ - ?. =('-----BEGIN RSA PRIVATE KEY-----' i.mep) ~ - ?. =('-----END RSA PRIVATE KEY-----' (snag a t.mep)) ~ - =/ b (de:base64 (rap 3 (scag a t.mep))) - ?~ b ~ - (ring:de:der u.b) - -- - -- - :: ++ en |= [m=@ k=key] ~| %rsa-len @@ -350,33 +267,99 @@ =((emsa m) (en:rsa s k)) -- :: -++ pkcs8 :: XX other key types? +++ pem :: rfc7468 |% + ++ en + |= [lab=@t der=@ux] + ^- wain + :: XX validate label? + :- (rap 3 ['-----BEGIN ' lab '-----' ~]) + =/ a (en:base64 der) + |- ^- wain + ?~ a + [(rap 3 ['-----END ' lab '-----' ~]) ~] + [(end 3 64 a) $(a (rsh 3 64 a))] + :: + ++ de + |= [lab=@t mep=wain] + ^- (unit @ux) + =/ a (sub (lent mep) 2) + ?~ mep ~ + :: XX validate label? + ?. =((rap 3 ['-----BEGIN ' lab '-----' ~]) i.mep) ~ + ?. =((rap 3 ['-----END ' lab '-----' ~]) (snag a t.mep)) ~ + (de:base64 (rap 3 (scag a t.mep))) + -- +:: +++ pkcs1 :: rfc3447 + |% + ++ spec + |% + ++ pass + |= k=key:rsa + ^- spec:asn1 + [%seq [%int n.pub.k] [%int e.pub.k] ~] + :: + ++ ring + |= k=key:rsa + ^- spec:asn1 + ~| %rsa-need-ring + ?> ?=(^ sek.k) + :~ %seq + [%int 0] + [%int n.pub.k] + [%int e.pub.k] + [%int d.u.sek.k] + [%int p.u.sek.k] + [%int q.u.sek.k] + [%int (mod d.u.sek.k (dec p.u.sek.k))] + [%int (mod d.u.sek.k (dec q.u.sek.k))] + [%int (~(inv fo p.u.sek.k) q.u.sek.k)] + == + -- + :: ++ der |% ++ en |% - ++ pass - |= k=key:rsa - ^- @ux - =; pec - (rep 3 ~(ren asn1 pec)) - :~ %seq - [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] - :- %bit - =; pec - (rep 3 ~(ren asn1 pec)) - [%seq [[%int n.pub.k] [%int e.pub.k] ~]] - == - :: - ++ ring !! + ++ pass |=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (pass:spec k)))) + ++ ring |=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (ring:spec k)))) -- - :: ++ de |% - ++ pass !! + ++ pass + |= a=@ + ^- (unit key:rsa) + =/ b (rush a decode:asn1) + ?~ b ~ + ?. ?=([%seq [%int *] [%int *] ~] u.b) + ~ + =* n p.i.p.u.b + =* e p.i.t.p.u.b + `[[n e] ~] :: - ++ ring !! + ++ ring + |= a=@ + ^- (unit key:rsa) + =/ b (rush a decode:asn1) + ?~ b ~ + ?. ?=([%seq *] u.b) ~ + ?. ?= $: [%int %0] + [%int *] + [%int *] + [%int *] + [%int *] + [%int *] + * + == + p.u.b + ~ + =* n p.i.t.p.u.b + =* e p.i.t.t.p.u.b + =* d p.i.t.t.t.p.u.b + =* p p.i.t.t.t.t.p.u.b + =* q p.i.t.t.t.t.t.p.u.b + `[[n e] `[d p q]] -- -- :: @@ -384,93 +367,129 @@ |% ++ en |% - ++ pass - |= k=key:rsa - ^- wain - :- '-----BEGIN PUBLIC KEY-----' - =/ a (en:base64 (pass:en:der k)) - |- ^- wain - ?~ a - ['-----END PUBLIC KEY-----' ~] - [(end 3 64 a) $(a (rsh 3 64 a))] - :: - ++ ring !! + ++ pass |=(k=key:rsa (en:^pem 'RSA PUBLIC KEY' (pass:en:der k))) + ++ ring |=(k=key:rsa (en:^pem 'RSA PRIVATE KEY' (ring:en:der k))) -- - :: ++ de |% - ++ pass !! - :: - ++ ring !! + ++ pass |=(mep=wain (biff (de:^pem 'RSA PUBLIC KEY' mep) pass:de:der)) + ++ ring |=(mep=wain (biff (de:^pem 'RSA PRIVATE KEY' mep) ring:de:der)) -- -- -- :: -++ pkcs10 :: XX other key types? - |% +++ pkcs8 :: rfc5208 + |% :: XX handle other key types? + ++ spec + |% + ++ pass + |= k=key:rsa + ^- spec:asn1 + :~ %seq + [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] + [%bit (pass:en:der:pkcs1 k)] + == + :: + ++ ring !! + -- + :: ++ der |% ++ en - |= [k=key:rsa hot=(list (list @t))] - ^- @ux - =; pec - (rep 3 ~(ren asn1 pec)) - =/ cer=spec:asn1 - :~ %seq - [%int 0] - [%seq ~] - :: XX deduplicate with +pass:en:der:pkcs8 - :~ %seq - [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] - :- %bit - =; pec - (rep 3 ~(ren asn1 pec)) - [%seq [[%int n.pub.k] [%int e.pub.k] ~]] - == - :+ %con [| 0] - =- ~(ren asn1 -) - :~ %seq - [%obj csr-ext:obj:asn1] - :~ %set - :~ %seq - :~ %seq - [%obj sub-alt:obj:asn1] - :- %oct - =; pec - (rep 3 ~(ren asn1 pec)) - :- %seq - %+ turn hot - |=(h=(list @t) [%con [& 2] (rip 3 (en-host h))]) - == - == - == - == - == - :: - ^- spec:asn1 - :~ %seq - cer - [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] - [%bit (swp 3 (~(sign rs256 k) (rep 3 ~(ren asn1 cer))))] - == + |% + ++ pass |=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (pass:spec k)))) + ++ ring !! ::|=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (ring:spec k)))) + -- :: - ++ de !! + ++ de + |% + ++ pass + |= a=@ + ^- (unit key:rsa) + =/ b (rush a decode:asn1) + ?~ b ~ + ?. ?=([%seq [%seq *] [%bit *] ~] u.b) + ~ + ?. ?& ?=([[%obj *] [%nul ~] ~] p.i.p.u.b) + =(rsa:obj:asn1 p.i.p.i.p.u.b) + == + ~ + (pass:de:der:pkcs1 p.i.t.p.u.b) + :: + ++ ring !! + -- -- :: ++ pem |% ++ en - |= [k=key:rsa hot=(list (list @t))] - ^- wain - :- '-----BEGIN CERTIFICATE REQUEST-----' - =/ a (en:base64 (en:der k hot)) - |- ^- wain - ?~ a - ['-----END CERTIFICATE REQUEST-----' ~] - [(end 3 64 a) $(a (rsh 3 64 a))] + |% + ++ pass |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k))) + ++ ring !! ::|=(k=key:rsa (en:^pem 'PUBLIC KEY' (ring:en:der k))) + -- :: + ++ de + |% + ++ pass |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der)) + ++ ring !! ::|=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) + -- + -- + -- +:: +++ pkcs10 :: rfc2986 + => |% + += csr [key=key:rsa hot=(list (list @t))] :: XX other key types? + -- + |% + ++ spec + |% + ++ host + |= hot=(list (list @t)) + ^- spec:asn1 + :- %seq + %+ turn hot + |=(h=(list @t) [%con [& 2] (rip 3 (en-host h))]) + :: + ++ cert :: XX rename + |= csr + ^- spec:asn1 + :~ %seq + [%int 0] + [%seq ~] + (pass:spec:pkcs8 key) + :+ %con [| 0] + =- ~(ren asn1 -) + :~ %seq + [%obj csr-ext:obj:asn1] + :~ %set + :~ %seq + :~ %seq + [%obj sub-alt:obj:asn1] + [%oct (rep 3 ~(ren asn1 (host hot)))] + == == == == == + :: + ++ sign + |= csr + ^- spec:asn1 + =/ cer (cert key hot) + :~ %seq + cer + [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] + [%bit (swp 3 (~(sign rs256 key) (rep 3 ~(ren asn1 cer))))] + == + -- + :: + ++ der + |% + ++ en |=(a=csr `@ux`(rep 3 ~(ren asn1 (sign:spec a)))) ++ de !! -- + :: + ++ pem + |% + ++ en |=(a=csr (en:^pem 'CERTIFICATE REQUEST' (en:der a))) + ++ de !! :: |=(mep=wain (biff (de:^pem 'CERTIFICATE REQUEST' mep) de:der)) + -- -- :: ++ en-json-sort :: print json @@ -1301,19 +1320,35 @@ 'zqVTrhnY+TemcScSx5O6f32aDfOUWWCzmw/gzvJxUYlJqjqd7dlT' '-----END RSA PRIVATE KEY-----' == + =/ kpem3-pub=wain + :~ '-----BEGIN RSA PUBLIC KEY-----' + 'MIIBCgKCAQEA2jJp8dgAKy5cSzDE4D+aUbKZsQoMhIWI2IFlE+AO0GCBMig5qxx2' + 'IIAPVIcSi5fjOLtTHnuIZYw+s06qeb8QIKRvkZaIwnA3Lz5UUrxgh96sezdXCCSG' + '7FndIFskcT+zG00JL+fPRdlPjt1Vg2b3kneo5aAKMIPyOTzcY590UTc+luQ3HhgS' + 'iNF3n5YQh24d3kS2YOUoSXQ13+YRljxNfBgXbV+C7/gO8mFxpkafhmgkIGNeWlqT' + '9oAIRa+gOx13uPAg+Jb/8lPV9bGaFqGvxvBMp3xUASlzYHiDntcB5MiOPRW6BoIG' + 'I5qDFSYRZBky9crE7WAYgqtPtg21zvxwFwIDAQAB' + '-----END RSA PUBLIC KEY-----' + == =/ k3=key:rsa - (need (ring:de:pem:rsa kpem3)) + (need (ring:de:pem:pkcs1 kpem3)) + =/ k3-pub=key:rsa + (need (pass:de:pem:pkcs1 kpem3-pub)) ;: weld %- expect-eq !> - [kpem1 (ring:en:pem:rsa k1)] + [kpem1 (ring:en:pem:pkcs1 k1)] %- expect-eq !> - [k1 (need (ring:de:pem:rsa kpem1))] + [k1 (need (ring:de:pem:pkcs1 kpem1))] %- expect-eq !> - [kpem2 (ring:en:pem:rsa k2)] + [kpem2 (ring:en:pem:pkcs1 k2)] %- expect-eq !> - [k2 (need (ring:de:pem:rsa kpem2))] + [k2 (need (ring:de:pem:pkcs1 kpem2))] %- expect-eq !> - [kpem3 (ring:en:pem:rsa k3)] + [kpem3 (ring:en:pem:pkcs1 k3)] + %- expect-eq !> + [kpem3-pub (pass:en:pem:pkcs1 k3)] + %- expect-eq !> + [k3-pub [pub.k3 ~]] == :: ++ test-rsa-pkcs8 @@ -1358,7 +1393,7 @@ '-----END PUBLIC KEY-----' == =/ k=key:rsa - (need (ring:de:pem:rsa kpem)) + (need (ring:de:pem:pkcs1 kpem)) %- expect-eq !> [pub (pass:en:pem:pkcs8 k)] :: @@ -1473,7 +1508,7 @@ '-----END RSA PRIVATE KEY-----' == =/ k2=key:rsa - (need (ring:de:pem:rsa kpem2)) + (need (ring:de:pem:pkcs1 kpem2)) =/ inp2=cord 'hello\0a' =/ exp2=@ux 0x2920.bba3.cb38.bca6.3768.6345.c95e.0717.81bf.6c61.4006.6070.a7b5.e609. @@ -1663,7 +1698,7 @@ '-----END RSA PRIVATE KEY-----' == =/ k=key:rsa - (need (ring:de:pem:rsa kpem)) + (need (ring:de:pem:pkcs1 kpem)) :: generated with openssl, certbot style =/ csr-pem=wain :~ '-----BEGIN CERTIFICATE REQUEST-----' From 3d40edc8d17cc0c7b735fd6633f47acd6305899c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 17 May 2018 12:36:29 -0400 Subject: [PATCH 37/95] refactors JWS, JWK thumbprint, and ACME POST requests --- app/acme.hoon | 94 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 36 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 473c1a586..30e3f9d14 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -539,7 +539,7 @@ == -- :: -++ jwk +++ jwk :: rfc7517 |% ++ en |% @@ -604,12 +604,47 @@ q+(cu de-base64url so) == -- + :: + ++ thumb :: rfc7638 + |% + ++ ring !! + ++ pass + |= k=key:rsa + (en-base64url (shax (crip (en-json-sort aor (pass:en k))))) + -- -- :: -++ thumbprint - |= jon=json - :: XX restrict keys to canonical set - (en-base64url (shax `@`(crip `tape`(en-json-sort aor jon)))) +++ jws :: rfc7515 + |% + ++ sign + |= [k=key:rsa pro=json lod=json] + |^ ^- json + =. pro header + =/ protect=cord (encode pro) + =/ payload=cord (encode lod) + :- %o %- my :~ + protected+s+protect + payload+s+payload + signature+s+(sign protect payload) + == + :: + ++ header + ?> ?=([%o *] pro) + ^- json + [%o (~(put by p.pro) %alg s+'RS256')] + :: + ++ encode + |= jon=json + (en-base64url (crip (en-json-sort aor jon))) + :: + ++ sign + |= [protect=cord payload=cord] + %- en-base64url + (swp 3 (~(sign rs256 k) (rap 3 ~[protect '.' payload]))) + -- + :: + ++ verify !! + -- :: ++ eor :: explicit order |= [com=$-([@ @] ?) lit=(list)] @@ -767,42 +802,29 @@ ++ abet [(flop mov) this(mov ~)] :: -++ jws-body - |= [url=purl bod=json] - ^- octs - :: ?> ?=(^ key.act) - =* enc (corl en-base64url (corl crip (cury en-json-sort aor))) - =/ payload=cord (enc bod) - =/ protect=cord - %- enc +++ request + |= [wir=wire url=purl bod=(unit json)] + |^ ^- card + [%hiss wir [~ ~] %httr %hiss url moth] + :: + ++ moth + ?~ bod + [%get ~ ~] + [%post (my content-type+['application/jose+json' ~] ~) `body] + :: + ++ body + ?> ?=(^ bod) + ^- octs + =; pro=json + (as-octt:mimes:html (en-json:html (sign:jws key.act pro u.bod))) :- %o %- my :~ - alg+s+'RS256' nonce+s+non url+s+(crip (en-purl:html url)) ?^ reg.act kid+s+kid.u.reg.act jwk+(pass:en:jwk key.act) == - %- (corl as-octt:mimes:html en-json:html) - ^- json - :- %o %- my :~ - protected+s+protect - payload+s+payload - :+ %signature %s - %- en-base64url - %+ swp 3 - (~(sign rs256 key.act) (rap 3 ~[protect '.' payload])) - == -:: -++ request - |= [wir=wire url=purl bod=(unit json)] - ^- card - =/ lod - ?~ bod - [%get ~ ~] - =/ hed (my content-type+['application/jose+json' ~] ~) - [%post hed `(jws-body url u.bod)] - [%hiss wir [~ ~] %httr %hiss url lod] + -- :: ++ directory (emit (request /acme/dir/(scot %p our.bow) bas ~)) @@ -884,7 +906,7 @@ :+ ~ /text/plain %- as-octs:mimes:html - (rap 3 [tok.cal '.' (thumbprint (pass:en:jwk key.act)) ~]) + (rap 3 [tok.cal '.' (pass:thumb:jwk key.act) ~]) :: %^ request /acme/cal/(scot %ud i)/der/(scot %ud ider) @@ -1571,7 +1593,7 @@ (pass:en:jwk k) %- expect-eq !> :- 'NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs' - (thumbprint jk) + (pass:thumb:jwk k) == :: ++ test-jws From 2938c19be1f043ccc47b979a4fd7bc8e8cc1b61a Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 17 May 2018 14:27:15 -0400 Subject: [PATCH 38/95] refactors DER en/de-coding out of +asn1 into a separate core --- app/acme.hoon | 420 ++++++++++++++++++++++++++------------------------ 1 file changed, 217 insertions(+), 203 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 30e3f9d14..953e47382 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -60,149 +60,163 @@ ++ de-base64url ~(de base64 | &) :: -++ asn1 :: at least, a little - => |% - += spec - $% [%int p=@u] - [%bit p=@ux] - [%oct p=@ux] - [%nul ~] - [%obj p=@ux] - [%seq p=(list spec)] - [%set p=(list spec)] :: XX actual set - [%con p=[p=? q=@udC] q=(list @)] :: XX manual +++ asn1 :: types and constants + |% + += spec + $% [%int p=@u] :: unsigned + [%bit p=@ux] :: pad yerself + [%oct p=@ux] :: + [%nul ~] :: + [%obj p=@ux] :: pack yerself + [%seq p=(list spec)] :: + [%set p=(list spec)] :: sort yerself + $: %con :: construct yerself + p=[p=? q=@udC] :: [primitive? tag] + q=(list @) :: bytes + == == + :: + ++ obj :: oid constants + |% :: rfc4055 + ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 + ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 + ++ rsa-sha-256 0xb.0101.0df7.8648.862a :: 1.2.840.113549.1.1.11 + :: rfc2985 + ++ csr-ext 0xe.0901.0df7.8648.862a :: 1.2.840.113549.1.9.14 + :: rfc3280 + ++ sub-alt 0x11.1d55 :: 2.5.29.17 + -- + -- +:: +++ der + |% + ++ en :: +en:der + =< |=(a=spec:asn1 `@ux`(rep 3 ~(ren raw a))) + |% + ++ raw :: bytes + |_ pec=spec:asn1 + ++ ren :: tlv + ^- (list @) + =/ a lem + [tag (weld (len a) a)] + :: + ++ tag :: type tag + ^- @ + ?- pec + [%int *] 2 + [%bit *] 3 + [%oct *] 4 + [%nul *] 5 + [%obj *] 6 + [%seq *] 48 :: (con 0x20 16) + [%set *] 49 :: (con 0x20 17) + [%con *] :(con q.p.pec 0x80 ?:(p.p.pec 0 0x20)) == :: - ++ obj :: oid constants - |% :: rfc4055 - ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 - ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 - ++ rsa-sha-256 0xb.0101.0df7.8648.862a :: 1.2.840.113549.1.1.11 - :: rfc2985 - ++ csr-ext 0xe.0901.0df7.8648.862a :: 1.2.840.113549.1.9.14 - :: rfc3280 - ++ sub-alt 0x11.1d55 :: 2.5.29.17 - -- - -- - :: - |_ pec=spec - ++ ren :: bytes - ^- (list @) - =/ a lem - [tag (weld (len a) a)] - :: - ++ tag :: type tag - ^- @ - ?- pec - [%int *] 2 - [%bit *] 3 - [%oct *] 4 - [%nul *] 5 - [%obj *] 6 - [%seq *] 48 :: (con 0x20 16) - [%set *] 49 :: (con 0x20 17) - [%con *] :(con q.p.pec 0x80 ?:(p.p.pec 0 0x20)) - == - :: - ++ lem :: element bytes - ^- (list @) - ?- pec - [%int *] =/ a (flop (rip 3 p.pec)) :: XX unsigned only! - ?~ a [0 ~] - ?:((lte i.a 127) a [0 a]) + ++ lem :: element bytes + ^- (list @) + ?- pec + [%int *] =/ a (flop (rip 3 p.pec)) + ?~ a [0 ~] + ?:((lte i.a 127) a [0 a]) + :: + [%bit *] [0 (rip 3 p.pec)] :: XX padding + [%oct *] (rip 3 p.pec) + [%nul *] ~ + [%obj *] (rip 3 p.pec) + :: + [%seq *] %- zing + |- ^- (list (list @)) + ?~ p.pec ~ + :- ren(pec i.p.pec) + $(p.pec t.p.pec) + :: + [%set *] %- zing :: XX tap/sort + |- ^- (list (list @)) + ?~ p.pec ~ + :- ren(pec i.p.pec) + $(p.pec t.p.pec) + :: + [%con *] q.pec + == :: - [%bit *] [0 (rip 3 p.pec)] :: XX padding - [%oct *] (rip 3 p.pec) - [%nul *] ~ - [%obj *] (rip 3 p.pec) - :: - [%seq *] %- zing - |- ^- (list (list @)) - ?~ p.pec ~ - :- ren(pec i.p.pec) - $(p.pec t.p.pec) - :: - [%set *] %- zing :: XX tap/sort - |- ^- (list (list @)) - ?~ p.pec ~ - :- ren(pec i.p.pec) - $(p.pec t.p.pec) - :: - [%con *] q.pec - == - :: - ++ len :: length bytes - |= a=(list @) - ^- (list @) - =/ b (lent a) - ?: (lte b 127) - [b ~] - [(con 0x80 (met 3 b)) (flop (rip 3 b))] - :: - ++ decode - %+ cook |*(a=* `spec:asn1`a) - :: ^- $-(nail (like spec:asn1)) - ;~ pose - %+ stag %int - %+ bass 256 - %+ sear + ++ len :: length bytes |= a=(list @) - ^- (unit (list @)) - ?~ a ~ - ?: ?=([@ ~] a) `a - ?. =(0 i.a) `a - ?.((gth i.t.a 127) ~ `t.a) - ;~(pfix (just `@`2) till) - :: - (stag %bit (boss 256 (cook tail ;~(pfix (just `@`3) till)))) :: XX test - (stag %oct (boss 256 ;~(pfix (just `@`4) till))) - (stag %nul (cold ~ ;~(plug (just `@`5) (just `@`0)))) - (stag %obj (boss 256 ;~(pfix (just `@`6) till))) - :: - %+ stag %seq - %+ sear - |=(a=(list @) (rust a (star decode))) :: XX plus? curr? - ;~(pfix (just `@`48) till) - :: - %+ stag %set - %+ sear - |=(a=(list @) (rust a (star decode))) :: XX plus? curr? - ;~(pfix (just `@`49) till) - :: - %+ stag %con - ;~ plug - %+ sear - |= a=@ - ^- (unit [? @udC]) - ?. =(1 (cut 0 [7 1] a)) ~ - :+ ~ - =(1 (cut 0 [5 1] a)) - (dis 0x1f a) - next - till - == - == + ^- (list @) + =/ b (lent a) + ?: (lte b 127) + [b ~] + [(con 0x80 (met 3 b)) (flop (rip 3 b))] + -- + -- :: - ++ till :: len-prefixed bytes - |= tub/nail - ^- (like (list @D)) - ?~ q.tub - (fail tub) - =* fuz i.q.tub - =+ ^- [nex=@ len=@] - =/ faz (end 0 7 fuz) - ?: =(0 (cut 0 [7 1] fuz)) - [0 faz] - [faz (rep 3 (flop (scag faz t.q.tub)))] - ?: ?& !=(0 nex) - !=(nex (met 3 len)) + ++ de :: +de:der + =< |=(a=@ `(unit spec:asn1)`(rush a decode)) + |% + ++ decode :: XX rename + %+ cook |*(a=* `spec:asn1`a) + :: ^- $-(nail (like spec:asn1)) + ;~ pose + %+ stag %int + %+ bass 256 + %+ sear + |= a=(list @) + ^- (unit (list @)) + ?~ a ~ + ?: ?=([@ ~] a) `a + ?. =(0 i.a) `a + ?.((gth i.t.a 127) ~ `t.a) + ;~(pfix (just `@`2) till) + :: + (stag %bit (boss 256 (cook tail ;~(pfix (just `@`3) till)))) :: XX test + (stag %oct (boss 256 ;~(pfix (just `@`4) till))) + (stag %nul (cold ~ ;~(plug (just `@`5) (just `@`0)))) + (stag %obj (boss 256 ;~(pfix (just `@`6) till))) + :: + %+ stag %seq + %+ sear + |=(a=(list @) (rust a (star decode))) :: XX plus? curr? + ;~(pfix (just `@`48) till) + :: + %+ stag %set + %+ sear + |=(a=(list @) (rust a (star decode))) :: XX plus? curr? + ;~(pfix (just `@`49) till) + :: + %+ stag %con + ;~ plug + %+ sear + |= a=@ + ^- (unit [? @udC]) + ?. =(1 (cut 0 [7 1] a)) ~ + :+ ~ + =(1 (cut 0 [5 1] a)) + (dis 0x1f a) + next + till == - (fail tub) - =/ zuf (swag [nex len] t.q.tub) - ?. =(len (lent zuf)) - (fail tub) - =/ zaf [p.p.tub (add +(nex) q.p.tub)] - [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] + == + :: + ++ till :: len-prefixed bytes + |= tub/nail + ^- (like (list @D)) + ?~ q.tub + (fail tub) + =* fuz i.q.tub + =+ ^- [nex=@ len=@] + =/ faz (end 0 7 fuz) + ?: =(0 (cut 0 [7 1] fuz)) + [0 faz] + [faz (rep 3 (flop (scag faz t.q.tub)))] + ?: ?& !=(0 nex) + !=(nex (met 3 len)) + == + (fail tub) + =/ zuf (swag [nex len] t.q.tub) + ?. =(len (lent zuf)) + (fail tub) + =/ zaf [p.p.tub (add +(nex) q.p.tub)] + [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] + -- -- :: ++ rsa :: unpadded! @@ -252,7 +266,7 @@ [%seq [%obj sha-256:obj:asn1] [%nul ~] ~] [%oct (shax m)] == - =/ t=(list @) ~(ren asn1 pec) + =/ t=(list @) ~(ren raw:en:der pec) =/ tlen (lent t) ?: (lth emlen (add 11 tlen)) ~|(%emsa-too-short !!) @@ -322,15 +336,15 @@ |% ++ en |% - ++ pass |=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (pass:spec k)))) - ++ ring |=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (ring:spec k)))) + ++ pass |=(k=key:rsa `@ux`(en:^der (pass:spec k))) + ++ ring |=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- ++ de |% ++ pass |= a=@ ^- (unit key:rsa) - =/ b (rush a decode:asn1) + =/ b (de:^der a) ?~ b ~ ?. ?=([%seq [%int *] [%int *] ~] u.b) ~ @@ -341,7 +355,7 @@ ++ ring |= a=@ ^- (unit key:rsa) - =/ b (rush a decode:asn1) + =/ b (de:^der a) ?~ b ~ ?. ?=([%seq *] u.b) ~ ?. ?= $: [%int %0] @@ -397,8 +411,8 @@ |% ++ en |% - ++ pass |=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (pass:spec k)))) - ++ ring !! ::|=(k=key:rsa `@ux`(rep 3 ~(ren asn1 (ring:spec k)))) + ++ pass |=(k=key:rsa `@ux`(en:^der (pass:spec k))) + ++ ring !! ::|=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- :: ++ de @@ -406,7 +420,7 @@ ++ pass |= a=@ ^- (unit key:rsa) - =/ b (rush a decode:asn1) + =/ b (de:^der a) ?~ b ~ ?. ?=([%seq [%seq *] [%bit *] ~] u.b) ~ @@ -458,14 +472,14 @@ [%seq ~] (pass:spec:pkcs8 key) :+ %con [| 0] - =- ~(ren asn1 -) + =- ~(ren raw:en:^der -) :~ %seq [%obj csr-ext:obj:asn1] :~ %set :~ %seq :~ %seq [%obj sub-alt:obj:asn1] - [%oct (rep 3 ~(ren asn1 (host hot)))] + [%oct (en:^der (host hot))] == == == == == :: ++ sign @@ -475,13 +489,13 @@ :~ %seq cer [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] - [%bit (swp 3 (~(sign rs256 key) (rep 3 ~(ren asn1 cer))))] + [%bit (swp 3 (~(sign rs256 key) (en:^der cer)))] == -- :: ++ der |% - ++ en |=(a=csr `@ux`(rep 3 ~(ren asn1 (sign:spec a)))) + ++ en |=(a=csr `@ux`(en:^der (sign:spec a))) ++ de !! -- :: @@ -769,7 +783,7 @@ += config [key=key:rsa exp=@da cer=wain] :: finalized config += history :: isn't over $: act=(list acct) :: - der=(list order) :: + rod=(list order) :: fig=(list (pair (list turf) config)) :: == :: += acme :: @@ -777,7 +791,7 @@ dir=directory :: service urls act=acct :: service account non=@t :: nonce from last - der=(map @ud order) :: active orders + rod=(map @ud order) :: active orders liv=(map (list turf) config) :: active config hit=history :: a foreign country == :: @@ -847,10 +861,10 @@ this :: XX pending registration assumed %- emil %+ turn - (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %0 *] a))) - |= [i=@ud der=^order] + (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %0 *] a))) + |= [i=@ud rod=^order] ^- card - ?> ?=([%0 *] der) + ?> ?=([%0 *] rod) %^ request /acme/der/(scot %ud i) der.dir :- ~ @@ -859,7 +873,7 @@ :- %identifiers :- %a %+ turn - dom.der + dom.rod |=(a=turf [%o (my type+s+'dns' value+s+(en-host a) ~)]) == :: @@ -869,11 +883,11 @@ =/ aut=(list (trel @ud @ud purl)) %- zing %+ turn - (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %1 *] a))) - |= [ider=@ud der=^order] - ?> ?=([%1 *] der) + (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %1 *] a))) + |= [ider=@ud rod=^order] + ?> ?=([%1 *] rod) %+ turn - ~(tap by aut.der) + ~(tap by aut.rod) |= [i=@ud aut=auth] ?> ?=([%0 *] aut) [i ider aut.aut] @@ -888,11 +902,11 @@ =/ cal=(list (trel @ud @ud trial)) %- zing %+ turn - (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %1 *] a))) - |= [ider=@ud der=^order] - ?> ?=([%1 *] der) + (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %1 *] a))) + |= [ider=@ud rod=^order] + ?> ?=([%1 *] rod) %+ turn - ~(tap by aut.der) + ~(tap by aut.rod) |= [i=@ud aut=auth] ?> ?=([%1 *] aut) [i ider cal.aut] @@ -919,10 +933,10 @@ %- emil =/ csr=(list (trel @ud purl @ux)) %+ turn - (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %2 *] a))) - |= [i=@ud der=^order] - ?> ?=([%2 *] der) - [i fin.der csr.der] + (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %2 *] a))) + |= [i=@ud rod=^order] + ?> ?=([%2 *] rod) + [i fin.rod csr.rod] %+ turn csr |= [i=@ud fin=purl csr=@ux] ^- card @@ -936,10 +950,10 @@ %- emil =/ url=(list (pair @ud purl)) %+ turn - (skim ~(tap by der) |=(a=[@ud ^order] ?=([@ %2 *] a))) - |= [i=@ud der=^order] - ?> ?=([%2 *] der) - [i der.der] + (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %2 *] a))) + |= [i=@ud rod=^order] + ?> ?=([%2 *] rod) + [i der.rod] %+ turn url |= [i=@ud der=purl] ^- card @@ -994,8 +1008,8 @@ %der =< abet:authorize =/ i=@ud (slav %ud (head t.t.wir)) - =/ rod=^order (~(got by der) i) - ?> ?=([%0 *] rod) + =/ der=^order (~(got by rod) i) + ?> ?=([%0 *] der) =/ loc=@t q:(head (skim q.rep |=((pair @t @t) ?=(%location p)))) =/ url=purl (need (de-purl:html loc)) @@ -1003,44 +1017,44 @@ (order:grab (need (de-json:html q:(need r.rep)))) =/ aut %- ~(gas by *(map @ud auth)) (spun aut.bod |=([a=purl b=@ud] [[b %0 a] +(b)])) - =/ dor=^order [%1 dom.rod exp.bod url fin.bod aut] - this(der (~(put by der) i dor)) + =/ dor=^order [%1 dom.der exp.bod url fin.bod aut] + this(rod (~(put by rod) i dor)) :: %aut =< abet:challenge ?> ?=([@ %der @ *] t.t.wir) =/ i (slav %ud i.t.t.wir) =/ ider (slav %ud i.t.t.t.t.wir) - =/ rod=^order (~(got by der) ider) - ?> ?=([%1 *] rod) - =/ aut=auth (~(got by aut.rod) i) + =/ der=^order (~(got by rod) ider) + ?> ?=([%1 *] der) + =/ aut=auth (~(got by aut.der) i) ?> ?=([%0 *] aut) =/ bod=[dom=turf sas=@t exp=@t cal=[typ=@t sas=@t url=purl tok=@t]] (auth:grab (need (de-json:html q:(need r.rep)))) =/ cal=trial [%http url.cal.bod tok.cal.bod %recv] :: XX parse tok? =/ tau=auth [%1 aut.aut dom.bod cal] - =. rod rod(aut (~(put by aut.rod) i tau)) - this(der (~(put by der) ider rod)) + =. der der(aut (~(put by aut.der) i tau)) + this(rod (~(put by rod) ider der)) :: %cal =< abet:finalize ?> ?=([@ %der @ *] t.t.wir) =/ i (slav %ud i.t.t.wir) =/ ider (slav %ud i.t.t.t.t.wir) - =/ rod=^order (~(got by der) ider) - ?> ?=([%1 *] rod) - =/ aut=auth (~(got by aut.rod) i) + =/ der=^order (~(got by rod) ider) + ?> ?=([%1 *] der) + =/ aut=auth (~(got by aut.der) i) ?> ?=([%1 *] aut) =/ bod=[typ=@t sas=@t url=purl tok=@t] (challenge:grab (need (de-json:html q:(need r.rep)))) ?> ?=(%pending sas.bod) =. sas.cal.aut %pend - =. rod rod(aut (~(put by aut.rod) i aut)) - =. der (~(put by der) ider rod) + =. der der(aut (~(put by aut.der) i aut)) + =. rod (~(put by rod) ider der) =/ fin=(list (pair @ud ^order)) %+ skim - ~(tap by der) + ~(tap by rod) |= a=[@ud ^order] ?& ?=([@ %1 *] a) %+ levy @@ -1050,7 +1064,7 @@ ?=(%pend sas.cal.aut) == == %= this - der %- ~(gas by der) + rod %- ~(gas by rod) %+ turn fin |= [i=@ud der=^order] ^+ [i der] @@ -1089,14 +1103,14 @@ %cer :: XX send configuration to eyre =< abet =/ i=@ud (slav %ud (head t.t.wir)) - =/ rod=^order (~(got by der) i) + =/ der=^order (~(got by rod) i) =/ cer=wain (to-wain:format q:(need r.rep)) - ?> ?=([%2 *] rod) + ?> ?=([%2 *] der) %= this - liv (~(put by liv) dom.rod [key.rod *@da cer]) :: XX exp when? - der (~(del by der) i) - der.hit [rod der.hit] + liv (~(put by liv) dom.der [key.der *@da cer]) :: XX exp when? + rod (~(del by rod) i) + rod.hit [der rod.hit] == == :: @@ -1144,7 +1158,7 @@ ++ add-order |= dom=(list turf) ^+ this - order(der (~(put by der) ~(wyt by der) [%0 dom])) + order(rod (~(put by rod) ~(wyt by rod) [%0 dom])) :: ++ test =, tester:tester @@ -1194,31 +1208,31 @@ ;: weld %- expect-eq !> :- [0x5 0x0 ~] - ~(ren asn1 nul) + ~(ren raw:en:der nul) %- expect-eq !> - [nul (scan ~(ren asn1 nul) decode:asn1)] + [nul (scan ~(ren raw:en:der nul) decode:de:der)] %- expect-eq !> :- [0x2 0x2 0x0 0xbb ~] - ~(ren asn1 int) + ~(ren raw:en:der int) %- expect-eq !> - [int (scan ~(ren asn1 int) decode:asn1)] + [int (scan ~(ren raw:en:der int) decode:de:der)] %- expect-eq !> :- [0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1 ~] - ~(ren asn1 obj) + ~(ren raw:en:der obj) %- expect-eq !> - [obj (scan ~(ren asn1 obj) decode:asn1)] + [obj (scan ~(ren raw:en:der obj) decode:de:der)] %- expect-eq !> :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb. d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 - `@ux`(swp 3 (rep 3 ~(ren asn1 oct))) + `@ux`(swp 3 (en:der oct)) %- expect-eq !> - [oct (scan ~(ren asn1 oct) decode:asn1)] + [oct (scan ~(ren raw:en:der oct) decode:de:der)] %- expect-eq !> :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5. df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 - `@ux`(swp 3 (rep 3 ~(ren asn1 seq))) + `@ux`(swp 3 (en:der seq)) %- expect-eq !> - [seq (scan ~(ren asn1 seq) decode:asn1)] + [seq (scan ~(ren raw:en:der seq) decode:de:der)] == :: ++ test-rsakey From 192ebadd872199cf0a543b307f61b061daf1e38c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 17 May 2018 16:31:33 -0400 Subject: [PATCH 39/95] refactors DER ASN.1 parser --- app/acme.hoon | 68 +++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 953e47382..803780a98 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -156,46 +156,38 @@ %+ cook |*(a=* `spec:asn1`a) :: ^- $-(nail (like spec:asn1)) ;~ pose - %+ stag %int - %+ bass 256 - %+ sear - |= a=(list @) - ^- (unit (list @)) - ?~ a ~ - ?: ?=([@ ~] a) `a - ?. =(0 i.a) `a - ?.((gth i.t.a 127) ~ `t.a) - ;~(pfix (just `@`2) till) - :: - (stag %bit (boss 256 (cook tail ;~(pfix (just `@`3) till)))) :: XX test - (stag %oct (boss 256 ;~(pfix (just `@`4) till))) - (stag %nul (cold ~ ;~(plug (just `@`5) (just `@`0)))) - (stag %obj (boss 256 ;~(pfix (just `@`6) till))) - :: - %+ stag %seq - %+ sear - |=(a=(list @) (rust a (star decode))) :: XX plus? curr? - ;~(pfix (just `@`48) till) - :: - %+ stag %set - %+ sear - |=(a=(list @) (rust a (star decode))) :: XX plus? curr? - ;~(pfix (just `@`49) till) - :: - %+ stag %con - ;~ plug - %+ sear - |= a=@ - ^- (unit [? @udC]) - ?. =(1 (cut 0 [7 1] a)) ~ - :+ ~ - =(1 (cut 0 [5 1] a)) - (dis 0x1f a) - next - till - == + (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) + (stag %bit (boss 256 (cook tail ;~(pfix (tag 3) till)))) :: XX test + (stag %oct (boss 256 ;~(pfix (tag 4) till))) + (stag %nul (cold ~ ;~(plug (tag 5) (tag 0)))) + (stag %obj (boss 256 ;~(pfix (tag 6) till))) + (stag %seq (sear recur ;~(pfix (tag 48) till))) + (stag %set (sear recur ;~(pfix (tag 49) till))) + (stag %con ;~(plug (sear context next) till)) == :: + ++ tag :: tag byte + |=(a=@ (just a)) + :: + ++ int :: @u big endian + |= a=(list @) + ^- (unit (list @)) + ?~ a ~ + ?: ?=([@ ~] a) `a + ?. =(0 i.a) `a + ?.((gth i.t.a 127) ~ `t.a) + :: + ++ recur + |=(a=(list @) (rust a (star decode))) :: XX plus? curr? + :: + ++ context :: context-specific tag + |= a=@ + ^- (unit [? @udC]) + ?. =(1 (cut 0 [7 1] a)) ~ + :+ ~ + =(1 (cut 0 [5 1] a)) + (dis 0x1f a) + :: ++ till :: len-prefixed bytes |= tub/nail ^- (like (list @D)) From a16dde1476b85ca9233343514d4a91dfcf4d9579 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 17 May 2018 18:10:24 -0400 Subject: [PATCH 40/95] comment jihad --- app/acme.hoon | 298 +++++++++++++++++++++++++------------------------- 1 file changed, 152 insertions(+), 146 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 803780a98..4599a35d1 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -3,11 +3,11 @@ :: :::: libraries :: -|% -++ base64 :: rfc4648 - =+ [pad=& url=|] :: section 4 or 5 - |% - ++ en :: encode base64 +|% :: +base64 +++ base64 :: rfc4648 + =+ [pad=& url=|] :: [pad? url-safe?] + |% :: +en:base64 + ++ en :: encode base64 |= tig=@ ^- cord =/ poc (~(dif fo 3) 0 (met 3 tig)) @@ -30,8 +30,8 @@ (cut 3 [(cut 0 [18 6] d) 1] cha) $(pad (rsh 3 3 pad)) == - :: - ++ de :: decode base64 + :: :: +de:base64 + ++ de :: decode base64 |= a=cord ^- (unit @) %+ rush a @@ -54,51 +54,52 @@ == -- :: -++ en-base64url :: padding omitted - ~(en base64 | &) :: per rfc7515 +++ en-base64url :: padding omitted + ~(en base64 | &) :: per rfc7515 :: ++ de-base64url ~(de base64 | &) :: -++ asn1 :: types and constants - |% - += spec - $% [%int p=@u] :: unsigned - [%bit p=@ux] :: pad yerself +++ asn1 + |% :: +spec:asn1 + += spec :: + $% [%int p=@u] :: unsigned + [%bit p=@ux] :: pad yerself [%oct p=@ux] :: [%nul ~] :: - [%obj p=@ux] :: pack yerself + [%obj p=@ux] :: pack yerself [%seq p=(list spec)] :: - [%set p=(list spec)] :: sort yerself - $: %con :: construct yerself - p=[p=? q=@udC] :: [primitive? tag] - q=(list @) :: bytes + [%set p=(list spec)] :: sort yerself + $: %con :: construct yerself + p=[p=? q=@udC] :: [primitive? tag] + q=(list @) :: bytes == == - :: - ++ obj :: oid constants - |% :: rfc4055 - ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 - ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 - ++ rsa-sha-256 0xb.0101.0df7.8648.862a :: 1.2.840.113549.1.1.11 - :: rfc2985 - ++ csr-ext 0xe.0901.0df7.8648.862a :: 1.2.840.113549.1.9.14 - :: rfc3280 - ++ sub-alt 0x11.1d55 :: 2.5.29.17 + :: :: +obj:asn1 + ++ obj :: oid constants + |% :: rfc4055 + ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 + ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 + ++ rsa-sha-256 0xb.0101.0df7.8648.862a :: 1.2.840.113549.1.1.11 + :: rfc2985 + ++ csr-ext 0xe.0901.0df7.8648.862a :: 1.2.840.113549.1.9.14 + :: rfc3280 + ++ sub-alt 0x11.1d55 :: 2.5.29.17 -- -- -:: -++ der - |% - ++ en :: +en:der +:: :: +der +++ der :: DER ASN.1 + |% :: +en:der + ++ en :: encode to atom =< |=(a=spec:asn1 `@ux`(rep 3 ~(ren raw a))) - |% - ++ raw :: bytes + |% :: +raw:en:der + ++ raw :: encode to bytes |_ pec=spec:asn1 - ++ ren :: tlv + :: :: +ren:raw:en:der + ++ ren :: tag-length-value ^- (list @) =/ a lem [tag (weld (len a) a)] - :: + :: :: +tag:raw:en:der ++ tag :: type tag ^- @ ?- pec @@ -111,11 +112,11 @@ [%set *] 49 :: (con 0x20 17) [%con *] :(con q.p.pec 0x80 ?:(p.p.pec 0 0x20)) == - :: + :: :: +lem:raw:en:der ++ lem :: element bytes ^- (list @) ?- pec - [%int *] =/ a (flop (rip 3 p.pec)) + [%int *] =/ a (flop (rip 3 p.pec)) :: note: big-endian ?~ a [0 ~] ?:((lte i.a 127) a [0 a]) :: @@ -138,22 +139,22 @@ :: [%con *] q.pec == - :: + :: :: +len:raw:en:der ++ len :: length bytes |= a=(list @) ^- (list @) =/ b (lent a) ?: (lte b 127) - [b ~] + [b ~] :: note: big-endian [(con 0x80 (met 3 b)) (flop (rip 3 b))] -- -- - :: - ++ de :: +de:der + :: :: +de:der + ++ de :: decode to spec =< |=(a=@ `(unit spec:asn1)`(rush a decode)) - |% - ++ decode :: XX rename - %+ cook |*(a=* `spec:asn1`a) + |% :: +decode:de:der + ++ decode :: DER parser + %+ cook |*(a=* `spec:asn1`a) :: XX rename :: ^- $-(nail (like spec:asn1)) ;~ pose (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) @@ -165,11 +166,11 @@ (stag %set (sear recur ;~(pfix (tag 49) till))) (stag %con ;~(plug (sear context next) till)) == - :: - ++ tag :: tag byte + :: :: +tag:de:der + ++ tag :: tag byte |=(a=@ (just a)) - :: - ++ int :: @u big endian + :: :: +int:de:der + ++ int :: @u big-endian |= a=(list @) ^- (unit (list @)) ?~ a ~ @@ -179,15 +180,15 @@ :: ++ recur |=(a=(list @) (rust a (star decode))) :: XX plus? curr? - :: - ++ context :: context-specific tag + :: :: +context:de:der + ++ context :: context-specific tag |= a=@ ^- (unit [? @udC]) ?. =(1 (cut 0 [7 1] a)) ~ :+ ~ =(1 (cut 0 [5 1] a)) (dis 0x1f a) - :: + :: :: +till:de:der ++ till :: len-prefixed bytes |= tub/nail ^- (like (list @D)) @@ -210,19 +211,19 @@ [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] -- -- -:: -++ rsa :: unpadded! - |% +:: :: +rsa +++ rsa :: textbook RSA + |% :: unpadded! += key $: pub=[n=@ux e=@ux] sek=(unit [d=@ux p=@ux q=@ux]) == - :: - ++ elcm + :: :: +elcm:rsa + ++ elcm :: carmichael totient |= [a=@ b=@] (div (mul a b) d:(egcd a b)) - :: - ++ new-key + :: :: +new-key:rsa + ++ new-key :: =/ e `@ux`65.537 |= [wid=@ eny=@] ^- key @@ -232,14 +233,14 @@ =/ n=@ux (mul p q) =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) [[n e] `[d p q]] - :: - ++ en + :: :: +en:rsa + ++ en :: unpadded RSA encrypt |= [m=@ k=key] ~| %rsa-len ?> (lte (met 0 m) (met 0 n.pub.k)) (~(exp fo n.pub.k) e.pub.k m) - :: - ++ de + :: :: +de:rsa + ++ de :: unpadded RSA decrypt |= [m=@ k=key] :: XX assert rsa-len here too? ~| %rsa-need-ring @@ -247,10 +248,11 @@ =/ fu (fu:number p.u.sek.k q.u.sek.k) (out.fu (exp.fu d.u.sek.k (sit.fu m))) -- -:: -++ rs256 +:: :: +rs256 +++ rs256 :: RSA sha-256 digest |_ k=key:rsa - ++ emsa :: EMSA-PKCS1-v1_5 + :: :: +emsa:rs256 + ++ emsa :: EMSA-PKCS1-v1_5 |= m=@ =/ emlen (met 3 n.pub.k) =/ pec=spec:asn1 @@ -264,18 +266,18 @@ ~|(%emsa-too-short !!) =/ ps (reap (sub emlen (add 3 tlen)) 0xff) %+ rep 3 - (flop (weld [0x0 0x1 ps] [0x0 t])) - :: - ++ sign |=(m=@ (de:rsa (emsa m) k)) - :: - ++ verify + (flop (weld [0x0 0x1 ps] [0x0 t])) :: note: big-endian + :: :: +sign:rs256 + ++ sign |=(m=@ (de:rsa (emsa m) k)) :: + :: :: +verify:rs256 + ++ verify :: |= [s=@ m=@] =((emsa m) (en:rsa s k)) -- -:: +:: :: +pem ++ pem :: rfc7468 - |% - ++ en + |% :: +en:pem + ++ en :: PEM encode |= [lab=@t der=@ux] ^- wain :: XX validate label? @@ -285,8 +287,8 @@ ?~ a [(rap 3 ['-----END ' lab '-----' ~]) ~] [(end 3 64 a) $(a (rsh 3 64 a))] - :: - ++ de + :: :: +de:pem + ++ de :: PEM decode |= [lab=@t mep=wain] ^- (unit @ux) =/ a (sub (lent mep) 2) @@ -296,18 +298,18 @@ ?. =((rap 3 ['-----END ' lab '-----' ~]) (snag a t.mep)) ~ (de:base64 (rap 3 (scag a t.mep))) -- -:: -++ pkcs1 :: rfc3447 - |% +:: :: +pkcs1 +++ pkcs1 :: RSA asym crypto + |% :: rfc3447 ++ spec |% - ++ pass - |= k=key:rsa + ++ pass :: +pass:spec:pkcs1 + |= k=key:rsa :: public key ASN.1 ^- spec:asn1 [%seq [%int n.pub.k] [%int e.pub.k] ~] :: - ++ ring - |= k=key:rsa + ++ ring :: +ring:spec:pkcs1 + |= k=key:rsa :: private key ASN.1 ^- spec:asn1 ~| %rsa-need-ring ?> ?=(^ sek.k) @@ -323,15 +325,15 @@ [%int (~(inv fo p.u.sek.k) q.u.sek.k)] == -- - :: - ++ der - |% - ++ en + :: :: +der:pkcs1 + ++ der :: + |% :: +en:der:pkcs1 + ++ en :: |% ++ pass |=(k=key:rsa `@ux`(en:^der (pass:spec k))) ++ ring |=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- - ++ de + ++ de :: +de:der:pkcs1 |% ++ pass |= a=@ @@ -371,24 +373,24 @@ :: ++ pem |% - ++ en + ++ en :: +en:pem:pkcs1 |% ++ pass |=(k=key:rsa (en:^pem 'RSA PUBLIC KEY' (pass:en:der k))) ++ ring |=(k=key:rsa (en:^pem 'RSA PRIVATE KEY' (ring:en:der k))) -- - ++ de + ++ de :: +de:pem:pkcs1 |% ++ pass |=(mep=wain (biff (de:^pem 'RSA PUBLIC KEY' mep) pass:de:der)) ++ ring |=(mep=wain (biff (de:^pem 'RSA PRIVATE KEY' mep) ring:de:der)) -- -- -- -:: -++ pkcs8 :: rfc5208 - |% :: XX handle other key types? +:: :: +pkcs8 +++ pkcs8 :: asym crypto + |% :: rfc5208 ++ spec - |% - ++ pass + |% :: +pass:spec:pkcs8 + ++ pass :: public key |= k=key:rsa ^- spec:asn1 :~ %seq @@ -398,16 +400,16 @@ :: ++ ring !! -- - :: - ++ der - |% - ++ en + :: :: +der:pkcs8 + ++ der :: + |% :: +en:der:pkcs8 + ++ en :: |% ++ pass |=(k=key:rsa `@ux`(en:^der (pass:spec k))) ++ ring !! ::|=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- - :: - ++ de + :: :: +de:der:pkcs8 + ++ de :: |% ++ pass |= a=@ @@ -425,39 +427,39 @@ ++ ring !! -- -- - :: - ++ pem - |% - ++ en + :: :: +pem:pkcs8 + ++ pem :: + |% :: +en:pem:pkcs8 + ++ en :: |% ++ pass |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k))) ++ ring !! ::|=(k=key:rsa (en:^pem 'PUBLIC KEY' (ring:en:der k))) -- - :: - ++ de + :: :: +de:pem:pkcs8 + ++ de :: |% ++ pass |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der)) ++ ring !! ::|=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) -- -- -- -:: -++ pkcs10 :: rfc2986 - => |% - += csr [key=key:rsa hot=(list (list @t))] :: XX other key types? +:: :: +pkcs10 +++ pkcs10 :: certificate request + => |% :: rfc2986 + += csr [key=key:rsa hot=(list (list @t))] -- |% ++ spec - |% - ++ host + |% :: +host:spec:pkcs10 + ++ host :: subject-alt names |= hot=(list (list @t)) ^- spec:asn1 :- %seq %+ turn hot |=(h=(list @t) [%con [& 2] (rip 3 (en-host h))]) - :: - ++ cert :: XX rename - |= csr + :: :: +cert:spec:pkcs10 + ++ cert :: cert request info + |= csr :: XX rename ^- spec:asn1 :~ %seq [%int 0] @@ -473,33 +475,33 @@ [%obj sub-alt:obj:asn1] [%oct (en:^der (host hot))] == == == == == - :: - ++ sign + :: :: +sign:spec:pkcs10 + ++ sign :: signed request |= csr ^- spec:asn1 =/ cer (cert key hot) :~ %seq cer [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] - [%bit (swp 3 (~(sign rs256 key) (en:^der cer)))] + [%bit (swp 3 (~(sign rs256 key) (en:^der cer)))] :: big-endian == -- - :: + :: :: +der:pkcs10 ++ der |% ++ en |=(a=csr `@ux`(en:^der (sign:spec a))) ++ de !! -- - :: + :: :: +pem:pkcs10 ++ pem |% ++ en |=(a=csr (en:^pem 'CERTIFICATE REQUEST' (en:der a))) ++ de !! :: |=(mep=wain (biff (de:^pem 'CERTIFICATE REQUEST' mep) de:der)) -- -- -:: -++ en-json-sort :: print json - |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) +:: :: +en-json-sort +++ en-json-sort :: json w/ sorted keys + |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) :: XX rename :: :: ++apex:en-json:html ++ apex =, en-json:html @@ -544,20 +546,21 @@ ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)]) == -- -:: -++ jwk :: rfc7517 - |% +:: :: +jwk +++ jwk :: json web keys + |% :: rfc7517 ++ en - |% - ++ pass + |% :: +pass:en:jwk + ++ pass :: encode public key |= k=key:rsa ^- json :- %o %- my :~ kty+s+'RSA' - n+s+(en-base64url (swp 3 n.pub.k)) + n+s+(en-base64url (swp 3 n.pub.k)) :: note: big-endian e+s+(en-base64url (swp 3 e.pub.k)) == - ++ ring + :: :: +ring:en:jwk + ++ ring :: encode private key |= k=key:rsa ^- json ~| %rsa-need-ring @@ -572,8 +575,8 @@ == -- ++ de - |% - ++ pass + |% :: +pass:de:jwk + ++ pass :: decode public key =, dejs-soft:format %+ ci |= [kty=@t n=(unit @) e=(unit @)] @@ -586,7 +589,8 @@ n+(cu de-base64url so) e+(cu de-base64url so) == - ++ ring + :: :: +ring:de:jwk + ++ ring :: decode private key =, dejs-soft:format %+ ci |= $: kty=@t @@ -610,20 +614,20 @@ q+(cu de-base64url so) == -- - :: - ++ thumb :: rfc7638 - |% + :: :: +thumb:jwk + ++ thumb :: thumbprint + |% :: rfc7638 ++ ring !! ++ pass |= k=key:rsa (en-base64url (shax (crip (en-json-sort aor (pass:en k))))) -- -- -:: -++ jws :: rfc7515 - |% - ++ sign - |= [k=key:rsa pro=json lod=json] +:: :: +jws +++ jws :: json web signature + |% :: rfc7515 + ++ sign :: +sign:jws + |= [k=key:rsa pro=json lod=json] :: flattened signature |^ ^- json =. pro header =/ protect=cord (encode pro) @@ -651,14 +655,14 @@ :: ++ verify !! -- -:: +:: :: +eor ++ eor :: explicit order |= [com=$-([@ @] ?) lit=(list)] |= [a=* b=*] ^- ? (fall (bind (both (find ~[a] lit) (find ~[b] lit)) com) |) -:: -++ en-host +:: :: +en-host +++ en-host :: rendor host |= hot=(list @t) ^- @t =| out=(list @t) @@ -668,6 +672,8 @@ (rap 3 [i.hot out]) $(out ['.' i.hot out], hot t.hot) :: +:::: acme api response json reparsers +:: ++ grab =, dejs:format |% From 671cc1d277d09b596a8bf615a16ad6fe5a722ab9 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 02:05:12 -0400 Subject: [PATCH 41/95] tests challenges locally before notifying ACME server --- app/acme.hoon | 133 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 87 insertions(+), 46 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 4599a35d1..71a285e73 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -853,14 +853,14 @@ reg.dir `[%o (my [['termsOfServiceAgreed' b+&] ~])] :: -++ order +++ new-order ^+ this ?~ reg.act this :: XX pending registration assumed %- emil %+ turn - (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %0 *] a))) - |= [i=@ud rod=^order] + (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %0 *] a))) + |= [i=@ud rod=order] ^- card ?> ?=([%0 *] rod) %^ request /acme/der/(scot %ud i) @@ -881,8 +881,8 @@ =/ aut=(list (trel @ud @ud purl)) %- zing %+ turn - (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %1 *] a))) - |= [ider=@ud rod=^order] + (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) + |= [ider=@ud rod=order] ?> ?=([%1 *] rod) %+ turn ~(tap by aut.rod) @@ -894,45 +894,80 @@ ^- card (request /acme/aut/(scot %ud i)/der/(scot %ud ider) aut ~) :: -++ challenge +++ save-challenge ^+ this %- emil =/ cal=(list (trel @ud @ud trial)) %- zing %+ turn - (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %1 *] a))) - |= [ider=@ud rod=^order] + (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) + |= [ider=@ud rod=order] ?> ?=([%1 *] rod) %+ turn ~(tap by aut.rod) |= [i=@ud aut=auth] ?> ?=([%1 *] aut) [i ider cal.aut] - %- zing %+ turn cal |= [i=@ud ider=@ud cal=trial] - ^- (list card) - :~ :^ %well - /acme/wel/(scot %ud i)/der/(scot %ud ider) - /acme-challenge/[tok.cal] - :+ ~ - /text/plain - %- as-octs:mimes:html - (rap 3 [tok.cal '.' (pass:thumb:jwk key.act) ~]) - :: - %^ request - /acme/cal/(scot %ud i)/der/(scot %ud ider) - cal.cal - `[%o ~] - == + ^- card + :^ %well + /acme/wel/(scot %ud i)/der/(scot %ud ider) + /acme-challenge/[tok.cal] + :+ ~ + /text/plain + %- as-octs:mimes:html + (rap 3 [tok.cal '.' (pass:thumb:jwk key.act) ~]) :: -++ finalize +++ test-challenge + ^+ this + %- emil + =/ cal=(list [@ud @ud turf trial]) + %- zing + %+ turn + (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) + |= [ider=@ud rod=order] + ?> ?=([%1 *] rod) + %+ turn + ~(tap by aut.rod) + |= [i=@ud aut=auth] + ?> ?=([%1 *] aut) + [i ider dom.aut cal.aut] + %+ turn cal + |= [i=@ud ider=@ud dom=turf cal=trial] + ^- card + =/ wir=wire /acme/tcal/(scot %ud i)/der/(scot %ud ider) + =/ pat=path /'.well-known'/acme-challenge/[tok.cal] + =/ pul=purl [[| ~ [%& dom]] [~ pat] ~] + (request wir pul ~) +:: +++ finalize-challenge + ^+ this + %- emil + =/ cal=(list (trel @ud @ud purl)) + %- zing + %+ turn + (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) + |= [ider=@ud rod=order] + ?> ?=([%1 *] rod) + %+ turn + ~(tap by aut.rod) + |= [i=@ud aut=auth] + ?> ?=([%1 *] aut) + [i ider cal.cal.aut] + %+ turn cal + |= [i=@ud ider=@ud cal=purl] + ^- card + =/ wir=wire /acme/cal/(scot %ud i)/der/(scot %ud ider) + (request wir cal `[%o ~]) +:: +++ finalize-order ^+ this %- emil =/ csr=(list (trel @ud purl @ux)) %+ turn - (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %2 *] a))) - |= [i=@ud rod=^order] + (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %2 *] a))) + |= [i=@ud rod=order] ?> ?=([%2 *] rod) [i fin.rod csr.rod] %+ turn csr @@ -948,8 +983,8 @@ %- emil =/ url=(list (pair @ud purl)) %+ turn - (skim ~(tap by rod) |=(a=[@ud ^order] ?=([@ %2 *] a))) - |= [i=@ud rod=^order] + (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %2 *] a))) + |= [i=@ud rod=order] ?> ?=([%2 *] rod) [i der.rod] %+ turn url @@ -966,6 +1001,8 @@ =? non ?=(^ ron) q.i.ron ?. ?=(%2 (div p.rep 100)) ~& %lack-of-success + ?: ?=(%tcal i.t.wir) + abet:test-challenge :: XX sleep? =/ bod=[typ=@t det=@t] (error:grab (need (de-json:html q:(need r.rep)))) ?: =('urn:ietf:params:acme:error:badNonce' typ.bod) @@ -989,13 +1026,13 @@ ?. ?=([%next ^] t.t.wir) register ?+ i.t.t.t.wir this - %der order + %der new-order %aut authorize - %cal challenge + %cal finalize-challenge == :: %reg - =< abet:order + =< abet:new-order =/ bod=[id=@t wen=@t sas=@t] :: XX @da (acct:grab (need (de-json:html q:(need r.rep)))) =/ loc=@t @@ -1006,7 +1043,7 @@ %der =< abet:authorize =/ i=@ud (slav %ud (head t.t.wir)) - =/ der=^order (~(got by rod) i) + =/ der=order (~(got by rod) i) ?> ?=([%0 *] der) =/ loc=@t q:(head (skim q.rep |=((pair @t @t) ?=(%location p)))) @@ -1015,15 +1052,15 @@ (order:grab (need (de-json:html q:(need r.rep)))) =/ aut %- ~(gas by *(map @ud auth)) (spun aut.bod |=([a=purl b=@ud] [[b %0 a] +(b)])) - =/ dor=^order [%1 dom.der exp.bod url fin.bod aut] + =/ dor=order [%1 dom.der exp.bod url fin.bod aut] this(rod (~(put by rod) i dor)) :: %aut - =< abet:challenge + =< abet:test-challenge:save-challenge ?> ?=([@ %der @ *] t.t.wir) =/ i (slav %ud i.t.t.wir) =/ ider (slav %ud i.t.t.t.t.wir) - =/ der=^order (~(got by rod) ider) + =/ der=order (~(got by rod) ider) ?> ?=([%1 *] der) =/ aut=auth (~(got by aut.der) i) ?> ?=([%0 *] aut) @@ -1034,13 +1071,17 @@ =/ tau=auth [%1 aut.aut dom.bod cal] =. der der(aut (~(put by aut.der) i tau)) this(rod (~(put by rod) ider der)) + :: + %tcal + :: XX check content type and response body + abet:finalize-challenge :: %cal - =< abet:finalize + =< abet:finalize-order ?> ?=([@ %der @ *] t.t.wir) =/ i (slav %ud i.t.t.wir) =/ ider (slav %ud i.t.t.t.t.wir) - =/ der=^order (~(got by rod) ider) + =/ der=order (~(got by rod) ider) ?> ?=([%1 *] der) =/ aut=auth (~(got by aut.der) i) ?> ?=([%1 *] aut) @@ -1050,10 +1091,10 @@ =. sas.cal.aut %pend =. der der(aut (~(put by aut.der) i aut)) =. rod (~(put by rod) ider der) - =/ fin=(list (pair @ud ^order)) + =/ fin=(list (pair @ud order)) %+ skim ~(tap by rod) - |= a=[@ud ^order] + |= a=[@ud order] ?& ?=([@ %1 *] a) %+ levy ~(tap by aut.a) @@ -1064,7 +1105,7 @@ %= this rod %- ~(gas by rod) %+ turn fin - |= [i=@ud der=^order] + |= [i=@ud der=order] ^+ [i der] ?> ?=([%1 *] der) =/ k=key:rsa rekey :: XX reuse @@ -1101,7 +1142,7 @@ %cer :: XX send configuration to eyre =< abet =/ i=@ud (slav %ud (head t.t.wir)) - =/ der=^order (~(got by rod) i) + =/ der=order (~(got by rod) i) =/ cer=wain (to-wain:format q:(need r.rep)) ?> ?=([%2 *] der) @@ -1118,17 +1159,17 @@ ?+ a ~& +<+.this [~ this] %init abet:init - %order abet:order + %order abet:new-order %auth abet:authorize - %trial abet:challenge - %final abet:finalize + %trial abet:test-challenge + %final abet:finalize-order %poll abet:poll-order %our abet:(add-order /org/urbit/(crip +:(scow %p our.bow)) ~) %test test == :: ++ poke-path - |=(a=path (add-order a ~)) + |=(a=path abet:(add-order a ~)) :: :: ++ prep _[~ this] ++ prep @@ -1156,7 +1197,7 @@ ++ add-order |= dom=(list turf) ^+ this - order(rod (~(put by rod) ~(wyt by rod) [%0 dom])) + new-order(rod (~(put by rod) ~(wyt by rod) [%0 dom])) :: ++ test =, tester:tester From 831813c660c5bc6cc1fdf3ee247b1d5fa577f58d Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 11:02:35 -0400 Subject: [PATCH 42/95] fixes badNonce retry, archives old orders when adding a new one --- app/acme.hoon | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 71a285e73..5e9f3333d 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -844,8 +844,8 @@ ++ nonce |= nex=wire ^+ this - ?> |(?=(~ nex) ?=([%next *] nex)) - (emit (request (weld `wire`/acme/non nex) non.dir ~)) + ?> ?=([%next *] nex) + (emit (request (weld `wire`/acme/non `wire`nex) non.dir ~)) :: ++ register %- emit(reg.act ~) @@ -1006,17 +1006,15 @@ =/ bod=[typ=@t det=@t] (error:grab (need (de-json:html q:(need r.rep)))) ?: =('urn:ietf:params:acme:error:badNonce' typ.bod) - =/ nex=wire - ?. ?=(?(%der %aut %cal) i.t.wir) - ~ - /next/[i.t.wir] - abet:(nonce nex) + ?. ?=(?(%reg %der %aut %cal %fin) i.t.wir) + ~&(unrecoverable-bad-nonce+wir abet:this) + abet:(nonce /next/[i.t.wir]) :: XX challenge is not pending :: XX order can't be finalized - [~ this] + abet:this ?+ i.t.wir !! %dir - =< abet:(nonce ~) + =< abet:(nonce /next/reg) =/ bod=^directory (directory:grab (need (de-json:html q:(need r.rep)))) this(dir bod) @@ -1024,8 +1022,10 @@ %non =< abet ?. ?=([%next ^] t.t.wir) - register - ?+ i.t.t.t.wir this + ~&(unrecognized-nonce-wire+wir this) + =* nex i.t.t.t.wir + ?+ nex ~&(unknown-nonce-next+nex this) + %reg register %der new-order %aut authorize %cal finalize-challenge @@ -1197,7 +1197,12 @@ ++ add-order |= dom=(list turf) ^+ this - new-order(rod (~(put by rod) ~(wyt by rod) [%0 dom])) + :: XX temporarily force one at a time + :: new-order(rod (~(put by rod) ~(wyt by rod) [%0 dom])) + %= new-order + rod.hit (weld ~(val by rod) rod.hit) + rod (~(put by ^+(rod ~)) ~(wyt by rod) [%0 dom]) + == :: ++ test =, tester:tester From 2198de77d85365c84a276463a07d4be8124eed59 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 11:34:55 -0400 Subject: [PATCH 43/95] support empty re-registration response, minor cleanup --- app/acme.hoon | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 5e9f3333d..0ac6d227f 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -4,8 +4,8 @@ :::: libraries :: |% :: +base64 -++ base64 :: rfc4648 - =+ [pad=& url=|] :: [pad? url-safe?] +++ base64 :: [pad? url-safe?] + =+ [pad=& url=|] :: |% :: +en:base64 ++ en :: encode base64 |= tig=@ @@ -1012,6 +1012,7 @@ :: XX challenge is not pending :: XX order can't be finalized abet:this + ~| sigh-fail+rep ?+ i.t.wir !! %dir =< abet:(nonce /next/reg) @@ -1033,12 +1034,16 @@ :: %reg =< abet:new-order - =/ bod=[id=@t wen=@t sas=@t] :: XX @da - (acct:grab (need (de-json:html q:(need r.rep)))) =/ loc=@t q:(head (skim q.rep |=((pair @t @t) ?=(%location p)))) - ?> ?=(%valid sas.bod) - this(reg.act `[wen.bod loc]) + =/ wen=@t :: XX @da + ?~ r.rep + (scot %da now.bow) + =/ bod=[id=@t wen=@t sas=@t] + (acct:grab (need (de-json:html q.u.r.rep))) + ?> ?=(%valid sas.bod) + wen.bod + this(reg.act `[wen loc]) :: %der =< abet:authorize @@ -1159,6 +1164,7 @@ ?+ a ~& +<+.this [~ this] %init abet:init + %reg abet:register %order abet:new-order %auth abet:authorize %trial abet:test-challenge @@ -1169,7 +1175,7 @@ == :: ++ poke-path - |=(a=path abet:(add-order a ~)) + |=(a=path abet:new-order:(add-order a ~)) :: :: ++ prep _[~ this] ++ prep From 2bbd8af93086ed9dd151adfdf6a13361bc8a8f60 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 11:51:19 -0400 Subject: [PATCH 44/95] use only one certificate key (for now) --- app/acme.hoon | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 0ac6d227f..2d6106b34 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -790,6 +790,7 @@ act=acct :: service account non=@t :: nonce from last rod=(map @ud order) :: active orders + cey=key:rsa :: cert key liv=(map (list turf) config) :: active config hit=history :: a foreign country == :: @@ -1113,9 +1114,9 @@ |= [i=@ud der=order] ^+ [i der] ?> ?=([%1 *] der) - =/ k=key:rsa rekey :: XX reuse - =/ csr=@ux (en:der:pkcs10 k dom.der) - [i %2 dom.der exp.der der.der fin.der k csr] + :: =/ k=key:rsa rekey :: XX reuse + =/ csr=@ux (en:der:pkcs10 cey dom.der) + [i %2 dom.der exp.der der.der fin.der cey csr] :: XX save pending authz somewhere instead of just dropping them == :: @@ -1196,7 +1197,7 @@ ++ init =/ url 'https://acme-staging-v02.api.letsencrypt.org/directory' - directory(bas (need (de-purl:html url)), act [rekey ~]) + directory(bas (need (de-purl:html url)), act [rekey ~], cey rekey) :: XX wait for DNS binding confirmation? :: (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) :: From 0eae33af9e3fc532639ae2c9e94885749c79ef81 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 12:23:34 -0400 Subject: [PATCH 45/95] disables some overly-restrictive json response parsing --- app/acme.hoon | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 2d6106b34..bc48a8edf 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1091,9 +1091,10 @@ ?> ?=([%1 *] der) =/ aut=auth (~(got by aut.der) i) ?> ?=([%1 *] aut) - =/ bod=[typ=@t sas=@t url=purl tok=@t] - (challenge:grab (need (de-json:html q:(need r.rep)))) - ?> ?=(%pending sas.bod) + :: XX 204 assuming pending? + :: =/ bod=[typ=@t sas=@t url=purl tok=@t] + :: (challenge:grab (need (de-json:html q:(need r.rep)))) + :: ?> ?=(%pending sas.bod) =. sas.cal.aut %pend =. der der(aut (~(put by aut.der) i aut)) =. rod (~(put by rod) ider der) @@ -1121,8 +1122,9 @@ == :: %fin - =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] - (order:grab (need (de-json:html q:(need r.rep)))) + :: XX rep body missing authorizations + :: =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] + :: (order:grab (need (de-json:html q:(need r.rep)))) :: XX check status? (i don't think failures get here) abet:poll-order :: From 8567866e89a364746ce99c80780d958d7c01d89a Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 12:27:28 -0400 Subject: [PATCH 46/95] fixes the nonce retry fix --- app/acme.hoon | 1 + 1 file changed, 1 insertion(+) diff --git a/app/acme.hoon b/app/acme.hoon index bc48a8edf..e235c8a7f 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1031,6 +1031,7 @@ %der new-order %aut authorize %cal finalize-challenge + %fin finalize-order == :: %reg From 9b7c5f93379f09fc0da49818ad167d95d5f5c452 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 12:36:39 -0400 Subject: [PATCH 47/95] insure that account and certificate keys are different determinism ftw! --- app/acme.hoon | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index e235c8a7f..9e6b5b339 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1189,18 +1189,23 @@ [~ this(+<+ u.old)] :: ++ rekey :: XX do something about this + |= eny=@ =| i=@ |- ^- key:rsa - =/ k (new-key:rsa 2.048 eny.bow) + =/ k (new-key:rsa 2.048 eny) =/ m (met 0 n.pub.k) ?: =(0 (mod m 8)) k ~& [%key iter=i width=m] - $(i +(i), eny.bow +(eny.bow)) + $(i +(i), eny +(eny)) :: ++ init =/ url 'https://acme-staging-v02.api.letsencrypt.org/directory' - directory(bas (need (de-purl:html url)), act [rekey ~], cey rekey) + %= directory + bas (need (de-purl:html url)) + act [(rekey (shas %act eny.bow)) ~] + cey (rekey (shas %act eny.bow)) + == :: XX wait for DNS binding confirmation? :: (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) :: From b4197152fedf1256c829880c976b96b73d20175d Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 12:50:45 -0400 Subject: [PATCH 48/95] parses order responses more minimally --- app/acme.hoon | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 9e6b5b339..d450c3cdf 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -704,11 +704,15 @@ ['status' so] == :: + ++ finalizing-order + %- ot + :~ ['expires' so] :: XX (su iso-8601) + ['status' so] + == + :: ++ final-order %- ot - :~ ['authorizations' (ar json-purl)] - ['finalize' json-purl] - ['expires' so] :: XX (su iso-8601) + :~ ['expires' so] :: XX (su iso-8601) ['status' so] ['certificate' json-purl] == @@ -1124,6 +1128,7 @@ :: %fin :: XX rep body missing authorizations + :: XX finalizing-order :: =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] :: (order:grab (need (de-json:html q:(need r.rep)))) :: XX check status? (i don't think failures get here) @@ -1133,15 +1138,15 @@ =/ i=@ud (slav %ud (head t.t.wir)) =/ raw=json (need (de-json:html q:(need r.rep))) - =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] - (order:grab raw) + =/ bod=[exp=@t sas=@t] + (finalizing-order:grab raw) ?+ sas.bod ~&(poll-order-status+sas.bod abet) %invalid abet :: XX check authz, retry order? %pending abet:poll-order %processing abet:poll-order %valid =< abet - =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t cer=purl] + =/ bod=[exp=@t sas=@t cer=purl] (final-order:grab raw) :: XX json reparser unit %- emit :: XX accept hed (request /acme/cer/(scot %ud i) cer.bod ~) From 77391241c7407da2ca31592ab55378031dacf75c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 18 May 2018 12:58:55 -0400 Subject: [PATCH 49/95] really make sure account/certificate keys are different --- app/acme.hoon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index d450c3cdf..4d1e5e326 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1208,8 +1208,8 @@ 'https://acme-staging-v02.api.letsencrypt.org/directory' %= directory bas (need (de-purl:html url)) - act [(rekey (shas %act eny.bow)) ~] - cey (rekey (shas %act eny.bow)) + act [(rekey eny.bow) ~] + cey (rekey (mix eny.bow (shaz now.bow))) == :: XX wait for DNS binding confirmation? :: (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) From 2a83c41f24c29649b3624c65a971c5e44ecccd94 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 21 May 2018 16:43:56 -0700 Subject: [PATCH 50/95] removes redundant new-order --- app/acme.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/acme.hoon b/app/acme.hoon index 4d1e5e326..96d61a896 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1184,7 +1184,7 @@ == :: ++ poke-path - |=(a=path abet:new-order:(add-order a ~)) + |=(a=path abet:(add-order a ~)) :: :: ++ prep _[~ this] ++ prep From 8c0eea3a19a11c81cd94aefb821517168c21bd5d Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 24 May 2018 09:57:06 -0700 Subject: [PATCH 51/95] renames +en-host to +join --- app/acme.hoon | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 96d61a896..4cb0c3220 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -456,7 +456,7 @@ ^- spec:asn1 :- %seq %+ turn hot - |=(h=(list @t) [%con [& 2] (rip 3 (en-host h))]) + |=(h=(list @t) [%con [& 2] (rip 3 (join '.' h))]) :: :: +cert:spec:pkcs10 ++ cert :: cert request info |= csr :: XX rename @@ -661,16 +661,16 @@ |= [a=* b=*] ^- ? (fall (bind (both (find ~[a] lit) (find ~[b] lit)) com) |) -:: :: +en-host -++ en-host :: rendor host - |= hot=(list @t) +:: :: +join +++ join :: join cords w/ sep + |= [sep=@t hot=(list @t)] ^- @t =| out=(list @t) ?> ?=(^ hot) |- ^- @t ?~ t.hot (rap 3 [i.hot out]) - $(out ['.' i.hot out], hot t.hot) + $(out [sep i.hot out], hot t.hot) :: :::: acme api response json reparsers :: @@ -877,7 +877,7 @@ :- %a %+ turn dom.rod - |=(a=turf [%o (my type+s+'dns' value+s+(en-host a) ~)]) + |=(a=turf [%o (my type+s+'dns' value+s+(join '.' a) ~)]) == :: ++ authorize From f7a6ad1fb2ccc465288c46cae569d9d03989a8ff Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 25 May 2018 00:28:26 -0700 Subject: [PATCH 52/95] first pass new-style comments for library cores --- app/acme.hoon | 514 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 373 insertions(+), 141 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 4cb0c3220..7d955b7a7 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1,13 +1,20 @@ /+ tester =, eyre :: -:::: libraries +:::: %zuse additions :: -|% :: +base64 -++ base64 :: [pad? url-safe?] - =+ [pad=& url=|] :: - |% :: +en:base64 - ++ en :: encode base64 +|% +:: |base64: flexible base64 encoding for little-endian atoms +:: +++ base64 + :: pad: include padding when encoding, require when decoding + :: url: use url-safe characters '-' for '+' and '_' for '/' + :: + =+ [pad=& url=|] + |% + :: +en:base64: encode atom to base64 cord + :: + ++ en |= tig=@ ^- cord =/ poc (~(dif fo 3) 0 (met 3 tig)) @@ -30,11 +37,13 @@ (cut 3 [(cut 0 [18 6] d) 1] cha) $(pad (rsh 3 3 pad)) == - :: :: +de:base64 - ++ de :: decode base64 + :: +de:base64: decode base64 cord to (unit @) + :: + ++ de |= a=cord ^- (unit @) %+ rush a + :: XX refactor and expose parser combinator %+ cook (cury swp 3) %+ bass 64 %+ cook welp @@ -53,29 +62,72 @@ (cold (reap b %0) (easy ~)) == -- +:: +en-base64url: url-safe base64 encoding, without padding :: -++ en-base64url :: padding omitted - ~(en base64 | &) :: per rfc7515 +++ en-base64url + ~(en base64 | &) +:: +de-base64url: url-safe base64 decoding, without padding :: ++ de-base64url ~(de base64 | &) :: +:::: %/lib/pkcs +:: +:: |asn1: small selection of types and constants for ASN.1 +:: +:: a minimal representation of some basic ASN.1 types, +:: created to support PKCS keys, digests, and cert requests +:: ++ asn1 - |% :: +spec:asn1 - += spec :: - $% [%int p=@u] :: unsigned - [%bit p=@ux] :: pad yerself - [%oct p=@ux] :: - [%nul ~] :: - [%obj p=@ux] :: pack yerself - [%seq p=(list spec)] :: - [%set p=(list spec)] :: sort yerself + |% + :: +spec:asn1: minimal representations of basic ASN.1 types + += spec + $% :: %int: arbitrary-sized, unsigned integers + :: + :: unsigned integers, represented as having a positive sign. + :: negative integers would be two's complement in DER, + :: but we don't need them. + :: + [%int p=@u] + :: %bit: very minimal support for bit strings + :: + :: specifically, values must already be padded and byte-aligned. + :: note that leading zeros are significant in ASN.1 bit strings, + :: so atomic encoding would be insufficient for complete support. + :: + [%bit p=@ux] + :: %oct: octets in little-endian byte order + :: + [%oct p=@ux] + :: %nul: fully supported! + :: + [%nul ~] + :: %obj: object identifiers, pre-packed + :: + :: object identifiers are technically a sequence of integers, + :: represented here in their already-encoded form. + :: + [%obj p=@ux] + :: %seq: a list of specs + :: + [%seq p=(list spec)] + :: %set: a logical set of specs + :: + :: implemented here as a list for the sake of simplicity. + :: encodings must dedupe and sort the list appropriately + :: + [%set p=(list spec)] + :: %con: context-specific + :: + :: here be dragons + :: $: %con :: construct yerself p=[p=? q=@udC] :: [primitive? tag] q=(list @) :: bytes == == - :: :: +obj:asn1 - ++ obj :: oid constants + :: |obj:asn1: constant object ids, pre-encoded + :: + ++ obj |% :: rfc4055 ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 @@ -86,10 +138,13 @@ ++ sub-alt 0x11.1d55 :: 2.5.29.17 -- -- -:: :: +der -++ der :: DER ASN.1 - |% :: +en:der - ++ en :: encode to atom +:: |der: distinguished encoding rules for ASN.1 +:: +++ der + |% + :: +en:der: encode +spec:asn1 to atom + :: + ++ en =< |=(a=spec:asn1 `@ux`(rep 3 ~(ren raw a))) |% :: +raw:en:der ++ raw :: encode to bytes @@ -149,12 +204,15 @@ [(con 0x80 (met 3 b)) (flop (rip 3 b))] -- -- - :: :: +de:der - ++ de :: decode to spec + :: +de:der: decode atom to +spec:asn1 + :: + ++ de =< |=(a=@ `(unit spec:asn1)`(rush a decode)) - |% :: +decode:de:der - ++ decode :: DER parser - %+ cook |*(a=* `spec:asn1`a) :: XX rename + |% + :: +decode:de:der: DER parser combinator XX rename + :: + ++ decode + %+ cook |*(a=* `spec:asn1`a) :: XX fix :: ^- $-(nail (like spec:asn1)) ;~ pose (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) @@ -166,30 +224,37 @@ (stag %set (sear recur ;~(pfix (tag 49) till))) (stag %con ;~(plug (sear context next) till)) == - :: :: +tag:de:der - ++ tag :: tag byte + :: +tag:de:der: parse tag byte + :: + ++ tag |=(a=@ (just a)) - :: :: +int:de:der - ++ int :: @u big-endian + :: +int:de:der: sear unsigned big-endian bytes + :: + ++ int |= a=(list @) ^- (unit (list @)) ?~ a ~ ?: ?=([@ ~] a) `a ?. =(0 i.a) `a ?.((gth i.t.a 127) ~ `t.a) + :: +recur:de:der: parse bytes for a list of +spec:asn1 :: ++ recur |=(a=(list @) (rust a (star decode))) :: XX plus? curr? - :: :: +context:de:der - ++ context :: context-specific tag + :: +context:de:der: decode context-specific tag byte + :: + ++ context |= a=@ ^- (unit [? @udC]) ?. =(1 (cut 0 [7 1] a)) ~ :+ ~ =(1 (cut 0 [5 1] a)) (dis 0x1f a) - :: :: +till:de:der - ++ till :: len-prefixed bytes + :: +till:de:der: parser combinator for len-prefixed bytes + :: + :: advance until + :: + ++ till |= tub/nail ^- (like (list @D)) ?~ q.tub @@ -211,19 +276,28 @@ [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] -- -- -:: :: +rsa -++ rsa :: textbook RSA - |% :: unpadded! +:: |rsa: primitive, textbook RSA +:: +:: unpadded, unsafe, unsuitable for encryption! +:: +++ rsa + |% + :: +key:rsa: rsa public or private key + :: += key - $: pub=[n=@ux e=@ux] + $: :: pub: public parameters (n=modulus, e=pub-exponent) + pub=[n=@ux e=@ux] + :: sek: secret parameters (d=private-exponent, p/q=primes) sek=(unit [d=@ux p=@ux q=@ux]) == - :: :: +elcm:rsa - ++ elcm :: carmichael totient + :: +elcm:rsa: carmichael totient + :: + ++ elcm |= [a=@ b=@] (div (mul a b) d:(egcd a b)) - :: :: +new-key:rsa - ++ new-key :: + :: +new-key:rsa + :: + ++ new-key =/ e `@ux`65.537 |= [wid=@ eny=@] ^- key @@ -233,13 +307,19 @@ =/ n=@ux (mul p q) =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) [[n e] `[d p q]] - :: :: +en:rsa - ++ en :: unpadded RSA encrypt + :: +en:rsa: primitive RSA encryption + :: + :: ciphertext = message^e (mod n) + :: + ++ en |= [m=@ k=key] ~| %rsa-len ?> (lte (met 0 m) (met 0 n.pub.k)) (~(exp fo n.pub.k) e.pub.k m) - :: :: +de:rsa + :: +de:rsa: primitive RSA decryption + :: + :: message = ciphertext^d (mod e) + :: ++ de :: unpadded RSA decrypt |= [m=@ k=key] :: XX assert rsa-len here too? @@ -248,11 +328,15 @@ =/ fu (fu:number p.u.sek.k q.u.sek.k) (out.fu (exp.fu d.u.sek.k (sit.fu m))) -- -:: :: +rs256 -++ rs256 :: RSA sha-256 digest +:: +rs256: RSA signatures over a sha-256 digest +:: +++ rs256 |_ k=key:rsa - :: :: +emsa:rs256 - ++ emsa :: EMSA-PKCS1-v1_5 + :: +emsa:rs256: message digest + :: + :: padded, DER encoded sha-256 hash (EMSA-PKCS1-v1_5) + :: + ++ emsa |= m=@ =/ emlen (met 3 n.pub.k) =/ pec=spec:asn1 @@ -267,17 +351,31 @@ =/ ps (reap (sub emlen (add 3 tlen)) 0xff) %+ rep 3 (flop (weld [0x0 0x1 ps] [0x0 t])) :: note: big-endian - :: :: +sign:rs256 - ++ sign |=(m=@ (de:rsa (emsa m) k)) :: - :: :: +verify:rs256 - ++ verify :: + :: +sign:rs256: sign message + :: + :: an RSA signature is the primitive decryption of the message hash + :: + ++ sign + |=(m=@ (de:rsa (emsa m) k)) + :: +verify:rs256: verify signature + :: + :: RSA signature verification confirms that the primitive encryption + :: of the signature matches the message hash + :: + ++ verify |= [s=@ m=@] =((emsa m) (en:rsa s k)) -- -:: :: +pem -++ pem :: rfc7468 - |% :: +en:pem - ++ en :: PEM encode +:: |pem: generic PEM implementation (rfc7468) +:: +:: PEM is the base64 encoding of DER encoded data, with BEGIN and +:: END labels indicating some type. +:: +++ pem + |% + :: +en:pem: PEM encode + :: + ++ en |= [lab=@t der=@ux] ^- wain :: XX validate label? @@ -287,8 +385,9 @@ ?~ a [(rap 3 ['-----END ' lab '-----' ~]) ~] [(end 3 64 a) $(a (rsh 3 64 a))] - :: :: +de:pem - ++ de :: PEM decode + :: +de:pem: PEM decode + :: + ++ de |= [lab=@t mep=wain] ^- (unit @ux) =/ a (sub (lent mep) 2) @@ -298,18 +397,24 @@ ?. =((rap 3 ['-----END ' lab '-----' ~]) (snag a t.mep)) ~ (de:base64 (rap 3 (scag a t.mep))) -- -:: :: +pkcs1 -++ pkcs1 :: RSA asym crypto - |% :: rfc3447 +:: |pkcs1: RSA asymmetric cryptography (rfc3447) +:: +++ pkcs1 + |% + :: |spec:pkcs1: ASN.1 specs for RSA keys + :: ++ spec |% - ++ pass :: +pass:spec:pkcs1 - |= k=key:rsa :: public key ASN.1 + :: +pass:spec:pkcs1: public key ASN.1 + :: + ++ pass + |= k=key:rsa ^- spec:asn1 [%seq [%int n.pub.k] [%int e.pub.k] ~] + :: +ring:spec:pkcs1: private key ASN.1 :: - ++ ring :: +ring:spec:pkcs1 - |= k=key:rsa :: private key ASN.1 + ++ ring + |= k=key:rsa ^- spec:asn1 ~| %rsa-need-ring ?> ?=(^ sek.k) @@ -325,16 +430,27 @@ [%int (~(inv fo p.u.sek.k) q.u.sek.k)] == -- - :: :: +der:pkcs1 - ++ der :: - |% :: +en:der:pkcs1 - ++ en :: + :: |der:pkcs1: DER for RSA keys + :: + ++ der + |% + :: |en:der:pkcs1: DER encoding for RSA keys + :: + ++ en |% + :: +pass:en:der:pkcs1: DER encode public key + :: ++ pass |=(k=key:rsa `@ux`(en:^der (pass:spec k))) + :: +ring:en:der:pkcs1: DER encode private key + :: ++ ring |=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- - ++ de :: +de:der:pkcs1 + :: |de:der:pkcs1: DER decoding for RSA keys + :: + ++ de |% + :: +pass:de:der:pkcs1: DER decode public key + :: ++ pass |= a=@ ^- (unit key:rsa) @@ -345,6 +461,7 @@ =* n p.i.p.u.b =* e p.i.t.p.u.b `[[n e] ~] + :: +ring:de:der:pkcs1: DER decode private key :: ++ ring |= a=@ @@ -370,47 +487,80 @@ `[[n e] `[d p q]] -- -- + :: |pem:pkcs1: PEM for RSA keys :: ++ pem |% - ++ en :: +en:pem:pkcs1 + :: |en:pem:pkcs1: PEM encoding for RSA keys + :: + ++ en |% + :: +pass:en:pem:pkcs1: PEM encode public key + :: ++ pass |=(k=key:rsa (en:^pem 'RSA PUBLIC KEY' (pass:en:der k))) + :: +ring:en:pem:pkcs1: PEM encode private key + :: ++ ring |=(k=key:rsa (en:^pem 'RSA PRIVATE KEY' (ring:en:der k))) -- - ++ de :: +de:pem:pkcs1 + :: |de:pem:pkcs1: PEM decoding for RSA keys + :: + ++ de |% + :: +pass:de:pem:pkcs1: PEM decode public key + :: ++ pass |=(mep=wain (biff (de:^pem 'RSA PUBLIC KEY' mep) pass:de:der)) + :: +ring:de:pem:pkcs1: PEM decode private key + :: ++ ring |=(mep=wain (biff (de:^pem 'RSA PRIVATE KEY' mep) ring:de:der)) -- -- -- -:: :: +pkcs8 -++ pkcs8 :: asym crypto - |% :: rfc5208 +:: |pkcs8: asymmetric cryptography (rfc5208) +:: +:: only implemented for RSA keys +:: +++ pkcs8 + |% + :: |spec:pkcs8: ASN.1 specs for asymmetric keys + :: ++ spec - |% :: +pass:spec:pkcs8 - ++ pass :: public key + |% + :: +pass:spec:pkcs8: public key ASN.1 + :: + ++ pass |= k=key:rsa ^- spec:asn1 :~ %seq [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] [%bit (pass:en:der:pkcs1 k)] == + :: +ring:spec:pkcs8: private key ASN.1 :: ++ ring !! -- - :: :: +der:pkcs8 - ++ der :: - |% :: +en:der:pkcs8 - ++ en :: + :: |der:pkcs8: DER for asymmetric keys + :: + ++ der + |% + :: |en:der:pkcs8: DER encoding for asymmetric keys + :: + ++ en |% - ++ pass |=(k=key:rsa `@ux`(en:^der (pass:spec k))) - ++ ring !! ::|=(k=key:rsa `@ux`(en:^der (ring:spec k))) + :: +pass:en:der:pkcs8: DER encode public key + :: + ++ pass + |=(k=key:rsa `@ux`(en:^der (pass:spec k))) + :: +ring:en:der:pkcs8: DER encode private key + :: + ++ ring !! + :: |=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- - :: :: +de:der:pkcs8 - ++ de :: + :: |de:der:pkcs8: DER encoding for asymmetric keys + :: + ++ de |% + :: +pass:de:der:pkcs8: DER decode public key + :: ++ pass |= a=@ ^- (unit key:rsa) @@ -423,43 +573,69 @@ == ~ (pass:de:der:pkcs1 p.i.t.p.u.b) + :: +ring:de:der:pkcs8: DER decode private key :: ++ ring !! -- -- - :: :: +pem:pkcs8 - ++ pem :: - |% :: +en:pem:pkcs8 - ++ en :: + :: |pem:pkcs8: PEM for asymmetric keys + :: + ++ pem + |% + :: |en:pem:pkcs8: PEM encoding for asymmetric keys + :: + ++ en |% - ++ pass |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k))) - ++ ring !! ::|=(k=key:rsa (en:^pem 'PUBLIC KEY' (ring:en:der k))) + :: +pass:en:pem:pkcs8: PEM encode public key + :: + ++ pass + |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k))) + :: +ring:en:pem:pkcs8: PEM encode private key + :: + ++ ring !! + :: |=(k=key:rsa (en:^pem 'PUBLIC KEY' (ring:en:der k))) -- - :: :: +de:pem:pkcs8 - ++ de :: + :: |de:pem:pkcs8: PEM decoding for asymmetric keys + :: + ++ de |% - ++ pass |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der)) - ++ ring !! ::|=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) + :: +pass:de:pem:pkcs8: PEM decode public key + :: + ++ pass + |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der)) + :: +ring:de:pem:pkcs8: PEM decode private key + :: + ++ ring !! + :: |=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) -- -- -- -:: :: +pkcs10 -++ pkcs10 :: certificate request - => |% :: rfc2986 +:: |pkcs10: certificate signing requests (rfc2986) +:: +:: only implemented for RSA keys with subject-alternate names +:: +++ pkcs10 + => |% + :: +csr: certificate request + :: += csr [key=key:rsa hot=(list (list @t))] -- |% + :: |spec:pkcs10: ASN.1 specs for certificate signing requests ++ spec - |% :: +host:spec:pkcs10 - ++ host :: subject-alt names + |% + :: +host:spec:pkcs10: subject-alternate-names + :: + ++ host |= hot=(list (list @t)) ^- spec:asn1 :- %seq %+ turn hot |=(h=(list @t) [%con [& 2] (rip 3 (join '.' h))]) - :: :: +cert:spec:pkcs10 - ++ cert :: cert request info - |= csr :: XX rename + :: +cert:spec:pkcs10: certificate request info + :: + ++ cert :: XX rename + |= csr ^- spec:asn1 :~ %seq [%int 0] @@ -475,8 +651,9 @@ [%obj sub-alt:obj:asn1] [%oct (en:^der (host hot))] == == == == == - :: :: +sign:spec:pkcs10 - ++ sign :: signed request + :: +sign:spec:pkcs10: signed certificate request + :: + ++ sign |= csr ^- spec:asn1 =/ cer (cert key hot) @@ -486,22 +663,38 @@ [%bit (swp 3 (~(sign rs256 key) (en:^der cer)))] :: big-endian == -- - :: :: +der:pkcs10 + :: |der:pkcs10: DER for certificate signing requests + :: ++ der |% - ++ en |=(a=csr `@ux`(en:^der (sign:spec a))) + :: +en:der:pkcs10: DER encode certificate signing request + :: + ++ en + |=(a=csr `@ux`(en:^der (sign:spec a))) + :: +de:der:pkcs10: DER decode certificate signing request + :: ++ de !! -- - :: :: +pem:pkcs10 + :: |pem:pkcs10: PEM for certificate signing requests + :: ++ pem |% - ++ en |=(a=csr (en:^pem 'CERTIFICATE REQUEST' (en:der a))) - ++ de !! :: |=(mep=wain (biff (de:^pem 'CERTIFICATE REQUEST' mep) de:der)) + :: +en:pem:pkcs10: PEM encode certificate signing request + :: + ++ en + |=(a=csr (en:^pem 'CERTIFICATE REQUEST' (en:der a))) + :: +de:pem:pkcs10: PEM decode certificate signing request + :: + ++ de !! + :: |=(mep=wain (biff (de:^pem 'CERTIFICATE REQUEST' mep) de:der)) -- -- -:: :: +en-json-sort -++ en-json-sort :: json w/ sorted keys - |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) :: XX rename +:: +en-json-sort: json encoding with sorted object keys +:: +:: to be included in %zuse, with sorting optional? +:: +++ en-json-sort :: XX rename + |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) :: :: ++apex:en-json:html ++ apex =, en-json:html @@ -546,12 +739,22 @@ ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)]) == -- -:: :: +jwk -++ jwk :: json web keys - |% :: rfc7517 +:: +:: %/lib/jose +:: +:: |jwk: json representations of cryptographic keys (rfc7517) +:: +:: only RSA for now +:: +++ jwk + |% + :: |en:jwk: encoding of json cryptographic keys + :: ++ en - |% :: +pass:en:jwk - ++ pass :: encode public key + |% + :: +pass:en:jwk: json encode public key + :: + ++ pass |= k=key:rsa ^- json :- %o %- my :~ @@ -559,8 +762,9 @@ n+s+(en-base64url (swp 3 n.pub.k)) :: note: big-endian e+s+(en-base64url (swp 3 e.pub.k)) == - :: :: +ring:en:jwk - ++ ring :: encode private key + :: +ring:en:jwk: json encode private key + :: + ++ ring |= k=key:rsa ^- json ~| %rsa-need-ring @@ -574,8 +778,12 @@ q+s+(en-base64url (swp 3 q.u.sek.k)) == -- + :: |de:jwk: decoding of json cryptographic keys + :: ++ de - |% :: +pass:de:jwk + |% + :: +pass:de:jwk: decode json public key + :: ++ pass :: decode public key =, dejs-soft:format %+ ci @@ -589,8 +797,9 @@ n+(cu de-base64url so) e+(cu de-base64url so) == - :: :: +ring:de:jwk - ++ ring :: decode private key + :: +ring:de:jwk: decode json private key + :: + ++ ring =, dejs-soft:format %+ ci |= $: kty=@t @@ -614,20 +823,30 @@ q+(cu de-base64url so) == -- - :: :: +thumb:jwk - ++ thumb :: thumbprint - |% :: rfc7638 - ++ ring !! + :: |thumb:jwk: "thumbprint" json-encoded key (rfc7638) + :: + ++ thumb + |% + :: +pass:thumb:jwk: thumbprint json-encoded public key + :: ++ pass |= k=key:rsa (en-base64url (shax (crip (en-json-sort aor (pass:en k))))) + :: +ring:thumb:jwk: thumbprint json-encoded private key + :: + ++ ring !! -- -- -:: :: +jws -++ jws :: json web signature - |% :: rfc7515 - ++ sign :: +sign:jws - |= [k=key:rsa pro=json lod=json] :: flattened signature +:: |jws: json web signatures (rfc7515) +:: +:: flattened signature only +:: +++ jws + |% + :: +sign:jws: sign json value + :: + ++ sign + |= [k=key:rsa pro=json lod=json] |^ ^- json =. pro header =/ protect=cord (encode pro) @@ -637,32 +856,45 @@ payload+s+payload signature+s+(sign protect payload) == + :: +header:sign:jws: set signature algorithm in header :: ++ header ?> ?=([%o *] pro) ^- json [%o (~(put by p.pro) %alg s+'RS256')] + :: +encode:sign:jws: encode json for signing + :: + :: alphabetically sort object keys, url-safe base64 encode + :: the serialized json :: ++ encode |= jon=json (en-base64url (crip (en-json-sort aor jon))) + :: +sign:sign:jws: compute signature + :: + :: url-safe base64 encode in big-endian byte order :: ++ sign |= [protect=cord payload=cord] %- en-base64url (swp 3 (~(sign rs256 k) (rap 3 ~[protect '.' payload]))) -- + :: +verify:jws: verify signature :: ++ verify !! -- -:: :: +eor -++ eor :: explicit order +:: +eor: explicit sort order comparator +:: +:: lookup :a and :b in :lit, pass their indices to :com +:: +++ eor |= [com=$-([@ @] ?) lit=(list)] |= [a=* b=*] ^- ? (fall (bind (both (find ~[a] lit) (find ~[b] lit)) com) |) -:: :: +join -++ join :: join cords w/ sep +:: +join: join list of cords with separator +:: +++ join |= [sep=@t hot=(list @t)] ^- @t =| out=(list @t) From 218369c85d6678b2bb9374385d878cce6a3e0052 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 25 May 2018 11:45:16 -0700 Subject: [PATCH 53/95] adds more comments and further refactors +asn1 and +der --- app/acme.hoon | 359 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 213 insertions(+), 146 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 7d955b7a7..369f64bc6 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -80,7 +80,17 @@ :: ++ asn1 |% + :: +bespoke:asn1: context-specific, generic ASN.1 tag type + :: + :: note that explicit implies constructed (ie, bit 5 is set in DER) + :: + += bespoke + :: imp: & is implicit, | is explicit + :: tag: 5 bits for the custom tag number + :: + [imp=? tag=@ud] :: +spec:asn1: minimal representations of basic ASN.1 types + :: += spec $% :: %int: arbitrary-sized, unsigned integers :: @@ -88,17 +98,17 @@ :: negative integers would be two's complement in DER, :: but we don't need them. :: - [%int p=@u] + [%int int=@u] :: %bit: very minimal support for bit strings :: :: specifically, values must already be padded and byte-aligned. :: note that leading zeros are significant in ASN.1 bit strings, :: so atomic encoding would be insufficient for complete support. :: - [%bit p=@ux] + [%bit bit=@ux] :: %oct: octets in little-endian byte order :: - [%oct p=@ux] + [%oct oct=@ux] :: %nul: fully supported! :: [%nul ~] @@ -107,24 +117,24 @@ :: object identifiers are technically a sequence of integers, :: represented here in their already-encoded form. :: - [%obj p=@ux] + [%obj obj=@ux] :: %seq: a list of specs :: - [%seq p=(list spec)] + [%seq seq=(list spec)] :: %set: a logical set of specs :: :: implemented here as a list for the sake of simplicity. - :: encodings must dedupe and sort the list appropriately + :: must be already deduplicated and sorted! :: - [%set p=(list spec)] + [%set set=(list spec)] :: %con: context-specific :: - :: here be dragons + :: general supported for context-specific tags. + :: bes: custom tag number, implicit or explicit + :: con: already-encoded bytes :: - $: %con :: construct yerself - p=[p=? q=@udC] :: [primitive? tag] - q=(list @) :: bytes - == == + [%con bes=bespoke con=(list @D)] + == :: |obj:asn1: constant object ids, pre-encoded :: ++ obj @@ -140,64 +150,85 @@ -- :: |der: distinguished encoding rules for ASN.1 :: +:: DER is a tag-length-value binary encoding for ASN.1, designed +:: so that there is only one (distinguished) valid encoding for an +:: instance of a type. +:: ++ der |% :: +en:der: encode +spec:asn1 to atom :: ++ en =< |=(a=spec:asn1 `@ux`(rep 3 ~(ren raw a))) - |% :: +raw:en:der - ++ raw :: encode to bytes + |% + :: +raw:en:der: door for encoding +spec:asn1 to list of bytes + :: + ++ raw |_ pec=spec:asn1 - :: :: +ren:raw:en:der - ++ ren :: tag-length-value - ^- (list @) + :: +ren:raw:en:der: render +spec:asn1 to tag-length-value bytes + :: + ++ ren + ^- (list @D) =/ a lem [tag (weld (len a) a)] - :: :: +tag:raw:en:der - ++ tag :: type tag - ^- @ + :: +tag:raw:en:der: tag byte + :: + ++ tag + ^- @D ?- pec [%int *] 2 [%bit *] 3 [%oct *] 4 [%nul *] 5 [%obj *] 6 - [%seq *] 48 :: (con 0x20 16) - [%set *] 49 :: (con 0x20 17) - [%con *] :(con q.p.pec 0x80 ?:(p.p.pec 0 0x20)) + [%seq *] 48 :: constructed: (con 0x20 16) + [%set *] 49 :: constructed: (con 0x20 17) + [%con *] ;: con + 0x80 :: context-specifc + ?:(imp.bes.pec 0 0x20) :: implicit? + (dis 0x1f tag.bes.pec) :: 5 bits of custom tag + == == - :: :: +lem:raw:en:der - ++ lem :: element bytes - ^- (list @) + :: +lem:raw:en:der: element bytes + :: + ++ lem + ^- (list @D) ?- pec - [%int *] =/ a (flop (rip 3 p.pec)) :: note: big-endian + :: unsigned only, interpreted as positive-signed and + :: rendered in big-endian byte order. negative-signed would + :: be two's complement + :: + [%int *] =/ a (flop (rip 3 int.pec)) ?~ a [0 ~] ?:((lte i.a 127) a [0 a]) + :: presumed to be already padded to a byte boundary :: - [%bit *] [0 (rip 3 p.pec)] :: XX padding - [%oct *] (rip 3 p.pec) + [%bit *] [0 (rip 3 bit.pec)] + [%oct *] (rip 3 oct.pec) [%nul *] ~ - [%obj *] (rip 3 p.pec) + [%obj *] (rip 3 obj.pec) :: [%seq *] %- zing |- ^- (list (list @)) - ?~ p.pec ~ - :- ren(pec i.p.pec) - $(p.pec t.p.pec) + ?~ seq.pec ~ + :- ren(pec i.seq.pec) + $(seq.pec t.seq.pec) + :: presumed to be already deduplicated and sorted :: - [%set *] %- zing :: XX tap/sort + [%set *] %- zing |- ^- (list (list @)) - ?~ p.pec ~ - :- ren(pec i.p.pec) - $(p.pec t.p.pec) + ?~ set.pec ~ + :- ren(pec i.set.pec) + $(set.pec t.set.pec) + :: already constructed :: - [%con *] q.pec + [%con *] con.pec == - :: :: +len:raw:en:der - ++ len :: length bytes - |= a=(list @) - ^- (list @) + :: +len:raw:en:der: length bytes + :: + ++ len + |= a=(list @D) + ^- (list @D) =/ b (lent a) ?: (lte b 127) [b ~] :: note: big-endian @@ -207,11 +238,11 @@ :: +de:der: decode atom to +spec:asn1 :: ++ de - =< |=(a=@ `(unit spec:asn1)`(rush a decode)) + =< |=(a=@ `(unit spec:asn1)`(rush a parse)) |% - :: +decode:de:der: DER parser combinator XX rename + :: +parse:de:der: DER parser combinator :: - ++ decode + ++ parse %+ cook |*(a=* `spec:asn1`a) :: XX fix :: ^- $-(nail (like spec:asn1)) ;~ pose @@ -227,12 +258,12 @@ :: +tag:de:der: parse tag byte :: ++ tag - |=(a=@ (just a)) + |=(a=@D (just a)) :: +int:de:der: sear unsigned big-endian bytes :: ++ int - |= a=(list @) - ^- (unit (list @)) + |= a=(list @D) + ^- (unit (list @D)) ?~ a ~ ?: ?=([@ ~] a) `a ?. =(0 i.a) `a @@ -240,12 +271,12 @@ :: +recur:de:der: parse bytes for a list of +spec:asn1 :: ++ recur - |=(a=(list @) (rust a (star decode))) :: XX plus? curr? + |=(a=(list @) (rust a (star parse))) :: +context:de:der: decode context-specific tag byte :: ++ context - |= a=@ - ^- (unit [? @udC]) + |= a=@D + ^- (unit bespoke:asn1) ?. =(1 (cut 0 [7 1] a)) ~ :+ ~ =(1 (cut 0 [5 1] a)) @@ -259,8 +290,12 @@ ^- (like (list @D)) ?~ q.tub (fail tub) + :: fuz: first byte - length, or length of the length =* fuz i.q.tub + :: nex: offset of value bytes from fuz + :: len: length of value bytes =+ ^- [nex=@ len=@] + :: faz: meaningful bits in fuz =/ faz (end 0 7 fuz) ?: =(0 (cut 0 [7 1] fuz)) [0 faz] @@ -269,9 +304,11 @@ !=(nex (met 3 len)) == (fail tub) + :: zuf: value bytes =/ zuf (swag [nex len] t.q.tub) ?. =(len (lent zuf)) (fail tub) + :: zaf: product nail =/ zaf [p.p.tub (add +(nex) q.p.tub)] [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] -- @@ -405,30 +442,72 @@ :: ++ spec |% - :: +pass:spec:pkcs1: public key ASN.1 + :: |en:spec:pkcs1: ASN.1 encoding for RSA keys :: - ++ pass - |= k=key:rsa - ^- spec:asn1 - [%seq [%int n.pub.k] [%int e.pub.k] ~] - :: +ring:spec:pkcs1: private key ASN.1 + ++ en + |% + :: +pass:en:spec:pkcs1: encode public key to ASN.1 + :: + ++ pass + |= k=key:rsa + ^- spec:asn1 + [%seq [%int n.pub.k] [%int e.pub.k] ~] + :: +ring:en:spec:pkcs1: encode private key to ASN.1 + :: + ++ ring + |= k=key:rsa + ^- spec:asn1 + ~| %rsa-need-ring + ?> ?=(^ sek.k) + :~ %seq + [%int 0] + [%int n.pub.k] + [%int e.pub.k] + [%int d.u.sek.k] + [%int p.u.sek.k] + [%int q.u.sek.k] + [%int (mod d.u.sek.k (dec p.u.sek.k))] + [%int (mod d.u.sek.k (dec q.u.sek.k))] + [%int (~(inv fo p.u.sek.k) q.u.sek.k)] + == + -- + :: |de:spec:pkcs1: ASN.1 decoding for RSA keys :: - ++ ring - |= k=key:rsa - ^- spec:asn1 - ~| %rsa-need-ring - ?> ?=(^ sek.k) - :~ %seq - [%int 0] - [%int n.pub.k] - [%int e.pub.k] - [%int d.u.sek.k] - [%int p.u.sek.k] - [%int q.u.sek.k] - [%int (mod d.u.sek.k (dec p.u.sek.k))] - [%int (mod d.u.sek.k (dec q.u.sek.k))] - [%int (~(inv fo p.u.sek.k) q.u.sek.k)] - == + ++ de + |% + :: +pass:de:spec:pkcs1: decode ASN.1 public key + :: + ++ pass + |= a=spec:asn1 + ^- (unit key:rsa) + ?. ?=([%seq [%int *] [%int *] ~] a) + ~ + =* n int.i.seq.a + =* e int.i.t.seq.a + `[[n e] ~] + :: +ring:de:spec:pkcs1: decode ASN.1 private key + :: + ++ ring + |= a=spec:asn1 + ^- (unit key:rsa) + ?. ?=([%seq *] a) ~ + ?. ?= $: [%int %0] + [%int *] + [%int *] + [%int *] + [%int *] + [%int *] + * + == + seq.a + ~ + =* n int.i.t.seq.a + =* e int.i.t.t.seq.a + =* d int.i.t.t.t.seq.a + =* p int.i.t.t.t.t.seq.a + =* q int.i.t.t.t.t.t.seq.a + `[[n e] `[d p q]] + -- -- :: |der:pkcs1: DER for RSA keys :: @@ -440,10 +519,10 @@ |% :: +pass:en:der:pkcs1: DER encode public key :: - ++ pass |=(k=key:rsa `@ux`(en:^der (pass:spec k))) + ++ pass |=(k=key:rsa `@ux`(en:^der (pass:en:spec k))) :: +ring:en:der:pkcs1: DER encode private key :: - ++ ring |=(k=key:rsa `@ux`(en:^der (ring:spec k))) + ++ ring |=(k=key:rsa `@ux`(en:^der (ring:en:spec k))) -- :: |de:der:pkcs1: DER decoding for RSA keys :: @@ -454,37 +533,13 @@ ++ pass |= a=@ ^- (unit key:rsa) - =/ b (de:^der a) - ?~ b ~ - ?. ?=([%seq [%int *] [%int *] ~] u.b) - ~ - =* n p.i.p.u.b - =* e p.i.t.p.u.b - `[[n e] ~] + (biff (de:^der a) pass:de:spec) :: +ring:de:der:pkcs1: DER decode private key :: ++ ring |= a=@ ^- (unit key:rsa) - =/ b (de:^der a) - ?~ b ~ - ?. ?=([%seq *] u.b) ~ - ?. ?= $: [%int %0] - [%int *] - [%int *] - [%int *] - [%int *] - [%int *] - * - == - p.u.b - ~ - =* n p.i.t.p.u.b - =* e p.i.t.t.p.u.b - =* d p.i.t.t.t.p.u.b - =* p p.i.t.t.t.t.p.u.b - =* q p.i.t.t.t.t.t.p.u.b - `[[n e] `[d p q]] + (biff (de:^der a) ring:de:spec) -- -- :: |pem:pkcs1: PEM for RSA keys @@ -568,11 +623,11 @@ ?~ b ~ ?. ?=([%seq [%seq *] [%bit *] ~] u.b) ~ - ?. ?& ?=([[%obj *] [%nul ~] ~] p.i.p.u.b) - =(rsa:obj:asn1 p.i.p.i.p.u.b) + ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.seq.u.b) + =(rsa:obj:asn1 obj.i.seq.i.seq.u.b) == ~ - (pass:de:der:pkcs1 p.i.t.p.u.b) + (pass:de:der:pkcs1 bit.i.t.seq.u.b) :: +ring:de:der:pkcs8: DER decode private key :: ++ ring !! @@ -616,52 +671,64 @@ :: ++ pkcs10 => |% - :: +csr: certificate request + :: +csr:pkcs10: certificate request :: += csr [key=key:rsa hot=(list (list @t))] -- |% :: |spec:pkcs10: ASN.1 specs for certificate signing requests + :: ++ spec |% - :: +host:spec:pkcs10: subject-alternate-names + :: |en:spec:pkcs10: ASN.1 encoding for certificate signing requests :: - ++ host - |= hot=(list (list @t)) - ^- spec:asn1 - :- %seq - %+ turn hot - |=(h=(list @t) [%con [& 2] (rip 3 (join '.' h))]) - :: +cert:spec:pkcs10: certificate request info - :: - ++ cert :: XX rename - |= csr - ^- spec:asn1 - :~ %seq - [%int 0] - [%seq ~] - (pass:spec:pkcs8 key) - :+ %con [| 0] - =- ~(ren raw:en:^der -) + ++ en + |% + :: +req:en:spec:pkcs10: signed certificate request + :: + ++ req + |= csr + ^- spec:asn1 + |^ =/ dat=spec:asn1 (info key hot) + :~ %seq + dat + [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] + :: big-endian signature bytes + [%bit (swp 3 (~(sign rs256 key) (en:^der dat)))] + == + :: +info:req:en:spec:pkcs10: certificate request info + :: + ++ info + |= csr + ^- spec:asn1 :~ %seq - [%obj csr-ext:obj:asn1] - :~ %set - :~ %seq + [%int 0] + [%seq ~] + (pass:spec:pkcs8 key) + :+ %con [| 0] + =- ~(ren raw:en:^der -) + :~ %seq + [%obj csr-ext:obj:asn1] + :~ %set :~ %seq - [%obj sub-alt:obj:asn1] - [%oct (en:^der (host hot))] - == == == == == - :: +sign:spec:pkcs10: signed certificate request - :: - ++ sign - |= csr - ^- spec:asn1 - =/ cer (cert key hot) - :~ %seq - cer - [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] - [%bit (swp 3 (~(sign rs256 key) (en:^der cer)))] :: big-endian - == + :~ %seq + [%obj sub-alt:obj:asn1] + [%oct (en:^der (san hot))] + == == == == == + :: +san:req:en:spec:pkcs10: subject-alternate-names + :: + ++ san + |= hot=(list (list @t)) + ^- spec:asn1 + :- %seq + %+ turn hot + :: implicit, context-specific tag #2 (IA5String) + :: XX sanitize string? + |=(h=(list @t) [%con [& 2] (rip 3 (join '.' h))]) + -- + -- + :: |de:spec:pkcs10: ASN.1 decoding for certificate signing requests + ++ de !! -- :: |der:pkcs10: DER for certificate signing requests :: @@ -670,7 +737,7 @@ :: +en:der:pkcs10: DER encode certificate signing request :: ++ en - |=(a=csr `@ux`(en:^der (sign:spec a))) + |=(a=csr `@ux`(en:^der (req:en:spec a))) :: +de:der:pkcs10: DER decode certificate signing request :: ++ de !! @@ -1506,29 +1573,29 @@ :- [0x5 0x0 ~] ~(ren raw:en:der nul) %- expect-eq !> - [nul (scan ~(ren raw:en:der nul) decode:de:der)] + [nul (scan ~(ren raw:en:der nul) parse:de:der)] %- expect-eq !> :- [0x2 0x2 0x0 0xbb ~] ~(ren raw:en:der int) %- expect-eq !> - [int (scan ~(ren raw:en:der int) decode:de:der)] + [int (scan ~(ren raw:en:der int) parse:de:der)] %- expect-eq !> :- [0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1 ~] ~(ren raw:en:der obj) %- expect-eq !> - [obj (scan ~(ren raw:en:der obj) decode:de:der)] + [obj (scan ~(ren raw:en:der obj) parse:de:der)] %- expect-eq !> :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb. d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 `@ux`(swp 3 (en:der oct)) %- expect-eq !> - [oct (scan ~(ren raw:en:der oct) decode:de:der)] + [oct (scan ~(ren raw:en:der oct) parse:de:der)] %- expect-eq !> :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5. df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 `@ux`(swp 3 (en:der seq)) %- expect-eq !> - [seq (scan ~(ren raw:en:der seq) decode:de:der)] + [seq (scan ~(ren raw:en:der seq) parse:de:der)] == :: ++ test-rsakey From 31f95df95980f9379bc791965d51977322575bc7 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 25 May 2018 14:14:40 -0700 Subject: [PATCH 54/95] additional refactoring and comment cleanup in asn1 and pkcs library cores --- app/acme.hoon | 261 ++++++++++++++++++++------------------------------ 1 file changed, 104 insertions(+), 157 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 369f64bc6..204dfad82 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -357,7 +357,7 @@ :: :: message = ciphertext^d (mod e) :: - ++ de :: unpadded RSA decrypt + ++ de |= [m=@ k=key] :: XX assert rsa-len here too? ~| %rsa-need-ring @@ -509,63 +509,37 @@ `[[n e] `[d p q]] -- -- - :: |der:pkcs1: DER for RSA keys + :: |der:pkcs1: DER encoding for RSA keys + :: + :: en(coding) and de(coding) for public (pass) and private (ring) keys :: ++ der |% - :: |en:der:pkcs1: DER encoding for RSA keys - :: ++ en |% - :: +pass:en:der:pkcs1: DER encode public key - :: ++ pass |=(k=key:rsa `@ux`(en:^der (pass:en:spec k))) - :: +ring:en:der:pkcs1: DER encode private key - :: ++ ring |=(k=key:rsa `@ux`(en:^der (ring:en:spec k))) -- - :: |de:der:pkcs1: DER decoding for RSA keys - :: ++ de |% - :: +pass:de:der:pkcs1: DER decode public key - :: - ++ pass - |= a=@ - ^- (unit key:rsa) - (biff (de:^der a) pass:de:spec) - :: +ring:de:der:pkcs1: DER decode private key - :: - ++ ring - |= a=@ - ^- (unit key:rsa) - (biff (de:^der a) ring:de:spec) + ++ pass |=(a=@ `(unit key:rsa)`(biff (de:^der a) pass:de:spec)) + ++ ring |=(a=@ `(unit key:rsa)`(biff (de:^der a) ring:de:spec)) -- -- - :: |pem:pkcs1: PEM for RSA keys + :: |pem:pkcs1: PEM encoding for RSA keys + :: + :: en(coding) and de(coding) for public (pass) and private (ring) keys :: ++ pem |% - :: |en:pem:pkcs1: PEM encoding for RSA keys - :: ++ en |% - :: +pass:en:pem:pkcs1: PEM encode public key - :: ++ pass |=(k=key:rsa (en:^pem 'RSA PUBLIC KEY' (pass:en:der k))) - :: +ring:en:pem:pkcs1: PEM encode private key - :: ++ ring |=(k=key:rsa (en:^pem 'RSA PRIVATE KEY' (ring:en:der k))) -- - :: |de:pem:pkcs1: PEM decoding for RSA keys - :: ++ de |% - :: +pass:de:pem:pkcs1: PEM decode public key - :: ++ pass |=(mep=wain (biff (de:^pem 'RSA PUBLIC KEY' mep) pass:de:der)) - :: +ring:de:pem:pkcs1: PEM decode private key - :: ++ ring |=(mep=wain (biff (de:^pem 'RSA PRIVATE KEY' mep) ring:de:der)) -- -- @@ -580,88 +554,76 @@ :: ++ spec |% - :: +pass:spec:pkcs8: public key ASN.1 + ++ en + |% + :: +pass:spec:pkcs8: public key ASN.1 + :: + ++ pass + |= k=key:rsa + ^- spec:asn1 + :~ %seq + [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] + [%bit (pass:en:der:pkcs1 k)] + == + :: +ring:spec:pkcs8: private key ASN.1 + :: + ++ ring !! + -- + :: |de:spec:pkcs8: :: - ++ pass - |= k=key:rsa - ^- spec:asn1 - :~ %seq - [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] - [%bit (pass:en:der:pkcs1 k)] - == - :: +ring:spec:pkcs8: private key ASN.1 - :: - ++ ring !! + ++ de + |% + :: +pass:de:spec:pkcs8: + :: + ++ pass + |= a=spec:asn1 + ^- (unit key:rsa) + ?. ?=([%seq [%seq *] [%bit *] ~] a) + ~ + ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.seq.a) + =(rsa:obj:asn1 obj.i.seq.i.seq.a) + == + ~ + (pass:de:der:pkcs1 bit.i.t.seq.a) + :: +ring:de:spec:pkcs8: + :: + ++ ring !! + -- -- - :: |der:pkcs8: DER for asymmetric keys + :: |der:pkcs8: DER encoding for asymmetric keys + :: + :: en(coding) and de(coding) for public (pass) and private (ring) keys + :: RSA-only for now :: ++ der |% - :: |en:der:pkcs8: DER encoding for asymmetric keys - :: ++ en |% - :: +pass:en:der:pkcs8: DER encode public key - :: - ++ pass - |=(k=key:rsa `@ux`(en:^der (pass:spec k))) - :: +ring:en:der:pkcs8: DER encode private key - :: - ++ ring !! - :: |=(k=key:rsa `@ux`(en:^der (ring:spec k))) + ++ pass |=(k=key:rsa `@ux`(en:^der (pass:en:spec k))) + ++ ring !! ::|=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- - :: |de:der:pkcs8: DER encoding for asymmetric keys - :: ++ de |% - :: +pass:de:der:pkcs8: DER decode public key - :: - ++ pass - |= a=@ - ^- (unit key:rsa) - =/ b (de:^der a) - ?~ b ~ - ?. ?=([%seq [%seq *] [%bit *] ~] u.b) - ~ - ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.seq.u.b) - =(rsa:obj:asn1 obj.i.seq.i.seq.u.b) - == - ~ - (pass:de:der:pkcs1 bit.i.t.seq.u.b) - :: +ring:de:der:pkcs8: DER decode private key - :: - ++ ring !! + ++ pass |=(a=@ `(unit key:rsa)`(biff (de:^der a) pass:de:spec)) + ++ ring !! ::|=(a=@ `(unit key:rsa)`(biff (de:^der a) ring:de:spec)) -- -- - :: |pem:pkcs8: PEM for asymmetric keys + :: |pem:pkcs8: PEM encoding for asymmetric keys + :: + :: en(coding) and de(coding) for public (pass) and private (ring) keys + :: RSA-only for now :: ++ pem |% - :: |en:pem:pkcs8: PEM encoding for asymmetric keys - :: ++ en |% - :: +pass:en:pem:pkcs8: PEM encode public key - :: - ++ pass - |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k))) - :: +ring:en:pem:pkcs8: PEM encode private key - :: - ++ ring !! - :: |=(k=key:rsa (en:^pem 'PUBLIC KEY' (ring:en:der k))) + ++ pass |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k))) + ++ ring !! ::|=(k=key:rsa (en:^pem 'PUBLIC KEY' (ring:en:der k))) -- - :: |de:pem:pkcs8: PEM decoding for asymmetric keys - :: ++ de |% - :: +pass:de:pem:pkcs8: PEM decode public key - :: - ++ pass - |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der)) - :: +ring:de:pem:pkcs8: PEM decode private key - :: - ++ ring !! - :: |=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) + ++ pass |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der)) + ++ ring !! ::|=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) -- -- -- @@ -680,80 +642,64 @@ :: ++ spec |% - :: |en:spec:pkcs10: ASN.1 encoding for certificate signing requests + :: +en:spec:pkcs10: ASN.1 encoding for certificate signing requests :: ++ en - |% - :: +req:en:spec:pkcs10: signed certificate request + |= csr + ^- spec:asn1 + |^ =/ dat=spec:asn1 (info key hot) + :~ %seq + dat + [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] + :: big-endian signature bytes + [%bit (swp 3 (~(sign rs256 key) (en:^der dat)))] + == + :: +info:en:spec:pkcs10: certificate request info :: - ++ req + ++ info |= csr ^- spec:asn1 - |^ =/ dat=spec:asn1 (info key hot) + :~ %seq + [%int 0] + [%seq ~] + (pass:en:spec:pkcs8 key) + :+ %con [| 0] + =- ~(ren raw:en:^der -) :~ %seq - dat - [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] - :: big-endian signature bytes - [%bit (swp 3 (~(sign rs256 key) (en:^der dat)))] - == - :: +info:req:en:spec:pkcs10: certificate request info - :: - ++ info - |= csr - ^- spec:asn1 - :~ %seq - [%int 0] - [%seq ~] - (pass:spec:pkcs8 key) - :+ %con [| 0] - =- ~(ren raw:en:^der -) - :~ %seq - [%obj csr-ext:obj:asn1] - :~ %set - :~ %seq - :~ %seq - [%obj sub-alt:obj:asn1] - [%oct (en:^der (san hot))] - == == == == == - :: +san:req:en:spec:pkcs10: subject-alternate-names - :: - ++ san - |= hot=(list (list @t)) - ^- spec:asn1 - :- %seq - %+ turn hot - :: implicit, context-specific tag #2 (IA5String) - :: XX sanitize string? - |=(h=(list @t) [%con [& 2] (rip 3 (join '.' h))]) - -- + [%obj csr-ext:obj:asn1] + :~ %set + :~ %seq + :~ %seq + [%obj sub-alt:obj:asn1] + [%oct (en:^der (san hot))] + == == == == == + :: +san:en:spec:pkcs10: subject-alternate-names + :: + ++ san + |= hot=(list (list @t)) + ^- spec:asn1 + :- %seq + %+ turn hot + :: implicit, context-specific tag #2 (IA5String) + :: XX sanitize string? + |=(h=(list @t) [%con [& 2] (rip 3 (join '.' h))]) -- :: |de:spec:pkcs10: ASN.1 decoding for certificate signing requests ++ de !! -- - :: |der:pkcs10: DER for certificate signing requests + :: |der:pkcs10: DER encoding for certificate signing requests :: ++ der |% - :: +en:der:pkcs10: DER encode certificate signing request - :: - ++ en - |=(a=csr `@ux`(en:^der (req:en:spec a))) - :: +de:der:pkcs10: DER decode certificate signing request - :: - ++ de !! + ++ en |=(a=csr `@ux`(en:^der (en:spec a))) + ++ de !! ::|=(a=@ `(unit csr)`(biff (de:^der a) de:spec)) -- - :: |pem:pkcs10: PEM for certificate signing requests + :: |pem:pkcs10: PEM encoding for certificate signing requests :: ++ pem |% - :: +en:pem:pkcs10: PEM encode certificate signing request - :: - ++ en - |=(a=csr (en:^pem 'CERTIFICATE REQUEST' (en:der a))) - :: +de:pem:pkcs10: PEM decode certificate signing request - :: - ++ de !! - :: |=(mep=wain (biff (de:^pem 'CERTIFICATE REQUEST' mep) de:der)) + ++ en |=(a=csr (en:^pem 'CERTIFICATE REQUEST' (en:der a))) + ++ de !! ::|=(mep=wain (biff (de:^pem 'CERTIFICATE REQUEST' mep) de:der)) -- -- :: +en-json-sort: json encoding with sorted object keys @@ -811,7 +757,8 @@ :: :: |jwk: json representations of cryptographic keys (rfc7517) :: -:: only RSA for now +:: url-safe base64 encoding of key parameters in big-endian byte order +:: RSA-only for now :: ++ jwk |% @@ -826,7 +773,7 @@ ^- json :- %o %- my :~ kty+s+'RSA' - n+s+(en-base64url (swp 3 n.pub.k)) :: note: big-endian + n+s+(en-base64url (swp 3 n.pub.k)) e+s+(en-base64url (swp 3 e.pub.k)) == :: +ring:en:jwk: json encode private key @@ -851,7 +798,7 @@ |% :: +pass:de:jwk: decode json public key :: - ++ pass :: decode public key + ++ pass =, dejs-soft:format %+ ci |= [kty=@t n=(unit @) e=(unit @)] From 1029a4475847326e533be820f8ba532cfeba96a2 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sun, 27 May 2018 22:57:58 -0700 Subject: [PATCH 55/95] tweaks and formats block comments --- app/acme.hoon | 105 +++++++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 204dfad82..96ffeecee 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -75,14 +75,14 @@ :: :: |asn1: small selection of types and constants for ASN.1 :: -:: a minimal representation of some basic ASN.1 types, -:: created to support PKCS keys, digests, and cert requests +:: A minimal representation of some basic ASN.1 types, +:: created to support PKCS keys, digests, and cert requests. :: ++ asn1 |% :: +bespoke:asn1: context-specific, generic ASN.1 tag type :: - :: note that explicit implies constructed (ie, bit 5 is set in DER) + :: Note that *explicit* implies *constructed* (ie, bit 5 is set in DER). :: += bespoke :: imp: & is implicit, | is explicit @@ -94,16 +94,16 @@ += spec $% :: %int: arbitrary-sized, unsigned integers :: - :: unsigned integers, represented as having a positive sign. - :: negative integers would be two's complement in DER, - :: but we don't need them. + :: Unsigned integers, represented as having a positive sign. + :: Negative integers would be two's complement in DER, + :: but we don't need them. :: [%int int=@u] :: %bit: very minimal support for bit strings :: - :: specifically, values must already be padded and byte-aligned. - :: note that leading zeros are significant in ASN.1 bit strings, - :: so atomic encoding would be insufficient for complete support. + :: Specifically, values must already be padded and byte-aligned. + :: Note that leading zeros are significant in ASN.1 bit strings, + :: so atomic encoding would be insufficient for complete support. :: [%bit bit=@ux] :: %oct: octets in little-endian byte order @@ -114,8 +114,8 @@ [%nul ~] :: %obj: object identifiers, pre-packed :: - :: object identifiers are technically a sequence of integers, - :: represented here in their already-encoded form. + :: Object identifiers are technically a sequence of integers, + :: represented here in their already-encoded form. :: [%obj obj=@ux] :: %seq: a list of specs @@ -123,15 +123,15 @@ [%seq seq=(list spec)] :: %set: a logical set of specs :: - :: implemented here as a list for the sake of simplicity. - :: must be already deduplicated and sorted! + :: Implemented here as a list for the sake of simplicity. + :: must be already deduplicated and sorted! :: [%set set=(list spec)] :: %con: context-specific :: - :: general supported for context-specific tags. - :: bes: custom tag number, implicit or explicit - :: con: already-encoded bytes + :: General support for context-specific tags. + :: bes: custom tag number, implicit or explicit + :: con: already-encoded bytes :: [%con bes=bespoke con=(list @D)] == @@ -150,9 +150,9 @@ -- :: |der: distinguished encoding rules for ASN.1 :: -:: DER is a tag-length-value binary encoding for ASN.1, designed -:: so that there is only one (distinguished) valid encoding for an -:: instance of a type. +:: DER is a tag-length-value binary encoding for ASN.1, designed +:: so that there is only one (distinguished) valid encoding for an +:: instance of a type. :: ++ der |% @@ -291,11 +291,14 @@ ?~ q.tub (fail tub) :: fuz: first byte - length, or length of the length + :: =* fuz i.q.tub :: nex: offset of value bytes from fuz :: len: length of value bytes + :: =+ ^- [nex=@ len=@] :: faz: meaningful bits in fuz + :: =/ faz (end 0 7 fuz) ?: =(0 (cut 0 [7 1] fuz)) [0 faz] @@ -305,17 +308,19 @@ == (fail tub) :: zuf: value bytes + :: =/ zuf (swag [nex len] t.q.tub) ?. =(len (lent zuf)) (fail tub) :: zaf: product nail + :: =/ zaf [p.p.tub (add +(nex) q.p.tub)] [zaf `[zuf zaf (slag (add nex len) t.q.tub)]] -- -- :: |rsa: primitive, textbook RSA :: -:: unpadded, unsafe, unsuitable for encryption! +:: Unpadded, unsafe, unsuitable for encryption! :: ++ rsa |% @@ -323,8 +328,10 @@ :: += key $: :: pub: public parameters (n=modulus, e=pub-exponent) + :: pub=[n=@ux e=@ux] :: sek: secret parameters (d=private-exponent, p/q=primes) + :: sek=(unit [d=@ux p=@ux q=@ux]) == :: +elcm:rsa: carmichael totient @@ -332,7 +339,7 @@ ++ elcm |= [a=@ b=@] (div (mul a b) d:(egcd a b)) - :: +new-key:rsa + :: +new-key:rsa: write somethingXXX :: ++ new-key =/ e `@ux`65.537 @@ -346,7 +353,7 @@ [[n e] `[d p q]] :: +en:rsa: primitive RSA encryption :: - :: ciphertext = message^e (mod n) + :: ciphertext = message^e (mod n) :: ++ en |= [m=@ k=key] @@ -355,7 +362,7 @@ (~(exp fo n.pub.k) e.pub.k m) :: +de:rsa: primitive RSA decryption :: - :: message = ciphertext^d (mod e) + :: message = ciphertext^d (mod e) :: ++ de |= [m=@ k=key] @@ -371,7 +378,7 @@ |_ k=key:rsa :: +emsa:rs256: message digest :: - :: padded, DER encoded sha-256 hash (EMSA-PKCS1-v1_5) + :: Padded, DER encoded sha-256 hash (EMSA-PKCS1-v1_5). :: ++ emsa |= m=@ @@ -390,14 +397,14 @@ (flop (weld [0x0 0x1 ps] [0x0 t])) :: note: big-endian :: +sign:rs256: sign message :: - :: an RSA signature is the primitive decryption of the message hash + :: An RSA signature is the primitive decryption of the message hash. :: ++ sign |=(m=@ (de:rsa (emsa m) k)) :: +verify:rs256: verify signature :: - :: RSA signature verification confirms that the primitive encryption - :: of the signature matches the message hash + :: RSA signature verification confirms that the primitive encryption + :: of the signature matches the message hash. :: ++ verify |= [s=@ m=@] @@ -405,8 +412,8 @@ -- :: |pem: generic PEM implementation (rfc7468) :: -:: PEM is the base64 encoding of DER encoded data, with BEGIN and -:: END labels indicating some type. +:: PEM is the base64 encoding of DER encoded data, with BEGIN and +:: END labels indicating some type. :: ++ pem |% @@ -511,7 +518,7 @@ -- :: |der:pkcs1: DER encoding for RSA keys :: - :: en(coding) and de(coding) for public (pass) and private (ring) keys + :: En(coding) and de(coding) for public (pass) and private (ring) keys. :: ++ der |% @@ -528,7 +535,7 @@ -- :: |pem:pkcs1: PEM encoding for RSA keys :: - :: en(coding) and de(coding) for public (pass) and private (ring) keys + :: En(coding) and de(coding) for public (pass) and private (ring) keys. :: ++ pem |% @@ -546,7 +553,7 @@ -- :: |pkcs8: asymmetric cryptography (rfc5208) :: -:: only implemented for RSA keys +:: RSA-only for now. :: ++ pkcs8 |% @@ -592,8 +599,8 @@ -- :: |der:pkcs8: DER encoding for asymmetric keys :: - :: en(coding) and de(coding) for public (pass) and private (ring) keys - :: RSA-only for now + :: En(coding) and de(coding) for public (pass) and private (ring) keys. + :: RSA-only for now. :: ++ der |% @@ -610,8 +617,8 @@ -- :: |pem:pkcs8: PEM encoding for asymmetric keys :: - :: en(coding) and de(coding) for public (pass) and private (ring) keys - :: RSA-only for now + :: En(coding) and de(coding) for public (pass) and private (ring) keys. + :: RSA-only for now. :: ++ pem |% @@ -629,7 +636,7 @@ -- :: |pkcs10: certificate signing requests (rfc2986) :: -:: only implemented for RSA keys with subject-alternate names +:: Only implemented for RSA keys with subject-alternate names. :: ++ pkcs10 => |% @@ -663,8 +670,10 @@ [%int 0] [%seq ~] (pass:en:spec:pkcs8 key) - :+ %con [| 0] - =- ~(ren raw:en:^der -) + :+ %con + `bespoke:asn1`[| 0] + %~ ren + raw:en:^der :~ %seq [%obj csr-ext:obj:asn1] :~ %set @@ -682,7 +691,7 @@ %+ turn hot :: implicit, context-specific tag #2 (IA5String) :: XX sanitize string? - |=(h=(list @t) [%con [& 2] (rip 3 (join '.' h))]) + |=(h=(list @t) [%con `bespoke:asn1`[& 2] (rip 3 (join '.' h))]) -- :: |de:spec:pkcs10: ASN.1 decoding for certificate signing requests ++ de !! @@ -704,7 +713,7 @@ -- :: +en-json-sort: json encoding with sorted object keys :: -:: to be included in %zuse, with sorting optional? +:: to be included in %zuse, with sorting optional? :: ++ en-json-sort :: XX rename |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) @@ -757,8 +766,8 @@ :: :: |jwk: json representations of cryptographic keys (rfc7517) :: -:: url-safe base64 encoding of key parameters in big-endian byte order -:: RSA-only for now +:: Url-safe base64 encoding of key parameters in big-endian byte order. +:: RSA-only for now :: ++ jwk |% @@ -853,7 +862,7 @@ -- :: |jws: json web signatures (rfc7515) :: -:: flattened signature only +:: Note: flattened signature form only. :: ++ jws |% @@ -878,15 +887,15 @@ [%o (~(put by p.pro) %alg s+'RS256')] :: +encode:sign:jws: encode json for signing :: - :: alphabetically sort object keys, url-safe base64 encode - :: the serialized json + :: Alphabetically sort object keys, url-safe base64 encode + :: the serialized json. :: ++ encode |= jon=json (en-base64url (crip (en-json-sort aor jon))) :: +sign:sign:jws: compute signature :: - :: url-safe base64 encode in big-endian byte order + :: Url-safe base64 encode in big-endian byte order. :: ++ sign |= [protect=cord payload=cord] @@ -899,7 +908,7 @@ -- :: +eor: explicit sort order comparator :: -:: lookup :a and :b in :lit, pass their indices to :com +:: Lookup :a and :b in :lit, and pass their indices to :com. :: ++ eor |= [com=$-([@ @] ?) lit=(list)] From 3a1c0725278ecf6d8acb92b6c26b6f662e9ade7f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 22 Jun 2018 23:43:41 -0400 Subject: [PATCH 56/95] revises :acme state, rewrites API client --- app/acme.hoon | 1062 +++++++++++++++++++++++++++++++------------------ 1 file changed, 679 insertions(+), 383 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 96ffeecee..63166ac30 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -926,13 +926,15 @@ ?~ t.hot (rap 3 [i.hot out]) $(out [sep i.hot out], hot t.hot) -:: -:::: acme api response json reparsers +:: |grab: acme api response json reparsers :: ++ grab =, dejs:format |% + :: +json-purl: parse url + :: ++ json-purl (su auri:de-purl:html) + :: +directory: parse ACME service directory :: ++ directory %- ot @@ -942,6 +944,7 @@ ['revokeCert' json-purl] ['keyChange' json-purl] == + :: +acct: parse ACME service account :: ++ acct %- ot @@ -950,6 +953,7 @@ ['status' so] :: ignore key, contact, initialIp == + :: +order: parse certificate order :: ++ order %- ot @@ -958,12 +962,18 @@ ['expires' so] :: XX (su iso-8601) ['status' so] == + :: +finalizing-order: parse order in a finalizing state + :: + :: XX remove once +order has optional keys :: ++ finalizing-order %- ot :~ ['expires' so] :: XX (su iso-8601) ['status' so] == + :: +final-order: parse order in a finalized state + :: + :: XX remove once +order has optional keys :: ++ final-order %- ot @@ -971,12 +981,15 @@ ['status' so] ['certificate' json-purl] == - :: + :: +auth: parse authorization ++ auth => |% + :: +iden: parse dns identifier to +turf + :: ++ iden |= [typ=@t hot=host] ?>(&(?=(%dns typ) ?=([%& *] hot)) p.hot) + :: +trial: transform parsed domain validation challenge :: ++ trial |= a=(list [typ=@t sas=@t url=purl tok=@t]) @@ -991,6 +1004,7 @@ ['expires' so] :: XX (su iso-8601) ['challenges' (cu trial (ar challenge))] == + :: +challenge: parse domain validation challenge :: ++ challenge %- ot @@ -999,6 +1013,7 @@ ['url' json-purl] ['token' so] == + :: +error: parse ACME service error response :: ++ error %- ot @@ -1011,290 +1026,461 @@ :::: acme state :: |% -+= move [bone card] :: -+= card :: - $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] :: - [%well wire path (unit mime)] :: - == :: -+= directory :: ACME v2 - $: reg/purl :: newAccount - non/purl :: newNonce - der/purl :: newOrder - rev/purl :: revokeCert - rek/purl :: keyChange - == :: -+= acct [key=key:rsa reg=(unit [wen=@t kid=@t])] :: account XX wen=@da -+= turf (list @t) :: domain -+= trial :: challenge - $% [%http cal=purl tok=@t sas=?(%recv %pend %auth)] :: http-only - == :: -+= auth :: authorization - $% [%0 aut=purl] :: received - [%1 aut=purl dom=turf cal=trial] :: in-progress - == :: -+= order :: certificate order - $% [%0 dom=(list turf)] :: initialized - [%1 dom=(list turf) exp=@t der=purl fin=purl aut=(map @ud auth)] :: XX exp=@da - [%2 dom=(list turf) exp=@t der=purl fin=purl key=key:rsa csr=@ux] :: cert requested - == :: -+= config [key=key:rsa exp=@da cer=wain] :: finalized config -+= history :: isn't over - $: act=(list acct) :: - rod=(list order) :: - fig=(list (pair (list turf) config)) :: - == :: -+= acme :: - $: bas=purl :: service base url - dir=directory :: service urls - act=acct :: service account - non=@t :: nonce from last - rod=(map @ud order) :: active orders - cey=key:rsa :: cert key - liv=(map (list turf) config) :: active config - hit=history :: a foreign country - == :: --- :: +:: +move: output effect +:: ++= move [bone card] +:: +card: output effect payload +:: ++= card + $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] + [%well wire path (unit mime)] + == +:: +turf: a domain, TLD first +:: ++= turf (list @t) +:: +acct: an ACME service account +:: ++= acct + $: :: key: account keypair + :: + key=key:rsa + :: reg: account registration + :: + reg=(unit [wen=@t kid=@t]) :: XX wen=@da + == +:: +config: finalized configuration +:: ++= config + $: :: dom: domains + :: + dom=(set turf) + :: key: certificate keypair + :: + key=key:rsa + :: cer: signed certificate + :: + cer=wain + :: exp: expiration date + :: + exp=@da + :: dor: source ACME service order URL + :: + dor=purl + == +:: +trial: domain validation challenge +:: ++= trial + $% :: %http only for now + $: %http + :: ego: ACME service challenge url + :: + ego=purl + :: tok: challenge token + :: + tok=@t + :: sas: challenge status + :: + sas=?(%recv %pend %auth) + == == +:: +auth: domain authorization +:: ++= auth + $: :: ego: ACME service authorization url + :: + ego=purl + :: dom: domain under authorization + :: + dom=turf + :: cal: domain validation challenge + :: + cal=trial + == +:: +order-auth: domain authorization state for order processing +:: ++= order-auth + $: :: pending: remote authorization urls + :: + pending=(list purl) + :: active: authorization in progress + :: + active=(unit [idx=@ auth]) + :: done: finalized authorizations (XX or failed?) + :: + done=(list auth) + == +:: +order: ACME certificate order +:: ++= order + $: :: dom: domains + :: + dom=(set turf) + :: sas: order state + :: + sas=$@(%wake [%rest wen=@da]) + :: exp: expiration date + :: + :: XX @da once ISO-8601 parser + :: + exp=@t + :: ego: ACME service order url + :: + ego=purl + :: fin: ACME service order finalization url + :: + fin=purl + :: key: certificate keypair + :: + key=key:rsa + :: csr: DER-encoded PKCS10 certificate signing request + :: + csr=@ux + :: aut: authorizations required by this order + :: + aut=order-auth + == +:: +history: archive of past ACME service interactions +:: ++= history + $: :: act: list of revoked account keypairs + :: + act=(list acct) + :: fig: list of expired configurations + :: + fig=(list config) + :: fal: list of failed order attempts + :: + fal=(list order) + == +:: +directory: ACME v2 service directory +:: ++= directory + $: :: reg: registration url (newAccount) + :: + reg=purl + :: non: nonce creation url (newNonce) + :: + non=purl + :: der: order creation url (newOrder) + :: + der=purl + :: rev: certificate revocation url (revokeCert) + :: + rev=purl + :: rek: account key revocation url (keyChange) + :: + rek=purl + == +:: +acme: complete app state +:: ++= acme + $: :: bas: ACME service root url + :: + bas=purl + :: dir: ACME service directory + :: + dir=directory + :: act: ACME service account + :: + act=acct + :: liv: active, live configuration + :: + liv=(unit config) + :: hit: ACME account history + :: + hit=history + :: nonces: list of unused nonces + :: + nonces=(list @t) + :: rod: active, in-progress order + :: + rod=(unit order) + :: pen: pending domains for next order + :: + pen=(unit (set turf)) + :: cey: certificate key XX move? + :: + cey=key:rsa + == +-- :: :::: acme app :: -=| mov=(list move) -|_ [bow=bowl:gall acme] +:: mov: list of outgoing moves for the current transaction :: -++ this . :: XX #712 +=| mov=(list move) +:: +|_ [bow=bowl:gall acme] +:: +this: self +:: +:: XX Should be a +* core alias, see urbit/arvo#712 +:: +++ this . +:: +emit: emit a move :: ++ emit |= car=card ~& [%emit car] this(mov [[ost.bow car] mov]) -:: -++ emil - |= rac=(list card) - q:(spin rac this |=([a=card b=_this] [~ (emit:b a)])) +:: +abet: finalize transaction :: ++ abet + ^- (quip move _this) [(flop mov) this(mov ~)] +:: +request: generic http request :: ++ request - |= [wir=wire url=purl bod=(unit json)] - |^ ^- card - [%hiss wir [~ ~] %httr %hiss url moth] - :: - ++ moth - ?~ bod - [%get ~ ~] - [%post (my content-type+['application/jose+json' ~] ~) `body] - :: - ++ body - ?> ?=(^ bod) - ^- octs - =; pro=json - (as-octt:mimes:html (en-json:html (sign:jws key.act pro u.bod))) - :- %o %- my :~ - nonce+s+non - url+s+(crip (en-purl:html url)) - ?^ reg.act - kid+s+kid.u.reg.act - jwk+(pass:en:jwk key.act) - == - -- -:: -++ directory - (emit (request /acme/dir/(scot %p our.bow) bas ~)) -:: -++ nonce - |= nex=wire - ^+ this - ?> ?=([%next *] nex) - (emit (request (weld `wire`/acme/non `wire`nex) non.dir ~)) -:: -++ register - %- emit(reg.act ~) - %^ request /acme/reg/(scot %p our.bow) - reg.dir - `[%o (my [['termsOfServiceAgreed' b+&] ~])] -:: -++ new-order - ^+ this - ?~ reg.act - this :: XX pending registration assumed - %- emil - %+ turn - (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %0 *] a))) - |= [i=@ud rod=order] + |= [wir=wire req=hiss] ^- card - ?> ?=([%0 *] rod) - %^ request /acme/der/(scot %ud i) - der.dir + [%hiss wir [~ ~] %httr %hiss req] +:: +signed-request: JWS JSON POST +:: +++ signed-request + |= [url=purl non=@t bod=json] + ^- hiss + :^ url %post + (my content-type+['application/jose+json' ~] ~) :- ~ - ^- json + ^- octs + =; pro=json + (as-octt:mimes:html (en-json:html (sign:jws key.act pro bod))) :- %o %- my :~ - :- %identifiers - :- %a - %+ turn - dom.rod - |=(a=turf [%o (my type+s+'dns' value+s+(join '.' a) ~)]) + nonce+s+non + url+s+(crip (en-purl:html url)) + ?^ reg.act + kid+s+kid.u.reg.act + jwk+(pass:en:jwk key.act) == +:: +bad-nonce: check if an http response is a badNonce error :: -++ authorize - ^+ this - %- emil - =/ aut=(list (trel @ud @ud purl)) - %- zing - %+ turn - (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) - |= [ider=@ud rod=order] - ?> ?=([%1 *] rod) - %+ turn - ~(tap by aut.rod) - |= [i=@ud aut=auth] - ?> ?=([%0 *] aut) - [i ider aut.aut] - %+ turn aut - |= [i=@ud ider=@ud aut=purl] - ^- card - (request /acme/aut/(scot %ud i)/der/(scot %ud ider) aut ~) +++ bad-nonce + |= rep=httr + ^- ? + :: XX always 400? + ?. =(400 p.rep) | + ?~ r.rep | + =/ jon=(unit json) (de-json:html q.u.r.rep) + ?~ jon | + :: XX unit parser, types + =('urn:ietf:params:acme:error:badNonce' +:(error:grab u.jon)) +:: |effect: send moves to advance :: -++ save-challenge - ^+ this - %- emil - =/ cal=(list (trel @ud @ud trial)) - %- zing - %+ turn - (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) - |= [ider=@ud rod=order] - ?> ?=([%1 *] rod) - %+ turn - ~(tap by aut.rod) - |= [i=@ud aut=auth] - ?> ?=([%1 *] aut) - [i ider cal.aut] - %+ turn cal - |= [i=@ud ider=@ud cal=trial] - ^- card - :^ %well - /acme/wel/(scot %ud i)/der/(scot %ud ider) - /acme-challenge/[tok.cal] - :+ ~ - /text/plain - %- as-octs:mimes:html - (rap 3 [tok.cal '.' (pass:thumb:jwk key.act) ~]) -:: -++ test-challenge - ^+ this - %- emil - =/ cal=(list [@ud @ud turf trial]) - %- zing - %+ turn - (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) - |= [ider=@ud rod=order] - ?> ?=([%1 *] rod) - %+ turn - ~(tap by aut.rod) - |= [i=@ud aut=auth] - ?> ?=([%1 *] aut) - [i ider dom.aut cal.aut] - %+ turn cal - |= [i=@ud ider=@ud dom=turf cal=trial] - ^- card - =/ wir=wire /acme/tcal/(scot %ud i)/der/(scot %ud ider) - =/ pat=path /'.well-known'/acme-challenge/[tok.cal] - =/ pul=purl [[| ~ [%& dom]] [~ pat] ~] - (request wir pul ~) -:: -++ finalize-challenge - ^+ this - %- emil - =/ cal=(list (trel @ud @ud purl)) - %- zing - %+ turn - (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %1 *] a))) - |= [ider=@ud rod=order] - ?> ?=([%1 *] rod) - %+ turn - ~(tap by aut.rod) - |= [i=@ud aut=auth] - ?> ?=([%1 *] aut) - [i ider cal.cal.aut] - %+ turn cal - |= [i=@ud ider=@ud cal=purl] - ^- card - =/ wir=wire /acme/cal/(scot %ud i)/der/(scot %ud ider) - (request wir cal `[%o ~]) -:: -++ finalize-order - ^+ this - %- emil - =/ csr=(list (trel @ud purl @ux)) - %+ turn - (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %2 *] a))) - |= [i=@ud rod=order] - ?> ?=([%2 *] rod) - [i fin.rod csr.rod] - %+ turn csr - |= [i=@ud fin=purl csr=@ux] - ^- card - %^ request - /acme/fin/(scot %ud i) - fin - `[%o (my csr+s+(en-base64url csr) ~)] -:: -++ poll-order - ^+ this - %- emil - =/ url=(list (pair @ud purl)) - %+ turn - (skim ~(tap by rod) |=(a=[@ud order] ?=([@ %2 *] a))) - |= [i=@ud rod=order] - ?> ?=([%2 *] rod) - [i der.rod] - %+ turn url - |= [i=@ud der=purl] - ^- card - (request /acme/por/(scot %ud i) der ~) -:: -++ sigh-httr - |= [wir=wire rep=httr:eyre] - ^- (quip move _this) - ~& [wir rep] - ?> ?=([%acme ^] wir) - =/ ron (skim q.rep |=((pair @t @t) ?=(%replay-nonce p))) - =? non ?=(^ ron) q.i.ron - ?. ?=(%2 (div p.rep 100)) - ~& %lack-of-success - ?: ?=(%tcal i.t.wir) - abet:test-challenge :: XX sleep? - =/ bod=[typ=@t det=@t] - (error:grab (need (de-json:html q:(need r.rep)))) - ?: =('urn:ietf:params:acme:error:badNonce' typ.bod) - ?. ?=(?(%reg %der %aut %cal %fin) i.t.wir) - ~&(unrecoverable-bad-nonce+wir abet:this) - abet:(nonce /next/[i.t.wir]) - :: XX challenge is not pending - :: XX order can't be finalized - abet:this - ~| sigh-fail+rep - ?+ i.t.wir !! - %dir - =< abet:(nonce /next/reg) - =/ bod=^directory - (directory:grab (need (de-json:html q:(need r.rep)))) - this(dir bod) +++ effect + |% + :: +directory: get ACME service directory :: - %non - =< abet - ?. ?=([%next ^] t.t.wir) - ~&(unrecognized-nonce-wire+wir this) - =* nex i.t.t.t.wir - ?+ nex ~&(unknown-nonce-next+nex this) - %reg register - %der new-order - %aut authorize - %cal finalize-challenge - %fin finalize-order + ++ directory + ^+ this + (emit (request /acme/directory/(scot %p our.bow) bas %get ~ ~)) :: XX now? + :: +nonce: get a new nonce for the next request + :: + ++ nonce + |= nex=wire + ^+ this + ?> ?=([%next *] nex) :: XX now? + (emit (request (weld `wire`/acme/nonce `wire`nex) non.dir %get ~ ~)) + :: +register: create ACME service account + :: + :: Note: accepts services ToS. + :: + ++ register + ^+ this + ?~ nonces + (nonce /next/register) + %- emit(nonces t.nonces, reg.act ~) + %+ request + /acme/register/(scot %p our.bow) :: XX now? + %^ signed-request reg.dir i.nonces + [%o (my [['termsOfServiceAgreed' b+&] ~])] + :: XX rekey + :: + :: +new-order: create a new certificate order + :: + ++ new-order + ^+ this + ~| %new-order-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=([~ ^] pen) ~|(%no-domains !!) + ?~ nonces + (nonce /next/new-order) + %- emit(nonces t.nonces) + %+ request + /acme/new-order/(scot %da now.bow) + %^ signed-request der.dir i.nonces + :- %o %- my :~ + :- %identifiers + :- %a + %+ turn + ~(tap in `(set turf)`u.pen) + |=(a=turf [%o (my type+s+'dns' value+s+(join '.' a) ~)]) == + :: +finalize-order: finalize completed order :: - %reg - =< abet:new-order + ++ finalize-order + ^+ this + ~| %finalize-order-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=(^ rod) ~|(%no-active-order !!) + ?. ?=(~ pending.aut.u.rod) ~|(%pending-authz !!) + ?. ?=(~ active.aut.u.rod) ~|(%active-authz !!) + :: XX revisit wrt rate limits + ?> ?=(%wake sas.u.rod) + ?~ nonces + (nonce /next/finalize-order) + %- emit(nonces t.nonces) + %+ request + /acme/finalize-order/(scot %da now.bow) + %^ signed-request fin.u.rod i.nonces + [%o (my csr+s+(en-base64url csr.u.rod) ~)] + :: +check-order: check completed order for certificate availability + :: + ++ check-order + ^+ this + ~| %check-order-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=(^ rod) ~|(%no-active-order !!) + ?. ?=(~ pending.aut.u.rod) ~|(%pending-authz !!) + ?. ?=(~ active.aut.u.rod) ~|(%active-authz !!) + :: XX revisit wrt rate limits + ?> ?=(%wake sas.u.rod) + (emit (request /acme/check-order/(scot %da now.bow) ego.u.rod %get ~ ~)) + :: +certificate: download PEM-encoded certificate + :: + ++ certificate + |= url=purl + ^+ this + ~| %certificate-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=(^ rod) ~|(%no-active-order !!) + =/ hed (my accept+['applicate/x-pem-file' ~] ~) + (emit (request /acme/certificate/(scot %da now.bow) url %get hed ~)) + :: +get-authz: get next ACME service domain authorization object + :: + ++ get-authz + ^+ this + ~| %get-authz-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=(^ rod) ~|(%no-active-order !!) + ?. ?=(^ pending.aut.u.rod) ~|(%no-pending-authz !!) + :: XX revisit wrt rate limits + ?> ?=(%wake sas.u.rod) + %- emit + (request /acme/get-authz/(scot %da now.bow) i.pending.aut.u.rod %get ~ ~) + :: XX check/finalize-authz ?? + :: + :: +save-trial: save ACME domain validation challenge to /.well-known/ + :: + ++ save-trial + ^+ this + ~| %save-trial-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=(^ rod) ~|(%no-active-order !!) + ?. ?=(^ active.aut.u.rod) ~|(%no-active-authz !!) + :: XX revisit wrt rate limits + ?> ?=(%wake sas.u.rod) + =* aut u.active.aut.u.rod + %- emit + :^ %well + :: XX idx in wire? + /acme/save-trial/(scot %da now.bow) + /acme-challenge/[tok.cal.aut] + :+ ~ + /text/plain + %- as-octs:mimes:html + (rap 3 [tok.cal.aut '.' (pass:thumb:jwk key.act) ~]) + :: +test-trial: confirm that ACME domain validation challenge is available + :: + ++ test-trial + ^+ this + ~| %test-trial-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=(^ rod) ~|(%no-active-order !!) + ?. ?=(^ active.aut.u.rod) ~|(%no-active-authz !!) + :: XX revisit wrt rate limits + ?> ?=(%wake sas.u.rod) + =* aut u.active.aut.u.rod + =/ pat=path /'.well-known'/acme-challenge/[tok.cal.aut] + :: note: requires port 80, just as the ACME service will + =/ url=purl [[sec=| por=~ hos=[%& dom.aut]] [ext=~ pat] hed=~] + :: =/ url=purl [[sec=| por=`8.081 hos=[%& /localhost]] [ext=~ pat] hed=~] + :: XX idx in wire? + (emit (request /acme/test-trial/(scot %da now.bow) url %get ~ ~)) + :: +finalize-trial: notify ACME service that challenge is ready + :: + ++ finalize-trial + ^+ this + ~| %test-trial-effect-fail + ?. ?=(^ reg.act) ~|(%no-account !!) + ?. ?=(^ rod) ~|(%no-active-order !!) + ?. ?=(^ active.aut.u.rod) ~|(%no-active-authz !!) + :: XX revisit wrt rate limits + ?> ?=(%wake sas.u.rod) + =* aut u.active.aut.u.rod + ?~ nonces + (nonce /next/finalize-trial) + %- emit(nonces t.nonces) + %+ request + :: XX idx in wire? + /acme/finalize-trial/(scot %da now.bow) + :: empty object included for signature + (signed-request ego.cal.aut i.nonces [%o ~]) + :: XX delete-trial? + :: + :: +retry: retry effect after timeout + :: + ++ retry !! + -- +:: |event: accept event, emit next effect(s) +:: +:: XX should these next effects be triggered at call sites instead? +:: +++ event + |% + :: +directory: accept ACME service directory, trigger registration + :: + ++ directory + |= rep=httr + ^+ this + ?. =(200 p.rep) + :: XX never happened yet, wat do? + ~& [%directory-fail rep] + this + =. dir (directory:grab (need (de-json:html q:(need r.rep)))) + ?~(reg.act register:effect this) + :: +nonce: accept new nonce (XX already saved?), trigger next effect + :: + :: As specified in the wire. + :: + ++ nonce + |= [wir=wire rep=httr] + ^+ this + ?. =(204 p.rep) + :: XX never happened yet, retry nonce? + ~& [%nonce-fail wir rep] + this + ?. &(?=(^ wir) ?=([%next ^] t.wir)) + ~& [%unrecognized-nonce-wire wir] + this + =* nex i.t.t.wir + ?+ nex + ~& [%unknown-nonce-next nex] + this + %register register:effect + %new-order new-order:effect + %finalize-order finalize-order:effect + %finalize-trial finalize-trial:effect + == + :: +register: accept ACME service registration + :: + ++ register + |= [wir=wire rep=httr] + ^+ this + ?. =(201 p.rep) + ::XX 204? + ?: (bad-nonce rep) + (nonce:effect /next/register) + :: XX retry immediately or backoff? + ~& [%register-fail wir rep] + this =/ loc=@t q:(head (skim q.rep |=((pair @t @t) ?=(%location p)))) =/ wen=@t :: XX @da @@ -1305,136 +1491,241 @@ ?> ?=(%valid sas.bod) wen.bod this(reg.act `[wen loc]) + :: XX rekey :: - %der - =< abet:authorize - =/ i=@ud (slav %ud (head t.t.wir)) - =/ der=order (~(got by rod) i) - ?> ?=([%0 *] der) + :: +new-order: order created, begin processing authorizations + :: + ++ new-order + |= [wir=wire rep=httr] + ^+ this + ?. =(201 p.rep) + ?: (bad-nonce rep) + (nonce:effect /next/new-order) + :: XX retry immediately or backoff? + :: XX possible 204? + ~& [%new-order-fail wir rep] + this + :: XX delete order if not? + ?> ?=(^ pen) =/ loc=@t q:(head (skim q.rep |=((pair @t @t) ?=(%location p)))) - =/ url=purl (need (de-purl:html loc)) + =/ ego=purl (need (de-purl:html loc)) + :: XX add parser output types + :: XX parse identifiers, confirm equal to pending domains + :: XX check status =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] (order:grab (need (de-json:html q:(need r.rep)))) - =/ aut %- ~(gas by *(map @ud auth)) - (spun aut.bod |=([a=purl b=@ud] [[b %0 a] +(b)])) - =/ dor=order [%1 dom.der exp.bod url fin.bod aut] - this(rod (~(put by rod) i dor)) + :: XX maybe generate key here? + =/ csr=@ux (en:der:pkcs10 cey ~(tap in u.pen)) + =/ dor=order + [dom=u.pen sas=%wake exp.bod ego fin.bod cey csr [aut.bod ~ ~]] + get-authz:effect(rod `dor, pen ~) + :: +finalize-order: order finalized, poll for certificate :: - %aut - =< abet:test-challenge:save-challenge - ?> ?=([@ %der @ *] t.t.wir) - =/ i (slav %ud i.t.t.wir) - =/ ider (slav %ud i.t.t.t.t.wir) - =/ der=order (~(got by rod) ider) - ?> ?=([%1 *] der) - =/ aut=auth (~(got by aut.der) i) - ?> ?=([%0 *] aut) - =/ bod=[dom=turf sas=@t exp=@t cal=[typ=@t sas=@t url=purl tok=@t]] - (auth:grab (need (de-json:html q:(need r.rep)))) - =/ cal=trial - [%http url.cal.bod tok.cal.bod %recv] :: XX parse tok? - =/ tau=auth [%1 aut.aut dom.bod cal] - =. der der(aut (~(put by aut.der) i tau)) - this(rod (~(put by rod) ider der)) - :: - %tcal - :: XX check content type and response body - abet:finalize-challenge - :: - %cal - =< abet:finalize-order - ?> ?=([@ %der @ *] t.t.wir) - =/ i (slav %ud i.t.t.wir) - =/ ider (slav %ud i.t.t.t.t.wir) - =/ der=order (~(got by rod) ider) - ?> ?=([%1 *] der) - =/ aut=auth (~(got by aut.der) i) - ?> ?=([%1 *] aut) - :: XX 204 assuming pending? - :: =/ bod=[typ=@t sas=@t url=purl tok=@t] - :: (challenge:grab (need (de-json:html q:(need r.rep)))) - :: ?> ?=(%pending sas.bod) - =. sas.cal.aut %pend - =. der der(aut (~(put by aut.der) i aut)) - =. rod (~(put by rod) ider der) - =/ fin=(list (pair @ud order)) - %+ skim - ~(tap by rod) - |= a=[@ud order] - ?& ?=([@ %1 *] a) - %+ levy - ~(tap by aut.a) - |= [i=@ud aut=auth] - ?& ?=([%1 *] aut) - ?=(%pend sas.cal.aut) - == == - %= this - rod %- ~(gas by rod) - %+ turn fin - |= [i=@ud der=order] - ^+ [i der] - ?> ?=([%1 *] der) - :: =/ k=key:rsa rekey :: XX reuse - =/ csr=@ux (en:der:pkcs10 cey dom.der) - [i %2 dom.der exp.der der.der fin.der cey csr] - :: XX save pending authz somewhere instead of just dropping them - == - :: - %fin - :: XX rep body missing authorizations + ++ finalize-order + |= [wir=wire rep=httr] + ^+ this + ?. =(200 p.rep) + ?: (bad-nonce rep) + (nonce:effect /next/finalize-order) + ~& [%finalize-order-fail wir rep] + ?> ?=(^ rod) + :: XX get the failure reason + this(rod ~, fal.hit [u.rod fal.hit]) + ?> ?=(^ rod) + :: XX rep body missing authorizations, need flexible/separate parser :: XX finalizing-order :: =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] :: (order:grab (need (de-json:html q:(need r.rep)))) :: XX check status? (i don't think failures get here) - abet:poll-order + check-order:effect + :: +check-order: check if certificate is ready for finalized order :: - %por - =/ i=@ud (slav %ud (head t.t.wir)) + ++ check-order + |= [wir=wire rep=httr] + ^+ this + ?. =(200 p.rep) + :: XX retry immediately? backoff? + ~& [%check-order-fail wir rep] + this + ?> ?=(^ rod) =/ raw=json (need (de-json:html q:(need r.rep))) =/ bod=[exp=@t sas=@t] (finalizing-order:grab raw) ?+ sas.bod - ~&(poll-order-status+sas.bod abet) - %invalid abet :: XX check authz, retry order? - %pending abet:poll-order - %processing abet:poll-order - %valid =< abet - =/ bod=[exp=@t sas=@t cer=purl] - (final-order:grab raw) :: XX json reparser unit - %- emit :: XX accept hed - (request /acme/cer/(scot %ud i) cer.bod ~) - :: XX del .well-known + ~& [%check-order-status-unknown sas.bod] + this + :: + %invalid + ~& [%check-order-fail %invalid wir rep] + :: XX check authz for debug info + :: XX send notification somehow? + :: XX start over with new order? + this + :: + %pending + check-order:effect + :: + %processing + check-order:effect + :: + %valid + :: XX json reparser unit + =/ bod=[exp=@t sas=@t cer=purl] + (final-order:grab raw) + :: XX update order state + :: XX =< delete-trial + (certificate:effect cer.bod) == :: - %cer :: XX send configuration to eyre - =< abet - =/ i=@ud (slav %ud (head t.t.wir)) - =/ der=order (~(got by rod) i) - =/ cer=wain - (to-wain:format q:(need r.rep)) - ?> ?=([%2 *] der) - %= this - liv (~(put by liv) dom.der [key.der *@da cer]) :: XX exp when? - rod (~(del by rod) i) - rod.hit [der rod.hit] - == + :: +certificate: accept PEM-encoded certificate + :: + ++ certificate + |= [wir=wire rep=httr] + ^+ this + ?. =(200 p.rep) + :: XX retry immediately? backoff? + ~& [%certificate-fail wir rep] + this + ?> ?=(^ rod) + =/ cer=wain (to-wain:format q:(need r.rep)) + =/ fig=config + :: XX expiration date + [dom.u.rod key.u.rod cer *@da ego.u.rod] + =? fig.hit ?=(^ liv) [u.liv fig.hit] + this(liv `fig, rod ~) + :: XX send configuration to eyre + :: XX other subscribers? + :: +get-authz: accept ACME service authorization object + :: + ++ get-authz + |= [wir=wire rep=httr] + ^+ this + ?. =(200 p.rep) + :: XX retry immediately? backoff? + ~& [%get-authz-fail wir rep] + this + ?> ?=(^ rod) + ?> ?=(^ pending.aut.u.rod) + :: XX parser types + =/ bod=[dom=turf sas=@t exp=@t cal=[typ=@t sas=@t ego=purl tok=@t]] + (auth:grab (need (de-json:html q:(need r.rep)))) + =/ cal=trial + :: XX parse token to verify url-safe base64? + [%http ego.cal.bod tok.cal.bod %recv] + :: XX check that URLs are the same + =/ tau=auth [i.pending.aut.u.rod dom.bod cal] + :: XX get idx from wire instead? + =/ idx=@ud +((lent done.aut.u.rod)) + =/ rod-aut=order-auth + %= aut.u.rod + pending t.pending.aut.u.rod + active `[idx tau] + == + =< test-trial:effect + save-trial:effect(aut.u.rod rod-aut) + :: XX check/finalize-authz ?? + :: + :: +test-trial: accept response from challenge test + :: + :: Note that +save-trail:effect has no corresponding event. + :: + ++ test-trial + |= [wir=wire rep=httr] + ^+ this + ?. =(200 p.rep) + :: XX retry immediately? backoff? + ~& [%test-trial-fail wir rep] + this + ?> ?=(^ rod) + ?> ?=(^ active.aut.u.rod) + :: XX check content type and response body + finalize-trial:effect + :: +finalize-trial: + :: + ++ finalize-trial + |= [wir=wire rep=httr] + ^+ this + ?. =(200 p.rep) + ?: (bad-nonce rep) + (nonce:effect /next/finalize-trial) + :: XX retry? or cancel order? + :: XX 204 assume pending? + ~& [%finalize-trial-fail wir rep] + :: XX handle "challenge is not pending" + this + ?> ?=(^ rod) + ?> ?=(^ active.aut.u.rod) + =* aut u.active.aut.u.rod + =/ bod=[typ=@t sas=@t url=purl tok=@t] + (challenge:grab (need (de-json:html q:(need r.rep)))) + :: XX what if it's not? + ?> ?=(%pending sas.bod) + ~! aut + =/ rod-aut=order-auth + aut.u.rod(active ~, done [+.aut(sas.cal %pend) done.aut.u.rod]) + ?~ pending.aut.u.rod + finalize-order:effect(aut.u.rod rod-aut) + get-authz:effect(aut.u.rod rod-aut) + :: XX delete-trial? + :: + :: +retry: retry effect after timeout + :: + ++ retry + :: XX implement wire parsing / next effect + !! + -- +:: +sigh-tang: handle http request failure +:: +++ sigh-tang + |= [wir=wire saw=tang] + ^- (quip move _this) + ~& [%sigh-tang wir] + :: XX take evasive action + [((slog saw) ~) this] +:: +sigh-httr: accept http response +:: +++ sigh-httr + |= [wir=wire rep=httr] + ^- (quip move _this) + ~& [wir rep] + ?> ?=([%acme ^] wir) + :: add nonce to pool, if present + =/ nonhed (skim q.rep |=((pair @t @t) ?=(%replay-nonce p))) + =? nonces ?=(^ nonhed) [q.i.nonhed nonces] + =< abet + ~| [%sigh-fail wir rep] + ?+ i.t.wir + ~&([%unknown-wire i.t.wir] !!) + %directory (directory:event rep) + %nonce (nonce:event t.wir rep) + %register (register:event t.wir rep) + :: XX rekey + %new-order (new-order:event t.wir rep) + %finalize-order (finalize-order:event t.wir rep) + %check-order (check-order:event t.wir rep) + %get-authz (get-authz:event t.wir rep) + :: XX check/finalize-authz ?? + %test-trial (test-trial:event t.wir rep) + %finalize-trial (finalize-trial:event t.wir rep) + :: XX delete-trial? == :: ++ poke-noun |= a=* ^- (quip move _this) - ?+ a ~& +<+.this - [~ this] - %init abet:init - %reg abet:register - %order abet:new-order - %auth abet:authorize - %trial abet:test-challenge - %final abet:finalize-order - %poll abet:poll-order - %our abet:(add-order /org/urbit/(crip +:(scow %p our.bow)) ~) + =< abet + ?+ a + ~&(+<+.this this) + %init init + %reg register:effect + %order new-order:effect + %auth get-authz:effect + %trial test-trial:effect + %final finalize-order:effect + %poll check-order:effect + %our (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) %test test == :: @@ -1444,9 +1735,12 @@ :: ++ prep _[~ this] ++ prep |= old=(unit acme) - ?~ old - abet:init - [~ this(+<+ u.old)] + ^- (quip move _this) + ?^ old + [~ this(+<+ u.old)] + ?: ?=(?(%earl %pawn) (clan:title our.bow)) + [~ this] + abet:init :: ++ rekey :: XX do something about this |= eny=@ @@ -1454,14 +1748,16 @@ |- ^- key:rsa =/ k (new-key:rsa 2.048 eny) =/ m (met 0 n.pub.k) - ?: =(0 (mod m 8)) k + :: ?: =(0 (mod m 8)) k + ?: =(2.048 m) k ~& [%key iter=i width=m] $(i +(i), eny +(eny)) :: ++ init =/ url 'https://acme-staging-v02.api.letsencrypt.org/directory' - %= directory + =< directory:effect + %= this bas (need (de-purl:html url)) act [(rekey eny.bow) ~] cey (rekey (mix eny.bow (shaz now.bow))) @@ -1472,12 +1768,12 @@ ++ add-order |= dom=(list turf) ^+ this - :: XX temporarily force one at a time - :: new-order(rod (~(put by rod) ~(wyt by rod) [%0 dom])) - %= new-order - rod.hit (weld ~(val by rod) rod.hit) - rod (~(put by ^+(rod ~)) ~(wyt by rod) [%0 dom]) - == + :: XX we may have pending moves out for this order + :: XX put dates in wires, check against order creation date? + :: XX or re-use order-id? + =? fal.hit ?=(^ rod) [u.rod fal.hit] + :: XX check registration, defer + new-order:effect(pen `(sy dom)) :: ++ test =, tester:tester @@ -1498,7 +1794,7 @@ test-jws test-csr == - ?~(out abet ((slog out) abet)) + ?~(out this ((slog out) this)) :: ++ test-base64 ;: weld From 1fb2f0624fb3bfef1af7c234dc429e94b8a55356 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sat, 23 Jun 2018 00:06:53 -0400 Subject: [PATCH 57/95] adds +certificate:event to +sigh-httr --- app/acme.hoon | 1 + 1 file changed, 1 insertion(+) diff --git a/app/acme.hoon b/app/acme.hoon index 63166ac30..46e0d2ab3 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1705,6 +1705,7 @@ %new-order (new-order:event t.wir rep) %finalize-order (finalize-order:event t.wir rep) %check-order (check-order:event t.wir rep) + %certificate (certificate:event t.wir rep) %get-authz (get-authz:event t.wir rep) :: XX check/finalize-authz ?? %test-trial (test-trial:event t.wir rep) From 2acd46a7016ddb7935484f5204cdd2070c56b750 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sat, 23 Jun 2018 00:11:22 -0400 Subject: [PATCH 58/95] refactors +sigh-httr --- app/acme.hoon | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 46e0d2ab3..7f59f468e 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1438,7 +1438,7 @@ :: +directory: accept ACME service directory, trigger registration :: ++ directory - |= rep=httr + |= [wir=wire rep=httr] ^+ this ?. =(200 p.rep) :: XX never happened yet, wat do? @@ -1696,20 +1696,21 @@ =? nonces ?=(^ nonhed) [q.i.nonhed nonces] =< abet ~| [%sigh-fail wir rep] + %. [t.wir rep] ?+ i.t.wir ~&([%unknown-wire i.t.wir] !!) - %directory (directory:event rep) - %nonce (nonce:event t.wir rep) - %register (register:event t.wir rep) + %directory directory:event + %nonce nonce:event + %register register:event :: XX rekey - %new-order (new-order:event t.wir rep) - %finalize-order (finalize-order:event t.wir rep) - %check-order (check-order:event t.wir rep) - %certificate (certificate:event t.wir rep) - %get-authz (get-authz:event t.wir rep) + %new-order new-order:event + %finalize-order finalize-order:event + %check-order check-order:event + %certificate certificate:event + %get-authz get-authz:event :: XX check/finalize-authz ?? - %test-trial (test-trial:event t.wir rep) - %finalize-trial (finalize-trial:event t.wir rep) + %test-trial test-trial:event + %finalize-trial finalize-trial:event :: XX delete-trial? == :: From dcf947712f31641d10550633a3b7a2b21e62ebb2 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sat, 23 Jun 2018 22:31:20 -0400 Subject: [PATCH 59/95] support already-completed domain validation challenges --- app/acme.hoon | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 7f59f468e..e5940ede3 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1660,9 +1660,9 @@ =* aut u.active.aut.u.rod =/ bod=[typ=@t sas=@t url=purl tok=@t] (challenge:grab (need (de-json:html q:(need r.rep)))) - :: XX what if it's not? - ?> ?=(%pending sas.bod) - ~! aut + :: XX check for other possible values in 200 response + :: note: may have already been validated + ?> ?=(?(%pending %valid) sas.bod) =/ rod-aut=order-auth aut.u.rod(active ~, done [+.aut(sas.cal %pend) done.aut.u.rod]) ?~ pending.aut.u.rod From 92d27238c1d6fc88af4db5754d23704487f6a78b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sat, 23 Jun 2018 23:27:43 -0400 Subject: [PATCH 60/95] archives active order in +add-order --- app/acme.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/acme.hoon b/app/acme.hoon index e5940ede3..0ca76507a 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1775,7 +1775,7 @@ :: XX or re-use order-id? =? fal.hit ?=(^ rod) [u.rod fal.hit] :: XX check registration, defer - new-order:effect(pen `(sy dom)) + new-order:effect(rod ~, pen `(sy dom)) :: ++ test =, tester:tester From 90efc6daf033f66f1a63e73c0b6cc87430bb31be Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sat, 23 Jun 2018 23:56:27 -0400 Subject: [PATCH 61/95] adds mechanism to print account key --- app/acme.hoon | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/acme.hoon b/app/acme.hoon index 0ca76507a..35862b0b0 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1720,6 +1720,9 @@ =< abet ?+ a ~&(+<+.this this) + %dbug ~& [%private (ring:en:pem:pkcs1 key.act)] + ~& [%public (pass:en:pem:pkcs1 key.act)] + this %init init %reg register:effect %order new-order:effect From c2ccfed00f0c593ea5323a210883292c617265b8 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sun, 24 Jun 2018 00:45:20 -0400 Subject: [PATCH 62/95] adds reproduction for invalid jws signature --- app/acme.hoon | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/app/acme.hoon b/app/acme.hoon index 35862b0b0..7e6b0705b 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1797,6 +1797,7 @@ test-rs256 test-jwk test-jws + test-jws-fail test-csr == ?~(out this ((slog out) this)) @@ -2322,6 +2323,88 @@ :- exp-ws (en-base64url (swp 3 (~(sign rs256 k) inp-ws))) == + :: XX this test should fail, but doesn't. + :: XX fix the bug and make it fail. + :: + :: urn:ietf:params:acme:error:malformed + :: JWS verification error + :: + ++ test-jws-fail + =/ kpem=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MIIEogIBAAKCAQEAkmWLu+9gyzCbrGAHTFE6Hs7CtVQofONmpnhmE7JQkmdS+aph' + 'WwZQfp9p6RU6vSoBaPXD96uqMXhvoOXz9/Ub5TRwLmQzfHZdksfU3pEZ8qFMikZU' + 'p5v+CyBnLq9YR0VXN+/JVatmYb1hhC1k101X9m+IU3DR3U+kyCZnXuOd10xVX05H' + '0pXl+nI25bZyMJFnz1Xfw1rTnhtU/w7bgCWYdMii5jLkl5zfoY2gulpPu7QeYa4K' + '3fTqklDNFK7kQQ1l4O3461fbSO0cnG4t8Vk3026ageA54+Qx8O8UDi8k18Z1NF+B' + 'pbPUZn55/InuZ8iGyHBZ4GRFIPG0iOdWM7gHCwIDAQABAoIBAAMQN/9SS6MJMULq' + 'CsXHxyl5sHtXa/BgWLHP+j2/FtRX++EkR0s+ln2FobZa+l5Q9m4Ljn5PbqSMAFfM' + 'Y6u0hNyj9om04oOl8bILl4Vcvqgp51oFvAEGOW15/o69+6bS3aBx7cqwfnsivInr' + 'nIXDvHcyey3kh9WCKNx3rxNVgfuTCkw0+K2qXkMTh2c3Iz2efR2f78qbNWQcBe1+' + 's83fABafxACYuXzfOYoO01GBCJnHrmXxJVePLXwxLkLeJHOQJQgPnagVbUH4kbUp' + 'OLd9h1dOVYKpyVaxbQiAH3U/ekOXCCv18a47/PQSbueolzSzMzwVPSZdf+88lzuq' + 'ZZyDXDECgYEAk5zt4cO7X+8IIeNXx8/2pztT9WmC1kqw4RtInoVXm62K1B0pPndW' + 'm0nMVFEDuSwdn61G5amlaOT0dTFHlMFydC9H+1L5PMK7d+6ArSeAtMWoUhz+jkcO' + 'B9KoMfZ9CtP2r5589zDGir8kaY8Fia5Z7TohpJDidmuumgDabl+qH+kCgYEA/eP6' + 'lIGVHF8EIrfewjLM+8i1RE/hzItOpegrwDUVeYfZlPM59xUyC9REdgvmnTssxPcL' + '2+EB11wvcImSPLuwN0kXUkh9qZUkr9hvYlikALNH1f8WhCJ0kT6pUeA7LbjU4/bM' + 'fsgcOh1POW2piIMERl1TuNRZg7JdKuCJKax3qtMCgYB2dxcifOc/0qIAMGgeX/Rf' + 'ueljp03tlPvnbPIW5oSs19X27YBQNY44Cj4F3Q7T6WfM4k9nuYKacEUQWIBODgJA' + '5EEsniaQcOfrFGoIjQ9qBMdVPxe8L6I+/P0nO96Wdg4gW12HNIniiAw8+x9Co75f' + '+KtPW0ekKj9yMQUcV4I9IQKBgE06bruDmzbRFDH3WjQaPc4M5E6OOfH9IgRHVh+W' + 'Rhz8nMu5HJWzBdEhVV3PCuwi1uBnAV112RiIOwnxXuFIejam7ggics8Fxe4TWPZC' + 'Xki0QBKxEElLLcgMlnaITZf/1AovxU5/Uk6/IZ0nZV1X9RHuS4w6U6xCsiJbwH1D' + 'r/bvAoGAV/Vx+Z2BD7QhmHofu98OMW6EGSjWMgOI4iXdcQ80Urz9akHkOM4KGojq' + 'UDobbxxkJt1K5Dzux+vnp1siiIkcLdVdtMzqo7KcKYWonMqZmppNqIFCXQHscCRD' + 'r6f1TIjlurYrazLAkRsmjE5uYM13/E1UdxplWSkdCbivIWqoqTM=' + '-----END RSA PRIVATE KEY-----' + == + =/ k=key:rsa + (need (ring:de:pem:pkcs1 kpem)) + =/ kid=@t + 'https://acme-staging-v02.api.letsencrypt.org/acme/acct/6336694' + =/ non=@t + 'a5Pwh6GcuqRSvHTQouW96XNg3iiMORMkBf_wSLOf0M4' + =/ url=purl + :- [sec=%.y por=~ hot=[%.y p=/org/letsencrypt/api/acme-staging-v02]] + :_ query=~ + :- ext=~ + %+ weld + /acme/challenge + /'efJn0ywfjIi3M7yT-6H8Mdq85R2LnI8XsTG3DaaY8Gc'/'138087558' + =/ protected-header=json + :- %o %- my :~ + nonce+s+non + url+s+(crip (en-purl:html url)) + kid+s+kid + == + =/ bod=json + [%o ~] + =/ exp=json + =/ payload=@t 'e30' + =/ protected=@t + %+ rap 3 + :~ 'eyJhbGci' + 'OiJSUzI1NiIsImtpZCI6Imh0dHBzOi8vYWNtZS1zdGFnaW5nLXYwMi5hcGkubGV0c2' + 'VuY3J5cHQub3JnL2FjbWUvYWNjdC82MzM2Njk0Iiwibm9uY2UiOiJhNVB3aDZHY3Vx' + 'UlN2SFRRb3VXOTZYTmczaWlNT1JNa0JmX3dTTE9mME00IiwidXJsIjoiaHR0cHM6Ly' + '9hY21lLXN0YWdpbmctdjAyLmFwaS5sZXRzZW5jcnlwdC5vcmcvYWNtZS9jaGFsbGVu' + 'Z2UvZWZKbjB5d2ZqSWkzTTd5VC02SDhNZHE4NVIyTG5JOFhzVEczRGFhWThHYy8xMz' + 'gwODc1NTgifQ' + == + =/ signature=@t + %+ rap 3 + :~ 'ZuQgIjhNY3UbmnPwBfleJRrmc2CCrwQ2eKkw1594_MaBwGZdSg6' + 'UaDljoJ9SKXpd_2-glsQuZG1YgpFzZIk66rip6D80Xu0ZJg9AR8KEqLSMHavONj4CR' + 'c6USw9Ov3LnfQgvt9W5xb8rc2NNl-ESCNRKkOBmwhNNM1kiOY1AbQa8Ko0uNFHSn3a' + 'Rm_PLGlaTcP-k8j6ZlyOBCp3CuyxBJ68I92cWH3aSEHf4mYQo6IE0qqhk6Dv1Cyayt' + '7Ds8ocmhvESxo-iiiecBTkEaw_YCYJle_Re6F2hyyEnLVULowMJdyrYvb2YXjjj9d9' + '9m3SSTy_L3kTohpktQxRSwWlmcg' + == + [%o (my payload+s+payload protected+s+protected signature+s+signature ~)] + %- expect-eq !> + :- exp + (sign:jws k protected-header bod) :: ++ test-csr =/ kpem=wain From 546053fb7c8dcc81762c73abc93a7552f0152a7c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 25 Jun 2018 14:07:48 -0400 Subject: [PATCH 63/95] adds failing test case for invalid JWS --- app/acme.hoon | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 7e6b0705b..99b36adef 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1797,7 +1797,7 @@ test-rs256 test-jwk test-jws - test-jws-fail + test-jws-2 test-csr == ?~(out this ((slog out) this)) @@ -2323,13 +2323,11 @@ :- exp-ws (en-base64url (swp 3 (~(sign rs256 k) inp-ws))) == - :: XX this test should fail, but doesn't. - :: XX fix the bug and make it fail. :: - :: urn:ietf:params:acme:error:malformed - :: JWS verification error - :: - ++ test-jws-fail + ++ test-jws-2 + :: captured from an in-the-wild failure + :: relevant sha-256 has a significant leading zero + :: which was not being captured in the asn.1 digest ... =/ kpem=wain :~ '-----BEGIN RSA PRIVATE KEY-----' 'MIIEogIBAAKCAQEAkmWLu+9gyzCbrGAHTFE6Hs7CtVQofONmpnhmE7JQkmdS+aph' @@ -2394,12 +2392,12 @@ == =/ signature=@t %+ rap 3 - :~ 'ZuQgIjhNY3UbmnPwBfleJRrmc2CCrwQ2eKkw1594_MaBwGZdSg6' - 'UaDljoJ9SKXpd_2-glsQuZG1YgpFzZIk66rip6D80Xu0ZJg9AR8KEqLSMHavONj4CR' - 'c6USw9Ov3LnfQgvt9W5xb8rc2NNl-ESCNRKkOBmwhNNM1kiOY1AbQa8Ko0uNFHSn3a' - 'Rm_PLGlaTcP-k8j6ZlyOBCp3CuyxBJ68I92cWH3aSEHf4mYQo6IE0qqhk6Dv1Cyayt' - '7Ds8ocmhvESxo-iiiecBTkEaw_YCYJle_Re6F2hyyEnLVULowMJdyrYvb2YXjjj9d9' - '9m3SSTy_L3kTohpktQxRSwWlmcg' + :~ 'cukOS_KIWTolvORyJoIu5eejdLoFi6xpd06Y6nW565zFMKZi44BepsWIZXw4yxYjxs' + '8xFdoKOxtXhBS5BT0mbkHSUGokAPTUiF5b1wjm00ZiKRYwnIotizsLPzHAJKwhMlFs' + 'x6oAu25mmremBgnNtVD_cskQBbkTBgiTL6alrkrmwxlP2gSqyX6uEO-UCY71QB_xYj' + '4IOoX2k0jdXJevXDAJSUWfs5cZkm8Ug_q4GVTRWhZmFHMnMzonmCC4Ui7nDa9oKJH5' + 'Npyn74FCcqbz111AK-Aul1dNhz3ojE1VOk3eVjH69lSGsaMleYR5fi60Jdc5ZbpPPy' + 't-CZRp1F0k6w' == [%o (my payload+s+payload protected+s+protected signature+s+signature ~)] %- expect-eq !> From 84452a6e0020218036d69fdb532d77703d441ca3 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 25 Jun 2018 14:08:15 -0400 Subject: [PATCH 64/95] updates ASN.1 %oct to explicitly track byte-length --- app/acme.hoon | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 99b36adef..6fd3e1588 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -108,7 +108,7 @@ [%bit bit=@ux] :: %oct: octets in little-endian byte order :: - [%oct oct=@ux] + [%oct len=@ud oct=@ux] :: %nul: fully supported! :: [%nul ~] @@ -204,7 +204,13 @@ :: presumed to be already padded to a byte boundary :: [%bit *] [0 (rip 3 bit.pec)] - [%oct *] (rip 3 oct.pec) + :: padded to byte-width + :: + [%oct *] =/ a (rip 3 oct.pec) + =/ b ~| %der-invalid-oct + (sub len.pec (lent a)) + (weld a (reap b 0)) + :: [%nul *] ~ [%obj *] (rip 3 obj.pec) :: @@ -248,7 +254,7 @@ ;~ pose (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) (stag %bit (boss 256 (cook tail ;~(pfix (tag 3) till)))) :: XX test - (stag %oct (boss 256 ;~(pfix (tag 4) till))) + (stag %oct (cook oct ;~(pfix (tag 4) till))) (stag %nul (cold ~ ;~(plug (tag 5) (tag 0)))) (stag %obj (boss 256 ;~(pfix (tag 6) till))) (stag %seq (sear recur ;~(pfix (tag 48) till))) @@ -268,6 +274,13 @@ ?: ?=([@ ~] a) `a ?. =(0 i.a) `a ?.((gth i.t.a 127) ~ `t.a) + :: +oct:de:der: cook bytes to capture length + :: + ++ oct + |= a=(list @D) + ^- [len=@ud oct=@ux] + :: XX do this in a parser combinator instead + [(lent a) (scan a (boss 256 (star next)))] :: +recur:de:der: parse bytes for a list of +spec:asn1 :: ++ recur @@ -386,7 +399,7 @@ =/ pec=spec:asn1 :~ %seq [%seq [%obj sha-256:obj:asn1] [%nul ~] ~] - [%oct (shax m)] + [%oct 32 (shax m)] == =/ t=(list @) ~(ren raw:en:der pec) =/ tlen (lent t) @@ -680,7 +693,10 @@ :~ %seq :~ %seq [%obj sub-alt:obj:asn1] - [%oct (en:^der (san hot))] + :: XX revisit, make +der output +octs + :: [%oct (en:^der (san hot))] + =/ nas=(list @D) ~(ren raw:en:^der (san hot)) + [%oct (lent nas) (rep 3 nas)] == == == == == :: +san:en:spec:pkcs10: subject-alternate-names :: @@ -1824,7 +1840,7 @@ =/ nul=spec:asn1 [%nul ~] =/ int=spec:asn1 [%int 187] =/ obj=spec:asn1 [%obj sha-256:obj:asn1] - =/ oct=spec:asn1 [%oct (shax 'hello\0a')] + =/ oct=spec:asn1 [%oct 32 (shax 'hello\0a')] =/ seq=spec:asn1 [%seq [%seq obj nul ~] oct ~] ;: weld %- expect-eq !> From b5f352f3bc8b2f629657afd72b71e575eee7d05a Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 25 Jun 2018 21:29:34 -0400 Subject: [PATCH 65/95] refactors +der %oct parser --- app/acme.hoon | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 6fd3e1588..71b24c494 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -253,10 +253,10 @@ :: ^- $-(nail (like spec:asn1)) ;~ pose (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) - (stag %bit (boss 256 (cook tail ;~(pfix (tag 3) till)))) :: XX test - (stag %oct (cook oct ;~(pfix (tag 4) till))) + (stag %bit (^boss 256 (cook tail ;~(pfix (tag 3) till)))) :: XX test + (stag %oct (boss 256 ;~(pfix (tag 4) till))) (stag %nul (cold ~ ;~(plug (tag 5) (tag 0)))) - (stag %obj (boss 256 ;~(pfix (tag 6) till))) + (stag %obj (^boss 256 ;~(pfix (tag 6) till))) (stag %seq (sear recur ;~(pfix (tag 48) till))) (stag %set (sear recur ;~(pfix (tag 49) till))) (stag %con ;~(plug (sear context next) till)) @@ -274,13 +274,6 @@ ?: ?=([@ ~] a) `a ?. =(0 i.a) `a ?.((gth i.t.a 127) ~ `t.a) - :: +oct:de:der: cook bytes to capture length - :: - ++ oct - |= a=(list @D) - ^- [len=@ud oct=@ux] - :: XX do this in a parser combinator instead - [(lent a) (scan a (boss 256 (star next)))] :: +recur:de:der: parse bytes for a list of +spec:asn1 :: ++ recur @@ -294,6 +287,17 @@ :+ ~ =(1 (cut 0 [5 1] a)) (dis 0x1f a) + :: +boss:de:der: shadowed to count as well + :: + :: Use for parsing +octs more broadly? + :: + ++ boss + |* [wuc=@ tyd=rule] + %+ cook + |= waq=(list @) + :- (lent waq) + (reel waq |=([p=@ q=@] (add p (mul wuc q)))) + tyd :: +till:de:der: parser combinator for len-prefixed bytes :: :: advance until From 3238cf6ce671992aabc827e63b8b4e6db2b89134 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 01:10:19 -0400 Subject: [PATCH 66/95] updates +der encoding to produce +octs, base-64 encoding to accept octs --- app/acme.hoon | 130 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 51 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 71b24c494..cd9d270e0 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -4,6 +4,18 @@ :::: %zuse additions :: |% +:: +rev: reverses block order, accounting for leading zeroes +:: +:: XX deduplicate with Mark's eth stuff +:: +++ rev + :: boq: block size + :: len: size of dat, in boq + :: dat: data to reverse + :: + |= [boq=bloq len=@ud dat=@] + =+ (swp boq dat) + (lsh boq (sub len (met boq dat)) -) :: |base64: flexible base64 encoding for little-endian atoms :: ++ base64 @@ -12,13 +24,17 @@ :: =+ [pad=& url=|] |% - :: +en:base64: encode atom to base64 cord + :: +en:base64: encode +octs to base64 cord :: ++ en - |= tig=@ + |= inp=octs ^- cord - =/ poc (~(dif fo 3) 0 (met 3 tig)) - =/ pad (lsh 3 poc (swp 3 tig)) + :: dif: offset from 3-byte block + :: + =/ dif=@ud (~(dif fo 3) 0 p.inp) + :: dap: reversed, 3-byte block-aligned input + :: + =/ dap=@ux (lsh 3 dif (rev 3 inp)) =/ cha ?: url 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' @@ -26,16 +42,16 @@ %- crip %- flop %+ weld - ?.(^pad ~ (reap poc '=')) - %+ slag poc + ?.(pad ~ (reap dif '=')) + %+ slag dif |- ^- tape - ?~ pad ~ - =/ d (end 3 3 pad) + ?: =(0x0 dap) ~ + =/ d (end 3 3 dap) :* (cut 3 [(cut 0 [0 6] d) 1] cha) (cut 3 [(cut 0 [6 6] d) 1] cha) (cut 3 [(cut 0 [12 6] d) 1] cha) (cut 3 [(cut 0 [18 6] d) 1] cha) - $(pad (rsh 3 3 pad)) + $(dap (rsh 3 3 dap)) == :: +de:base64: decode base64 cord to (unit @) :: @@ -70,6 +86,13 @@ :: ++ de-base64url ~(de base64 | &) +:: |octn: encode/decode unsigned atoms as big-endian octet stream +:: +++ octn + |% + ++ en |=(a=@u `octs`[(met 3 a) (swp 3 a)]) + ++ de |=(a=octs `@u`(rev 3 p.a q.a)) + -- :: :::: %/lib/pkcs :: @@ -156,10 +179,13 @@ :: ++ der |% - :: +en:der: encode +spec:asn1 to atom + :: +en:der: encode +spec:asn1 to +octs (kindof) :: ++ en - =< |=(a=spec:asn1 `@ux`(rep 3 ~(ren raw a))) + =< |= a=spec:asn1 + ^- [len=@ud dat=@ux] + =/ b ~(ren raw a) + [(lent b) (rep 3 b)] |% :: +raw:en:der: door for encoding +spec:asn1 to list of bytes :: @@ -244,7 +270,7 @@ :: +de:der: decode atom to +spec:asn1 :: ++ de - =< |=(a=@ `(unit spec:asn1)`(rush a parse)) + =< |=([len=@ud dat=@ux] `(unit spec:asn1)`(rush dat parse)) |% :: +parse:de:der: DER parser combinator :: @@ -437,11 +463,11 @@ :: +en:pem: PEM encode :: ++ en - |= [lab=@t der=@ux] + |= [lab=@t len=@ud der=@ux] ^- wain :: XX validate label? :- (rap 3 ['-----BEGIN ' lab '-----' ~]) - =/ a (en:base64 der) + =/ a (en:base64 len `@`der) |- ^- wain ?~ a [(rap 3 ['-----END ' lab '-----' ~]) ~] @@ -450,12 +476,13 @@ :: ++ de |= [lab=@t mep=wain] - ^- (unit @ux) + ^- (unit [len=@ud der=@ux]) =/ a (sub (lent mep) 2) ?~ mep ~ :: XX validate label? ?. =((rap 3 ['-----BEGIN ' lab '-----' ~]) i.mep) ~ ?. =((rap 3 ['-----END ' lab '-----' ~]) (snag a t.mep)) ~ + =- ?~(- ~ `[(met 3 u.-) u.-]) (de:base64 (rap 3 (scag a t.mep))) -- :: |pkcs1: RSA asymmetric cryptography (rfc3447) @@ -541,13 +568,13 @@ |% ++ en |% - ++ pass |=(k=key:rsa `@ux`(en:^der (pass:en:spec k))) - ++ ring |=(k=key:rsa `@ux`(en:^der (ring:en:spec k))) + ++ pass |=(k=key:rsa (en:^der (pass:en:spec k))) + ++ ring |=(k=key:rsa (en:^der (ring:en:spec k))) -- ++ de |% - ++ pass |=(a=@ `(unit key:rsa)`(biff (de:^der a) pass:de:spec)) - ++ ring |=(a=@ `(unit key:rsa)`(biff (de:^der a) ring:de:spec)) + ++ pass |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) pass:de:spec)) + ++ ring |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) ring:de:spec)) -- -- :: |pem:pkcs1: PEM encoding for RSA keys @@ -587,7 +614,7 @@ ^- spec:asn1 :~ %seq [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] - [%bit (pass:en:der:pkcs1 k)] + [%bit +:(pass:en:der:pkcs1 k)] == :: +ring:spec:pkcs8: private key ASN.1 :: @@ -608,7 +635,7 @@ =(rsa:obj:asn1 obj.i.seq.i.seq.a) == ~ - (pass:de:der:pkcs1 bit.i.t.seq.a) + (pass:de:der:pkcs1 (met 3 bit.i.t.seq.a) bit.i.t.seq.a) :: +ring:de:spec:pkcs8: :: ++ ring !! @@ -623,12 +650,12 @@ |% ++ en |% - ++ pass |=(k=key:rsa `@ux`(en:^der (pass:en:spec k))) + ++ pass |=(k=key:rsa `[len=@ud dat=@ux]`(en:^der (pass:en:spec k))) ++ ring !! ::|=(k=key:rsa `@ux`(en:^der (ring:spec k))) -- ++ de |% - ++ pass |=(a=@ `(unit key:rsa)`(biff (de:^der a) pass:de:spec)) + ++ pass |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) pass:de:spec)) ++ ring !! ::|=(a=@ `(unit key:rsa)`(biff (de:^der a) ring:de:spec)) -- -- @@ -676,7 +703,8 @@ dat [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] :: big-endian signature bytes - [%bit (swp 3 (~(sign rs256 key) (en:^der dat)))] + :: XX revisit %bit + [%bit (swp 3 (~(sign rs256 key) +:(en:^der dat)))] == :: +info:en:spec:pkcs10: certificate request info :: @@ -697,10 +725,7 @@ :~ %seq :~ %seq [%obj sub-alt:obj:asn1] - :: XX revisit, make +der output +octs - :: [%oct (en:^der (san hot))] - =/ nas=(list @D) ~(ren raw:en:^der (san hot)) - [%oct (lent nas) (rep 3 nas)] + [%oct (en:^der (san hot))] == == == == == :: +san:en:spec:pkcs10: subject-alternate-names :: @@ -720,7 +745,7 @@ :: ++ der |% - ++ en |=(a=csr `@ux`(en:^der (en:spec a))) + ++ en |=(a=csr `[len=@ud der=@ux]`(en:^der (en:spec a))) ++ de !! ::|=(a=@ `(unit csr)`(biff (de:^der a) de:spec)) -- :: |pem:pkcs10: PEM encoding for certificate signing requests @@ -802,8 +827,8 @@ ^- json :- %o %- my :~ kty+s+'RSA' - n+s+(en-base64url (swp 3 n.pub.k)) - e+s+(en-base64url (swp 3 e.pub.k)) + n+s+(en-base64url (en:octn n.pub.k)) + e+s+(en-base64url (en:octn e.pub.k)) == :: +ring:en:jwk: json encode private key :: @@ -814,11 +839,11 @@ ?> ?=(^ sek.k) :- %o %- my :~ kty+s+'RSA' - n+s+(en-base64url (swp 3 n.pub.k)) - e+s+(en-base64url (swp 3 e.pub.k)) - d+s+(en-base64url (swp 3 d.u.sek.k)) - p+s+(en-base64url (swp 3 p.u.sek.k)) - q+s+(en-base64url (swp 3 q.u.sek.k)) + n+s+(en-base64url (en:octn n.pub.k)) + e+s+(en-base64url (en:octn e.pub.k)) + d+s+(en-base64url (en:octn d.u.sek.k)) + p+s+(en-base64url (en:octn p.u.sek.k)) + q+s+(en-base64url (en:octn q.u.sek.k)) == -- :: |de:jwk: decoding of json cryptographic keys @@ -874,7 +899,7 @@ :: ++ pass |= k=key:rsa - (en-base64url (shax (crip (en-json-sort aor (pass:en k))))) + (en-base64url 32 (shax (crip (en-json-sort aor (pass:en k))))) :: +ring:thumb:jwk: thumbprint json-encoded private key :: ++ ring !! @@ -912,15 +937,18 @@ :: ++ encode |= jon=json - (en-base64url (crip (en-json-sort aor jon))) + %- en-base64url + %- as-octt:mimes:html + (en-json-sort aor jon) :: +sign:sign:jws: compute signature :: :: Url-safe base64 encode in big-endian byte order. :: ++ sign |= [protect=cord payload=cord] - %- en-base64url - (swp 3 (~(sign rs256 k) (rap 3 ~[protect '.' payload]))) + =/ sig=@ud (~(sign rs256 k) (rap 3 ~[protect '.' payload])) + =/ len=@ud (met 3 n.pub.k) + (en-base64url len (rev 3 len sig)) -- :: +verify:jws: verify signature :: @@ -1350,7 +1378,7 @@ %+ request /acme/finalize-order/(scot %da now.bow) %^ signed-request fin.u.rod i.nonces - [%o (my csr+s+(en-base64url csr.u.rod) ~)] + [%o (my csr+s+(en-base64url (met 3 csr.u.rod) `@`csr.u.rod) ~)] :: +check-order: check completed order for certificate availability :: ++ check-order @@ -1536,7 +1564,7 @@ =/ bod=[aut=(list purl) fin=purl exp=@t sas=@t] (order:grab (need (de-json:html q:(need r.rep)))) :: XX maybe generate key here? - =/ csr=@ux (en:der:pkcs10 cey ~(tap in u.pen)) + =/ csr=@ux +:(en:der:pkcs10 cey ~(tap in u.pen)) =/ dor=order [dom=u.pen sas=%wake exp.bod ego fin.bod cey csr [aut.bod ~ ~]] get-authz:effect(rod `dor, pen ~) @@ -1825,17 +1853,17 @@ ++ test-base64 ;: weld %- expect-eq !> - ['AQAB' (en-base64url 65.537)] + ['AQAB' (en-base64url (en:octn 65.537))] %- expect-eq !> [65.537 (need (de-base64url 'AQAB'))] :: echo "hello" | base64 %- expect-eq !> - ['aGVsbG8K' (en:base64 'hello\0a')] + ['aGVsbG8K' (en:base64 (as-octs:mimes:html 'hello\0a'))] %- expect-eq !> ['hello\0a' (need (de:base64 'aGVsbG8K'))] :: echo -n -e "\x01\x01\x02\x03" | base64 %- expect-eq !> - ['AQECAw==' (en:base64 (swp 3 0x101.0203))] + ['AQECAw==' (en:base64 (en:octn 0x101.0203))] %- expect-eq !> [0x302.0101 (need (de:base64 'AQECAw=='))] == @@ -1865,13 +1893,13 @@ %- expect-eq !> :- 0x420.5891.b5b5.22d5.df08.6d0f.f0b1.10fb. d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 - `@ux`(swp 3 (en:der oct)) + `@ux`(swp 3 +:(en:der oct)) %- expect-eq !> [oct (scan ~(ren raw:en:der oct) parse:de:der)] %- expect-eq !> :- 0x30.3130.0d06.0960.8648.0165.0304.0201.0500.0420.5891.b5b5.22d5. df08.6d0f.f0b1.10fb.d9d2.1bb4.fc71.63af.34d0.8286.a2e8.46f6.be03 - `@ux`(swp 3 (en:der seq)) + `@ux`(swp 3 +:(en:der seq)) %- expect-eq !> [seq (scan ~(ren raw:en:der seq) parse:de:der)] == @@ -2222,7 +2250,7 @@ :: save kpem2 to private.pem :: echo "hello" | openssl dgst -sha256 -sign private.pem | base64 %- expect-eq !> - [exp2b64 (en:base64 (swp 3 sig))] + [exp2b64 (en:base64 (met 3 sig) (swp 3 sig))] == :: ++ test-jwk @@ -2335,13 +2363,13 @@ `@ux`(~(inv fo (elcm:rsa (dec p.u.sek.k) (dec q.u.sek.k))) e.pub.k) %- expect-eq !> :- hedt - (en-base64url (crip (en-json-sort aor hed))) + (en-base64url (as-octt:mimes:html (en-json-sort aor hed))) %- expect-eq !> :- lodt - (en-base64url (crip (en-json-sort (eor lte lod-order) lod))) + (en-base64url (as-octt:mimes:html (en-json-sort (eor lte lod-order) lod))) %- expect-eq !> :- exp-ws - (en-base64url (swp 3 (~(sign rs256 k) inp-ws))) + (en-base64url (en:octn (~(sign rs256 k) inp-ws))) == :: ++ test-jws-2 From 67590f70c7d673129376e5f05a0ae84d921981a6 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 03:21:32 -0400 Subject: [PATCH 67/95] updates +de:base64 to output +octs --- app/acme.hoon | 69 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index cd9d270e0..2066d83c7 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -57,26 +57,43 @@ :: ++ de |= a=cord - ^- (unit @) - %+ rush a - :: XX refactor and expose parser combinator - %+ cook (cury swp 3) - %+ bass 64 - %+ cook welp + ^- (unit octs) + (rush a parse) + :: +parse:base64: parse base64 cord to +octs + :: + ++ parse + %+ sear reduce ;~ plug - %- plus - ;~ pose + %- plus ;~ pose (cook |=(a=@ (sub a 'A')) (shim 'A' 'Z')) (cook |=(a=@ (sub a 'G')) (shim 'a' 'z')) (cook |=(a=@ (add a 4)) (shim '0' '9')) (cold 62 (just ?:(url '-' '+'))) (cold 63 (just ?:(url '_' '/'))) == - ?: pad - (stun 0^2 (cold %0 tis)) - =/ b (~(dif fo 4) 0 (met 3 a)) - (cold (reap b %0) (easy ~)) + (stun 0^2 (cold %0 tis)) == + :: +reduce: reduce, measure, and swap base64 digits + :: + ++ reduce + |= [dat=(list @) dap=(list @)] + ^- (unit [len=@ud dat=@]) + =/ lat (lent dat) + =/ lap (lent dap) + =/ dif (~(dif fo 4) 0 lat) + ?: &(pad !=(dif lap)) + :: padding required and incorrect + ~&(%base-64-padding-err-one ~) + ?: &(!pad !=(0 lap)) + :: padding not required but present + ~&(%base-64-padding-err-two ~) + =/ len (sub (mul 3 (div (add lat dif) 4)) dif) + :+ ~ len + %+ swp 3 + :: %+ base 64 + %+ roll + (weld dat (reap dif 0)) + |=([p=@ q=@] (add p (mul 64 q))) -- :: +en-base64url: url-safe base64 encoding, without padding :: @@ -482,7 +499,7 @@ :: XX validate label? ?. =((rap 3 ['-----BEGIN ' lab '-----' ~]) i.mep) ~ ?. =((rap 3 ['-----END ' lab '-----' ~]) (snag a t.mep)) ~ - =- ?~(- ~ `[(met 3 u.-) u.-]) + ^- (unit [@ @]) (de:base64 (rap 3 (scag a t.mep))) -- :: |pkcs1: RSA asymmetric cryptography (rfc3447) @@ -855,10 +872,9 @@ ++ pass =, dejs-soft:format %+ ci - |= [kty=@t n=(unit @) e=(unit @)] + |= [kty=@t n=(unit octs) e=(unit octs)] ^- (unit key:rsa) - =/ swp (cury swp 3) - =/ pub (both (bind n swp) (bind e swp)) + =/ pub (both (bind n de:octn) (bind e de:octn)) ?~(pub ~ `[u.pub ~]) %- ot :~ kty+(su (jest 'RSA')) @@ -871,16 +887,15 @@ =, dejs-soft:format %+ ci |= $: kty=@t - n=(unit @) - e=(unit @) - d=(unit @) - p=(unit @) - q=(unit @) + n=(unit octs) + e=(unit octs) + d=(unit octs) + p=(unit octs) + q=(unit octs) == ^- (unit key:rsa) - =/ swp (cury swp 3) - =/ pub (both (bind n swp) (bind e swp)) - =/ sek :(both (bind d swp) (bind p swp) (bind q swp)) + =/ pub (both (bind n de:octn) (bind e de:octn)) + =/ sek :(both (bind d de:octn) (bind p de:octn) (bind q de:octn)) ?:(|(?=(~ pub) ?=(~ sek)) ~ `[u.pub sek]) %- ot :~ kty+(su (jest 'RSA')) @@ -1855,17 +1870,17 @@ %- expect-eq !> ['AQAB' (en-base64url (en:octn 65.537))] %- expect-eq !> - [65.537 (need (de-base64url 'AQAB'))] + [65.537 (de:octn (need (de-base64url 'AQAB')))] :: echo "hello" | base64 %- expect-eq !> ['aGVsbG8K' (en:base64 (as-octs:mimes:html 'hello\0a'))] %- expect-eq !> - ['hello\0a' (need (de:base64 'aGVsbG8K'))] + ['hello\0a' +:(need (de:base64 'aGVsbG8K'))] :: echo -n -e "\x01\x01\x02\x03" | base64 %- expect-eq !> ['AQECAw==' (en:base64 (en:octn 0x101.0203))] %- expect-eq !> - [0x302.0101 (need (de:base64 'AQECAw=='))] + [0x302.0101 +:(need (de:base64 'AQECAw=='))] == :: ++ test-asn1 From a9871af7fb8e939fd570cb0c87b8446762a6fa49 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 03:32:45 -0400 Subject: [PATCH 68/95] always parse :len bytes in +de:der --- app/acme.hoon | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/acme.hoon b/app/acme.hoon index 2066d83c7..fc37cb51d 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -287,7 +287,13 @@ :: +de:der: decode atom to +spec:asn1 :: ++ de - =< |=([len=@ud dat=@ux] `(unit spec:asn1)`(rush dat parse)) + =< |= [len=@ud dat=@ux] + ^- (unit spec:asn1) + :: XX refactor into +parse + =/ a (rip 3 dat) + =/ b ~| %der-invalid-len + (sub len (lent a)) + (rust `(list @D)`(weld a (reap b 0)) parse) |% :: +parse:de:der: DER parser combinator :: From fffff33dfcdecf0eb9eb4fef4126ecb8d1cb20bf Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 10:49:03 -0400 Subject: [PATCH 69/95] refactors +parse:base64 --- app/acme.hoon | 67 +++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index fc37cb51d..cdfb7ab35 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -62,38 +62,41 @@ :: +parse:base64: parse base64 cord to +octs :: ++ parse - %+ sear reduce - ;~ plug - %- plus ;~ pose - (cook |=(a=@ (sub a 'A')) (shim 'A' 'Z')) - (cook |=(a=@ (sub a 'G')) (shim 'a' 'z')) - (cook |=(a=@ (add a 4)) (shim '0' '9')) - (cold 62 (just ?:(url '-' '+'))) - (cold 63 (just ?:(url '_' '/'))) - == - (stun 0^2 (cold %0 tis)) - == - :: +reduce: reduce, measure, and swap base64 digits - :: - ++ reduce - |= [dat=(list @) dap=(list @)] - ^- (unit [len=@ud dat=@]) - =/ lat (lent dat) - =/ lap (lent dap) - =/ dif (~(dif fo 4) 0 lat) - ?: &(pad !=(dif lap)) - :: padding required and incorrect - ~&(%base-64-padding-err-one ~) - ?: &(!pad !=(0 lap)) - :: padding not required but present - ~&(%base-64-padding-err-two ~) - =/ len (sub (mul 3 (div (add lat dif) 4)) dif) - :+ ~ len - %+ swp 3 - :: %+ base 64 - %+ roll - (weld dat (reap dif 0)) - |=([p=@ q=@] (add p (mul 64 q))) + =< ^- $-(nail (like octs)) + %+ sear reduce + ;~ plug + %- plus ;~ pose + (cook |=(a=@ (sub a 'A')) (shim 'A' 'Z')) + (cook |=(a=@ (sub a 'G')) (shim 'a' 'z')) + (cook |=(a=@ (add a 4)) (shim '0' '9')) + (cold 62 (just ?:(url '-' '+'))) + (cold 63 (just ?:(url '_' '/'))) + == + (stun 0^2 (cold %0 tis)) + == + |% + :: +reduce:parse:base64: reduce, measure, and swap base64 digits + :: + ++ reduce + |= [dat=(list @) dap=(list @)] + ^- (unit octs) + =/ lat (lent dat) + =/ lap (lent dap) + =/ dif (~(dif fo 4) 0 lat) + ?: &(pad !=(dif lap)) + :: padding required and incorrect + ~&(%base-64-padding-err-one ~) + ?: &(!pad !=(0 lap)) + :: padding not required but present + ~&(%base-64-padding-err-two ~) + =/ len (sub (mul 3 (div (add lat dif) 4)) dif) + :+ ~ len + %+ swp 3 + :: %+ base 64 + %+ roll + (weld dat (reap dif 0)) + |=([p=@ q=@] (add p (mul 64 q))) + -- -- :: +en-base64url: url-safe base64 encoding, without padding :: From e194b15b78499b363addc284ea1bfbf9c431fa56 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 10:52:24 -0400 Subject: [PATCH 70/95] refactors +parse:der --- app/acme.hoon | 55 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index cdfb7ab35..acda0414d 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -290,34 +290,33 @@ :: +de:der: decode atom to +spec:asn1 :: ++ de - =< |= [len=@ud dat=@ux] - ^- (unit spec:asn1) - :: XX refactor into +parse - =/ a (rip 3 dat) - =/ b ~| %der-invalid-len - (sub len (lent a)) - (rust `(list @D)`(weld a (reap b 0)) parse) + |= [len=@ud dat=@ux] + ^- (unit spec:asn1) + :: XX refactor into +parse + =/ a (rip 3 dat) + =/ b ~| %der-invalid-len + (sub len (lent a)) + (rust `(list @D)`(weld a (reap b 0)) parse) + :: +parse:der: DER parser combinator + :: + ++ parse + =< ^- $-(nail (like spec:asn1)) + ;~ pose + (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) + (stag %bit (^boss 256 (cook tail ;~(pfix (tag 3) till)))) :: XX test + (stag %oct (boss 256 ;~(pfix (tag 4) till))) + (stag %nul (cold ~ ;~(plug (tag 5) (tag 0)))) + (stag %obj (^boss 256 ;~(pfix (tag 6) till))) + (stag %seq (sear recur ;~(pfix (tag 48) till))) + (stag %set (sear recur ;~(pfix (tag 49) till))) + (stag %con ;~(plug (sear context next) till)) + == |% - :: +parse:de:der: DER parser combinator - :: - ++ parse - %+ cook |*(a=* `spec:asn1`a) :: XX fix - :: ^- $-(nail (like spec:asn1)) - ;~ pose - (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) - (stag %bit (^boss 256 (cook tail ;~(pfix (tag 3) till)))) :: XX test - (stag %oct (boss 256 ;~(pfix (tag 4) till))) - (stag %nul (cold ~ ;~(plug (tag 5) (tag 0)))) - (stag %obj (^boss 256 ;~(pfix (tag 6) till))) - (stag %seq (sear recur ;~(pfix (tag 48) till))) - (stag %set (sear recur ;~(pfix (tag 49) till))) - (stag %con ;~(plug (sear context next) till)) - == - :: +tag:de:der: parse tag byte + :: +tag:parse:der: parse tag byte :: ++ tag |=(a=@D (just a)) - :: +int:de:der: sear unsigned big-endian bytes + :: +int:parse:der: sear unsigned big-endian bytes :: ++ int |= a=(list @D) @@ -326,11 +325,11 @@ ?: ?=([@ ~] a) `a ?. =(0 i.a) `a ?.((gth i.t.a 127) ~ `t.a) - :: +recur:de:der: parse bytes for a list of +spec:asn1 + :: +recur:parse:der: parse bytes for a list of +spec:asn1 :: ++ recur |=(a=(list @) (rust a (star parse))) - :: +context:de:der: decode context-specific tag byte + :: +context:parse:der: decode context-specific tag byte :: ++ context |= a=@D @@ -339,7 +338,7 @@ :+ ~ =(1 (cut 0 [5 1] a)) (dis 0x1f a) - :: +boss:de:der: shadowed to count as well + :: +boss:parse:der: shadowed to count as well :: :: Use for parsing +octs more broadly? :: @@ -350,7 +349,7 @@ :- (lent waq) (reel waq |=([p=@ q=@] (add p (mul wuc q)))) tyd - :: +till:de:der: parser combinator for len-prefixed bytes + :: +till:parse:der: parser combinator for len-prefixed bytes :: :: advance until :: From 0b4ee7702ee25566f603ccad754ab821eda3b593 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 11:24:42 -0400 Subject: [PATCH 71/95] improves rsa key generation (somewhat) --- app/acme.hoon | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index acda0414d..6c111269a 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -402,6 +402,37 @@ :: sek=(unit [d=@ux p=@ux q=@ux]) == + :: +ramp: make rabin-miller probabilistic prime + :: + :: XX replace +ramp:number? + :: a: bitwidth + :: b: snags (XX small primes to check divisibility?) + :: c: entropy + :: + ++ ramp + |= [a=@ b=(list @) c=@] + =. c (shas %ramp c) + :: XX what is this value? + :: + =| d=@ + |- ^- @ux + :: XX what is this condition? + :: + ?: =((mul 100 a) d) + ~|(%ar-ramp !!) + :: e: prime candidate + :: + :: Sets low bit, as prime must be odd. + :: Sets high bit, as +raw:og only gives up to :a bits. + :: + =/ e :(con 1 (lsh 0 (dec a) 1) (~(raw og c) a)) + :: XX what algorithm is this modular remainder check? + :: + ?: ?& (levy b |=(f/@ !=(1 (mod e f)))) + (pram:number e) + == + e + $(c +(c), d (shax d)) :: +elcm:rsa: carmichael totient :: ++ elcm @@ -414,8 +445,8 @@ |= [wid=@ eny=@] ^- key =/ diw (rsh 0 1 wid) - =/ p=@ux (ramp:number diw [3 5 ~] eny) - =/ q=@ux (ramp:number diw [3 5 ~] +(eny)) + =/ p=@ux (ramp diw [3 5 ~] eny) + =/ q=@ux (ramp diw [3 5 ~] +(eny)) =/ n=@ux (mul p q) =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) [[n e] `[d p q]] From 56db9be68784f6815a2c86739f4c90c7981e6f1e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 12:22:48 -0400 Subject: [PATCH 72/95] refactors jwk public/private key en/de-coding --- app/acme.hoon | 62 +++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 6c111269a..9622e1d16 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -875,17 +875,18 @@ :: |en:jwk: encoding of json cryptographic keys :: ++ en + => |% + :: +numb:en:jwk: base64-url encode big-endian number + :: + ++ numb (corl en-base64url en:octn) + -- |% :: +pass:en:jwk: json encode public key :: ++ pass |= k=key:rsa ^- json - :- %o %- my :~ - kty+s+'RSA' - n+s+(en-base64url (en:octn n.pub.k)) - e+s+(en-base64url (en:octn e.pub.k)) - == + [%o (my kty+s+'RSA' n+s+(numb n.pub.k) e+s+(numb e.pub.k) ~)] :: +ring:en:jwk: json encode private key :: ++ ring @@ -895,55 +896,44 @@ ?> ?=(^ sek.k) :- %o %- my :~ kty+s+'RSA' - n+s+(en-base64url (en:octn n.pub.k)) - e+s+(en-base64url (en:octn e.pub.k)) - d+s+(en-base64url (en:octn d.u.sek.k)) - p+s+(en-base64url (en:octn p.u.sek.k)) - q+s+(en-base64url (en:octn q.u.sek.k)) + n+s+(numb n.pub.k) + e+s+(numb e.pub.k) + d+s+(numb d.u.sek.k) + p+s+(numb p.u.sek.k) + q+s+(numb q.u.sek.k) == -- :: |de:jwk: decoding of json cryptographic keys :: ++ de + =, dejs-soft:format + => |% + :: +numb:de:jwk: parse base64-url big-endian number + :: + ++ numb (cu (cork de-base64url (lift de:octn)) so) + -- |% :: +pass:de:jwk: decode json public key :: ++ pass - =, dejs-soft:format %+ ci - |= [kty=@t n=(unit octs) e=(unit octs)] + =/ a (unit @ux) + |= [kty=@t n=a e=a] ^- (unit key:rsa) - =/ pub (both (bind n de:octn) (bind e de:octn)) + =/ pub (both n e) ?~(pub ~ `[u.pub ~]) - %- ot :~ - kty+(su (jest 'RSA')) - n+(cu de-base64url so) - e+(cu de-base64url so) - == + (ot kty+(su (jest 'RSA')) n+numb e+numb ~) :: +ring:de:jwk: decode json private key :: ++ ring - =, dejs-soft:format %+ ci - |= $: kty=@t - n=(unit octs) - e=(unit octs) - d=(unit octs) - p=(unit octs) - q=(unit octs) - == + =/ a (unit @ux) + |= [kty=@t n=a e=a d=a p=a q=a] ^- (unit key:rsa) - =/ pub (both (bind n de:octn) (bind e de:octn)) - =/ sek :(both (bind d de:octn) (bind p de:octn) (bind q de:octn)) + =/ pub (both n e) + =/ sek :(both d p q) ?:(|(?=(~ pub) ?=(~ sek)) ~ `[u.pub sek]) - %- ot :~ - kty+(su (jest 'RSA')) - n+(cu de-base64url so) - e+(cu de-base64url so) - d+(cu de-base64url so) - p+(cu de-base64url so) - q+(cu de-base64url so) - == + (ot kty+(su (jest 'RSA')) n+numb e+numb d+numb p+numb q+numb ~) -- :: |thumb:jwk: "thumbprint" json-encoded key (rfc7638) :: From f46e22624708ced53b364a1b8ebd0c84f119a6ad Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 14:29:42 -0400 Subject: [PATCH 73/95] updates +der %bit en/de-coding to use +octs, tests for significant trailing zeros --- app/acme.hoon | 72 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 9622e1d16..224af46fb 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -145,12 +145,15 @@ :: %bit: very minimal support for bit strings :: :: Specifically, values must already be padded and byte-aligned. - :: Note that leading zeros are significant in ASN.1 bit strings, - :: so atomic encoding would be insufficient for complete support. + :: len: bitwidth + :: bit: data :: - [%bit bit=@ux] + [%bit len=@ud bit=@ux] :: %oct: octets in little-endian byte order :: + :: len: bytewidth + :: bit: data + :: [%oct len=@ud oct=@ux] :: %nul: fully supported! :: @@ -247,9 +250,14 @@ [%int *] =/ a (flop (rip 3 int.pec)) ?~ a [0 ~] ?:((lte i.a 127) a [0 a]) - :: presumed to be already padded to a byte boundary + :: padded to byte-width, must be already byte-aligned :: - [%bit *] [0 (rip 3 bit.pec)] + [%bit *] =/ a (rip 3 bit.pec) + =/ b ~| %der-invalid-bit + ?. =(0 (mod len.pec 8)) + ~|(%der-invalid-bit-alignment !!) + (sub (div len.pec 8) (lent a)) + [0 (weld a (reap b 0))] :: padded to byte-width :: [%oct *] =/ a (rip 3 oct.pec) @@ -303,7 +311,7 @@ =< ^- $-(nail (like spec:asn1)) ;~ pose (stag %int (bass 256 (sear int ;~(pfix (tag 2) till)))) - (stag %bit (^boss 256 (cook tail ;~(pfix (tag 3) till)))) :: XX test + (stag %bit (sear bit (boss 256 ;~(pfix (tag 3) till)))) (stag %oct (boss 256 ;~(pfix (tag 4) till))) (stag %nul (cold ~ ;~(plug (tag 5) (tag 0)))) (stag %obj (^boss 256 ;~(pfix (tag 6) till))) @@ -325,6 +333,15 @@ ?: ?=([@ ~] a) `a ?. =(0 i.a) `a ?.((gth i.t.a 127) ~ `t.a) + :: +bit:parse:der: convert bytewidth to bitwidth + :: + ++ bit + |= [len=@ud dat=@ux] + ^- (unit [len=@ud dat=@ux]) + ?. =(0 (end 3 1 dat)) ~ + :+ ~ + (mul 8 (dec len)) + (rsh 3 1 dat) :: +recur:parse:der: parse bytes for a list of +spec:asn1 :: ++ recur @@ -670,7 +687,9 @@ ^- spec:asn1 :~ %seq [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] - [%bit +:(pass:en:der:pkcs1 k)] + =/ a=[len=@ud dat=@ux] + (pass:en:der:pkcs1 k) + [%bit (mul 8 len.a) dat.a] == :: +ring:spec:pkcs8: private key ASN.1 :: @@ -691,7 +710,7 @@ =(rsa:obj:asn1 obj.i.seq.i.seq.a) == ~ - (pass:de:der:pkcs1 (met 3 bit.i.t.seq.a) bit.i.t.seq.a) + (pass:de:der:pkcs1 (div len.i.t.seq.a 8) bit.i.t.seq.a) :: +ring:de:spec:pkcs8: :: ++ ring !! @@ -758,9 +777,13 @@ :~ %seq dat [%seq [[%obj rsa-sha-256:obj:asn1] [%nul ~] ~]] - :: big-endian signature bytes - :: XX revisit %bit - [%bit (swp 3 (~(sign rs256 key) +:(en:^der dat)))] + :: big-endian signature bits + :: + :: the signature bitwidth is definitionally the key length + :: + :+ %bit + (met 0 n.pub.key) + (swp 3 (~(sign rs256 key) +:(en:^der dat))) == :: +info:en:spec:pkcs10: certificate request info :: @@ -1886,6 +1909,7 @@ test-rsa test-rsapem test-rsa-pkcs8 + test-rsa-pem-zero test-rs256 test-jwk test-jws @@ -2146,6 +2170,32 @@ %- expect-eq !> [pub (pass:en:pem:pkcs8 k)] :: + ++ test-rsa-pem-zero + :: intentional bad values to test significant trailing zeros + =/ k=key:rsa [[n=(bex 16) e=(bex 16)] ~] + :: pkcs1 + =/ kpem=wain + :~ '-----BEGIN RSA PUBLIC KEY-----' + 'MAoCAwEAAAIDAQAA' + '-----END RSA PUBLIC KEY-----' + == + :: pkcs8 + =/ kpem2=wain + :~ '-----BEGIN PUBLIC KEY-----' + 'MB4wDQYJKoZIhvcNAQEBBQADDQAwCgIDAQAAAgMBAAA=' + '-----END PUBLIC KEY-----' + == + ;: weld + %- expect-eq !> + [kpem (pass:en:pem:pkcs1 k)] + %- expect-eq !> + [`k (pass:de:pem:pkcs1 kpem)] + %- expect-eq !> + [kpem2 (pass:en:pem:pkcs8 k)] + %- expect-eq !> + [`k (pass:de:pem:pkcs8 kpem2)] + == + :: ++ test-rsa =/ k1=key:rsa =/ p `@ux`61 From d2a7111f581466e8b3a385374a80690cc9265fbe Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 27 Jun 2018 01:15:35 -0400 Subject: [PATCH 74/95] adds pkcs8 private key en/de-coding --- app/acme.hoon | 80 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 224af46fb..576ef9e1f 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -668,7 +668,7 @@ -- -- -- -:: |pkcs8: asymmetric cryptography (rfc5208) +:: |pkcs8: asymmetric cryptography (rfc5208, rfc5958) :: :: RSA-only for now. :: @@ -682,6 +682,9 @@ |% :: +pass:spec:pkcs8: public key ASN.1 :: + :: Technically not part of pkcs8, but standardized later in + :: the superseding RFC. Included here for symmetry. + :: ++ pass |= k=key:rsa ^- spec:asn1 @@ -693,13 +696,19 @@ == :: +ring:spec:pkcs8: private key ASN.1 :: - ++ ring !! + ++ ring + |= k=key:rsa + ^- spec:asn1 + :~ %seq + [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] + [%oct (ring:en:der:pkcs1 k)] + == -- - :: |de:spec:pkcs8: + :: |de:spec:pkcs8: ASN.1 decoding for asymmetric keys :: ++ de |% - :: +pass:de:spec:pkcs8: + :: +pass:de:spec:pkcs8: decode public key ASN.1 :: ++ pass |= a=spec:asn1 @@ -711,9 +720,18 @@ == ~ (pass:de:der:pkcs1 (div len.i.t.seq.a 8) bit.i.t.seq.a) - :: +ring:de:spec:pkcs8: + :: +ring:de:spec:pkcs8: decode private key ASN.1 :: - ++ ring !! + ++ ring + |= a=spec:asn1 + ^- (unit key:rsa) + ?. ?=([%seq [%seq *] [%oct *] ~] a) + ~ + ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.seq.a) + =(rsa:obj:asn1 obj.i.seq.i.seq.a) + == + ~ + (ring:de:der:pkcs1 [len oct]:i.t.seq.a) -- -- :: |der:pkcs8: DER encoding for asymmetric keys @@ -726,12 +744,12 @@ ++ en |% ++ pass |=(k=key:rsa `[len=@ud dat=@ux]`(en:^der (pass:en:spec k))) - ++ ring !! ::|=(k=key:rsa `@ux`(en:^der (ring:spec k))) + ++ ring |=(k=key:rsa `[len=@ud dat=@ux]`(en:^der (ring:en:spec k))) -- ++ de |% ++ pass |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) pass:de:spec)) - ++ ring !! ::|=(a=@ `(unit key:rsa)`(biff (de:^der a) ring:de:spec)) + ++ ring |=([len=@ud dat=@ux] `(unit key:rsa)`(biff (de:^der len dat) ring:de:spec)) -- -- :: |pem:pkcs8: PEM encoding for asymmetric keys @@ -744,12 +762,12 @@ ++ en |% ++ pass |=(k=key:rsa (en:^pem 'PUBLIC KEY' (pass:en:der k))) - ++ ring !! ::|=(k=key:rsa (en:^pem 'PUBLIC KEY' (ring:en:der k))) + ++ ring |=(k=key:rsa (en:^pem 'PRIVATE KEY' (ring:en:der k))) -- ++ de |% ++ pass |=(mep=wain (biff (de:^pem 'PUBLIC KEY' mep) pass:de:der)) - ++ ring !! ::|=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) + ++ ring |=(mep=wain (biff (de:^pem 'PRIVATE KEY' mep) ring:de:der)) -- -- -- @@ -2165,10 +2183,48 @@ 'FwIDAQAB' '-----END PUBLIC KEY-----' == + =/ pri=wain + :~ '-----BEGIN PRIVATE KEY-----' + 'MIIEujANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDaMmnx2AArLlxLMMTg' + 'P5pRspmxCgyEhYjYgWUT4A7QYIEyKDmrHHYggA9UhxKLl+M4u1Mee4hljD6zTqp5' + 'vxAgpG+RlojCcDcvPlRSvGCH3qx7N1cIJIbsWd0gWyRxP7MbTQkv589F2U+O3VWD' + 'ZveSd6jloAowg/I5PNxjn3RRNz6W5DceGBKI0XeflhCHbh3eRLZg5ShJdDXf5hGW' + 'PE18GBdtX4Lv+A7yYXGmRp+GaCQgY15aWpP2gAhFr6A7HXe48CD4lv/yU9X1sZoW' + 'oa/G8EynfFQBKXNgeIOe1wHkyI49FboGggYjmoMVJhFkGTL1ysTtYBiCq0+2DbXO' + '/HAXAgMBAAECggEAfSrsYaKyPhMjOLLqTWXPBcy5o7iLA76CiQh5TlR6ywiBNJ+k' + 'rUbvcKdlo+y0M8XWv+Wdwd/Fl9NC6KNY4ew7uS37Hn5HR5sN3RkZUDjl+ys+sJRH' + 'ZdFmYNEQK459MkYDXcbsXUHSQlRt8huAAZggrzHbfpY3Iiue2TzThIalOCy0Kxnn' + 'WsrkYvp2JlVBt5TzTqg/VmHH/J7/81GZLkbSKKX/8fjWlXlYaiY5fSar38dgFmoK' + 'dyrMuSLoUV2ZfKSPPyye9dRHjRLwH5rQX8s37nj09J7Z2n2HQfHgcIk6wv0LIJCK' + 'aqqoTwo9DgFTPyrf4yHHXETJrEiU0f0QKCjUIQKBgQD6aLu9BHOy1gl6tuEK1p4W' + 's5H+fwN+3sXIU37khXsfaibLqB/TOvUZaOamHlHSww+Avy5VEYA1SuS5lm4KvfmJ' + 'jrNCl0IUHgP237NtO9OavG3ahVoTXr90gnpvxwfNHZCsSHy7Dn+sQrNYEIc1LwW9' + 'cc+9e+dpxNnktlErSyyyEQKBgQDfEZCcOWZHDJW2j/UNAwueMgxrNDvX2q0I7+l/' + 'gEd6pwNicjBhvnMsGPac9XwP2mozWkY5W46BwL0iKatsd54bCnWJJMfgC/EMiPoj' + 'KuZvPZ1veUZ0dWT3Eu9OJjOfYoraxjGYWXcNEEW60VDZjF12odsTcOz3pj+5FeGq' + 'PsjXpwKBgQDUBU3Acz6LU5LfJm1RQfrE+fJJa73H9FO+lIPCdgqTxMtocMfRj//r' + 'LdjtGorpS2Oa/UT7nj/R38HeKbKuwb/BauP5JB0871Un+KzxdlBqmdThyztDX1v4' + 'CGomrny6faf7V7zUnSgY8LjtfcEdlNzlVLIym/CKq7RaZMxBPftwIQKBgAIwRu3x' + 'djpuOi3PXcUh6YRE03Bd09R7VcVHrU/N72WZq+PUYPskhjbBi/HgSrZRG0ejtBqt' + '9kj5niFurTrkNY3oXVzaGoftNhE8as/bhOVEgn3sf69202XFLsnigBEpQ1mAJk5r' + 'WkqrhTOfCB8KTIR0dBTNv9VyMR/cwhkMgqXzAoGAGuwiOIO+mR+emZDt96EQkiL5' + 'XhIayQvEUfdlO+eAUWhivLd0vmBDqYWwN+ufiKAhwTLpsyklDeVvBK3LNxZkswmB' + '0jbcVOU9dMQbs9yVlK7EGlCm+DcyJU7OpVOuGdj5N6ZxJxLHk7p/fZoN85RZYLOb' + 'D+DO8nFRiUmqOp3t2VM=' + '-----END PRIVATE KEY-----' + == =/ k=key:rsa (need (ring:de:pem:pkcs1 kpem)) - %- expect-eq !> - [pub (pass:en:pem:pkcs8 k)] + ;: weld + %- expect-eq !> + [pub (pass:en:pem:pkcs8 k)] + %- expect-eq !> + [`k(sek ~) (pass:de:pem:pkcs8 pub)] + %- expect-eq !> + [pri (ring:en:pem:pkcs8 k)] + %- expect-eq !> + [`k (ring:de:pem:pkcs8 pri)] + == :: ++ test-rsa-pem-zero :: intentional bad values to test significant trailing zeros From 8a8b16e0bdcb3a1d5ee7622f3472e316d26e9afc Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 17:53:07 -0400 Subject: [PATCH 75/95] adds csr context-specific tag explanation comment --- app/acme.hoon | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/acme.hoon b/app/acme.hoon index 576ef9e1f..d01684697 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -812,6 +812,8 @@ [%int 0] [%seq ~] (pass:en:spec:pkcs8 key) + :: explicit, context-specific tag #0 (extensions) + :: :+ %con `bespoke:asn1`[| 0] %~ ren From d40151604b971141145c8306430c07af7d3c78ee Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 27 Jun 2018 12:57:44 -0400 Subject: [PATCH 76/95] adds comment to and reformats +emsa:rs256 --- app/acme.hoon | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index d01684697..f241ffda1 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -504,13 +504,16 @@ [%seq [%obj sha-256:obj:asn1] [%nul ~] ~] [%oct 32 (shax m)] == - =/ t=(list @) ~(ren raw:en:der pec) - =/ tlen (lent t) + :: note: this asn.1 digest is rendered raw here, as we require + :: big-endian bytes, and the product of +en:der is little-endian + :: + =/ t=(list @D) ~(ren raw:en:der pec) + =/ tlen=@ud (lent t) ?: (lth emlen (add 11 tlen)) ~|(%emsa-too-short !!) - =/ ps (reap (sub emlen (add 3 tlen)) 0xff) - %+ rep 3 - (flop (weld [0x0 0x1 ps] [0x0 t])) :: note: big-endian + =/ ps=(list @D) + (reap (sub emlen (add 3 tlen)) 0xff) + (rep 3 (flop (weld [0x0 0x1 ps] [0x0 t]))) :: +sign:rs256: sign message :: :: An RSA signature is the primitive decryption of the message hash. From 76788656d7f39e8ae763c9af8536f0876e1e2cba Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 26 Jun 2018 17:53:29 -0400 Subject: [PATCH 77/95] refactors +nonce:effect and call sites and fixes typo in +bad-nonce --- app/acme.hoon | 61 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index f241ffda1..dc29a6526 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1173,6 +1173,14 @@ $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] [%well wire path (unit mime)] == +:: +nonce-next: next effect to emit upon receiving nonce +:: ++= nonce-next + $? %register + %new-order + %finalize-order + %finalize-trial + == :: +turf: a domain, TLD first :: += turf (list @t) @@ -1399,7 +1407,7 @@ =/ jon=(unit json) (de-json:html q.u.r.rep) ?~ jon | :: XX unit parser, types - =('urn:ietf:params:acme:error:badNonce' +:(error:grab u.jon)) + =('urn:ietf:params:acme:error:badNonce' -:(error:grab u.jon)) :: |effect: send moves to advance :: ++ effect @@ -1412,10 +1420,12 @@ :: +nonce: get a new nonce for the next request :: ++ nonce - |= nex=wire + |= nex=@tas + ~| [%bad-nonce-next nex] + ?> ?=(nonce-next nex) ^+ this - ?> ?=([%next *] nex) :: XX now? - (emit (request (weld `wire`/acme/nonce `wire`nex) non.dir %get ~ ~)) + :: XX now? + (emit (request /acme/nonce/next/[nex] non.dir %get ~ ~)) :: +register: create ACME service account :: :: Note: accepts services ToS. @@ -1423,7 +1433,7 @@ ++ register ^+ this ?~ nonces - (nonce /next/register) + (nonce %register) %- emit(nonces t.nonces, reg.act ~) %+ request /acme/register/(scot %p our.bow) :: XX now? @@ -1439,7 +1449,7 @@ ?. ?=(^ reg.act) ~|(%no-account !!) ?. ?=([~ ^] pen) ~|(%no-domains !!) ?~ nonces - (nonce /next/new-order) + (nonce %new-order) %- emit(nonces t.nonces) %+ request /acme/new-order/(scot %da now.bow) @@ -1463,7 +1473,7 @@ :: XX revisit wrt rate limits ?> ?=(%wake sas.u.rod) ?~ nonces - (nonce /next/finalize-order) + (nonce %finalize-order) %- emit(nonces t.nonces) %+ request /acme/finalize-order/(scot %da now.bow) @@ -1554,7 +1564,7 @@ ?> ?=(%wake sas.u.rod) =* aut u.active.aut.u.rod ?~ nonces - (nonce /next/finalize-trial) + (nonce %finalize-trial) %- emit(nonces t.nonces) %+ request :: XX idx in wire? @@ -1584,24 +1594,27 @@ this =. dir (directory:grab (need (de-json:html q:(need r.rep)))) ?~(reg.act register:effect this) - :: +nonce: accept new nonce (XX already saved?), trigger next effect + :: +nonce: accept new nonce and trigger next effect :: - :: As specified in the wire. + :: Nonce has already been saved in +sigh-httr. The next effect + :: is specified in the wire. :: ++ nonce |= [wir=wire rep=httr] ^+ this - ?. =(204 p.rep) - :: XX never happened yet, retry nonce? - ~& [%nonce-fail wir rep] - this - ?. &(?=(^ wir) ?=([%next ^] t.wir)) - ~& [%unrecognized-nonce-wire wir] - this + ~| [%unrecognized-nonce-wire wir] + ?> &(?=(^ wir) ?=([%next ^] t.wir)) =* nex i.t.t.wir - ?+ nex - ~& [%unknown-nonce-next nex] - this + ~| [%unknown-nonce-next nex] + ?> ?=(nonce-next nex) + ?. =(204 p.rep) + :: cttp i/o timeout, always retry + :: XX set timer to backoff? + ?: =(504 p.rep) (nonce:effect nex) + :: XX never happened yet, retry nonce anyway? + :: + ~&([%nonce-fail wir rep] this) + ?- nex %register register:effect %new-order new-order:effect %finalize-order finalize-order:effect @@ -1615,7 +1628,7 @@ ?. =(201 p.rep) ::XX 204? ?: (bad-nonce rep) - (nonce:effect /next/register) + (nonce:effect %register) :: XX retry immediately or backoff? ~& [%register-fail wir rep] this @@ -1638,7 +1651,7 @@ ^+ this ?. =(201 p.rep) ?: (bad-nonce rep) - (nonce:effect /next/new-order) + (nonce:effect %new-order) :: XX retry immediately or backoff? :: XX possible 204? ~& [%new-order-fail wir rep] @@ -1665,7 +1678,7 @@ ^+ this ?. =(200 p.rep) ?: (bad-nonce rep) - (nonce:effect /next/finalize-order) + (nonce:effect %finalize-order) ~& [%finalize-order-fail wir rep] ?> ?=(^ rod) :: XX get the failure reason @@ -1787,7 +1800,7 @@ ^+ this ?. =(200 p.rep) ?: (bad-nonce rep) - (nonce:effect /next/finalize-trial) + (nonce:effect %finalize-trial) :: XX retry? or cancel order? :: XX 204 assume pending? ~& [%finalize-trial-fail wir rep] From c8c90bc587cd7d4f7a99c398c662e00caed3570f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 15:56:20 -0400 Subject: [PATCH 78/95] integrates :acme with %eyre (receive new domains/orders, install certificates) --- app/acme.hoon | 24 ++++++++++++++++++++---- mar/acme/order.hoon | 9 +++++++++ sys/vane/eyre.hoon | 20 +++++++------------- 3 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 mar/acme/order.hoon diff --git a/app/acme.hoon b/app/acme.hoon index dc29a6526..0c5eafc27 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1172,6 +1172,7 @@ += card $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] [%well wire path (unit mime)] + [%rule wire %cert (unit [wain wain])] == :: +nonce-next: next effect to emit upon receiving nonce :: @@ -1501,6 +1502,15 @@ ?. ?=(^ rod) ~|(%no-active-order !!) =/ hed (my accept+['applicate/x-pem-file' ~] ~) (emit (request /acme/certificate/(scot %da now.bow) url %get hed ~)) + :: +install: tell %eyre about our certificate + :: + ++ install + ^+ this + ~| %install-effect-fail + ?> ?=(^ liv) + :: XX use pkcs8 + =/ key=wain (ring:en:pem:pkcs1 key.u.liv) + (emit %rule /install %cert `[key `wain`cer.u.liv]) :: +get-authz: get next ACME service domain authorization object :: ++ get-authz @@ -1743,11 +1753,10 @@ =/ cer=wain (to-wain:format q:(need r.rep)) =/ fig=config :: XX expiration date - [dom.u.rod key.u.rod cer *@da ego.u.rod] + [dom.u.rod key.u.rod cer (add now.bow ~d90) ego.u.rod] =? fig.hit ?=(^ liv) [u.liv fig.hit] - this(liv `fig, rod ~) - :: XX send configuration to eyre - :: XX other subscribers? + :: XX set renewal timer + install:effect(liv `fig, rod ~) :: +get-authz: accept ACME service authorization object :: ++ get-authz @@ -1864,6 +1873,11 @@ %finalize-trial finalize-trial:event :: XX delete-trial? == +:: +poke-acme-order: create new order for a set of domains +:: +++ poke-acme-order + |=(a=(set turf) abet:(add-order ~(tap in a))) +:: +poke-noun: for debugging :: ++ poke-noun |= a=* @@ -1882,8 +1896,10 @@ %final finalize-order:effect %poll check-order:effect %our (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) + %rule install:effect %test test == +:: +poke-path: for debugging :: ++ poke-path |=(a=path abet:(add-order a ~)) diff --git a/mar/acme/order.hoon b/mar/acme/order.hoon new file mode 100644 index 000000000..a43c30cc6 --- /dev/null +++ b/mar/acme/order.hoon @@ -0,0 +1,9 @@ +:: +:::: /mar/acme/order/hoon + :: +|_ a=(set (list @t)) +++ grab + |% + ++ noun (set (list @t)) + -- +-- diff --git a/sys/vane/eyre.hoon b/sys/vane/eyre.hoon index a37fc76c2..4d3f389c3 100644 --- a/sys/vane/eyre.hoon +++ b/sys/vane/eyre.hoon @@ -671,10 +671,9 @@ |=(a=host ?>(?=(%& -.a) p.a)) =/ dif/(set (list @t)) (~(dif in mod) dom) =? dom ?=(^ dif) (~(uni in dom) mod) - ~& [%eyre %acme-order dom] - :: =? mow ?=(^ dif) - :: =/ cmd [%acme %poke `cage`[%acme-order !>(dom)]] - :: [[hen %pass ~ %g %deal [our our] cmd] mow] + =? mow ?=(^ dif) + =/ cmd [%acme %poke `cage`[%acme-order !>(dom)]] + :_(mow [hen %pass /acme/order %g %deal [our our] cmd]) %= +>.$ ged hen :: register external mow :_(mow [hen [%give %form fig]]) @@ -687,10 +686,8 @@ ?- -.p.kyz $cert ?: =(secure.fig p.p.kyz) +>.$ - %= +>.$ - secure.fig p.p.kyz - mow :_(mow [hen [%give %form fig]]) - == + =. secure.fig p.p.kyz + +>.$(mow :_(mow [ged [%give %form fig]])) :: $turf =/ mod/(set (list @t)) @@ -698,13 +695,10 @@ (~(put in dom) q.p.kyz) (~(del in dom) q.p.kyz) ?: =(dom mod) +>.$ - ~& [%eyre %acme-order dom] - :: =. mow - :: =/ cmd [%acme %poke `cage`[%acme-order !>(dom)]] - :: [[hen %pass ~ %g %deal [our our] cmd] mow] + =/ cmd [%acme %poke `cage`[%acme-order !>(mod)]] %= +>.$ dom mod - mow :_(mow [hen [%give %form fig]]) + mow :_(mow [hen %pass /acme/order %g %deal [our our] cmd]) == == :: From 26b10e79b5372355a5d7ce8f5c8114ccaff727f8 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 20:03:16 -0400 Subject: [PATCH 79/95] defer initial http request from +prep --- app/acme.hoon | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 0c5eafc27..181fc5ff5 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1171,6 +1171,7 @@ :: += card $% [%hiss wire [~ ~] %httr %hiss hiss:eyre] + [%wait wire @da] [%well wire path (unit mime)] [%rule wire %cert (unit [wain wain])] == @@ -1585,7 +1586,10 @@ :: :: +retry: retry effect after timeout :: - ++ retry !! + ++ retry + |= [wir=wire wen=@da] + :: XX validate wire and date + (emit %wait [%acme wir] wen) -- :: |event: accept event, emit next effect(s) :: @@ -1833,8 +1837,13 @@ :: +retry: retry effect after timeout :: ++ retry - :: XX implement wire parsing / next effect - !! + |= wir=wire + ^+ this + ?+ wir + ~&(unknown-retry+wir this) + :: XX do the needful + [%directory ~] directory:effect + == -- :: +sigh-tang: handle http request failure :: @@ -1873,6 +1882,14 @@ %finalize-trial finalize-trial:event :: XX delete-trial? == +:: +wake: timer wakeup event +:: +++ wake + |= [wir=wire ~] + ^- (quip move _this) + ~& [%wake wir] + ?> ?=([%acme *] wir) + abet:(retry:event t.wir) :: +poke-acme-order: create new order for a set of domains :: ++ poke-acme-order @@ -1928,7 +1945,7 @@ ++ init =/ url 'https://acme-staging-v02.api.letsencrypt.org/directory' - =< directory:effect + =< (retry:effect /directory +(now.bow)) %= this bas (need (de-purl:html url)) act [(rekey eny.bow) ~] From 5393b129f268ba7794ba5420f3ba4c5c4e4469e7 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 22:52:35 -0400 Subject: [PATCH 80/95] defers pending order creation to after registration --- app/acme.hoon | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 181fc5ff5..57590e8ff 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1655,7 +1655,8 @@ (acct:grab (need (de-json:html q.u.r.rep))) ?> ?=(%valid sas.bod) wen.bod - this(reg.act `[wen loc]) + =. reg.act `[wen loc] + ?~(pen this new-order:effect) :: XX rekey :: :: +new-order: order created, begin processing authorizations @@ -1893,7 +1894,9 @@ :: +poke-acme-order: create new order for a set of domains :: ++ poke-acme-order - |=(a=(set turf) abet:(add-order ~(tap in a))) + |= a=(set turf) + ~& [%poke-acme a] + abet:(add-order a) :: +poke-noun: for debugging :: ++ poke-noun @@ -1912,14 +1915,14 @@ %trial test-trial:effect %final finalize-order:effect %poll check-order:effect - %our (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) + %our (add-order (sy /org/urbit/(crip +:(scow %p our.bow)) ~)) %rule install:effect %test test == :: +poke-path: for debugging :: ++ poke-path - |=(a=path abet:(add-order a ~)) + |=(a=path abet:(add-order (sy a ~))) :: :: ++ prep _[~ this] ++ prep @@ -1951,18 +1954,16 @@ act [(rekey eny.bow) ~] cey (rekey (mix eny.bow (shaz now.bow))) == - :: XX wait for DNS binding confirmation? - :: (add-order /org/urbit/(crip +:(scow %p our.bow)) ~) :: ++ add-order - |= dom=(list turf) + |= dom=(set turf) ^+ this :: XX we may have pending moves out for this order :: XX put dates in wires, check against order creation date? :: XX or re-use order-id? =? fal.hit ?=(^ rod) [u.rod fal.hit] - :: XX check registration, defer - new-order:effect(rod ~, pen `(sy dom)) + =< ?~(reg.act this new-order:effect) + this(rod ~, pen `dom) :: ++ test =, tester:tester From 6ec776f04aa70889d75c3265c9fe0855c9aef7d7 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 29 Jun 2018 00:01:45 -0400 Subject: [PATCH 81/95] defers :acme initialization to first certificate order --- app/acme.hoon | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 57590e8ff..cba797f9a 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1928,11 +1928,9 @@ ++ prep |= old=(unit acme) ^- (quip move _this) - ?^ old - [~ this(+<+ u.old)] - ?: ?=(?(%earl %pawn) (clan:title our.bow)) + ?~ old [~ this] - abet:init + [~ this(+<+ u.old)] :: ++ rekey :: XX do something about this |= eny=@ @@ -1958,12 +1956,26 @@ ++ add-order |= dom=(set turf) ^+ this - :: XX we may have pending moves out for this order - :: XX put dates in wires, check against order creation date? - :: XX or re-use order-id? + ?: ?=(?(%earl %pawn) (clan:title our.bow)) + this + :: set pending order + :: + =. pen `dom + :: archive active order if exists + :: + :: XX we may have pending moves out for this order + :: put dates in wires, check against order creation date? + :: or re-use order-id? + :: =? fal.hit ?=(^ rod) [u.rod fal.hit] - =< ?~(reg.act this new-order:effect) - this(rod ~, pen `dom) + =. rod ~ + :: if registered, create order + :: + ?^ reg.act + new-order:effect + :: if initialized, defer + :: + ?.(=(act *acct) this init) :: ++ test =, tester:tester From a20122a410419a2d4c8c514339fc46437d467c32 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 19:02:19 -0400 Subject: [PATCH 82/95] auto-starts :acme --- lib/hood/drum.hoon | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/hood/drum.hoon b/lib/hood/drum.hoon index 7ac3f3c64..5abf0e61a 100644 --- a/lib/hood/drum.hoon +++ b/lib/hood/drum.hoon @@ -81,6 +81,7 @@ ?: ?=($pawn myr) [[%base %collections] [%base %hall] [%base %talk] [%base %dojo] ~] :~ [%home %collections] + [%home %acme] [%home %dns] [%home %dojo] [%home %hall] From d8649441bfe22fcf5a65496e061911405e1b32fe Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 23:27:12 -0400 Subject: [PATCH 83/95] updates oauth libraries to use the real %eyre host scry --- lib/oauth1.hoon | 2 +- lib/oauth2.hoon | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/oauth1.hoon b/lib/oauth1.hoon index 35a47dc90..1adae5201 100644 --- a/lib/oauth1.hoon +++ b/lib/oauth1.hoon @@ -102,7 +102,7 @@ |= a/$@(@t purl) ^- hiss (post-quay (parse-url a) oauth-callback+oauth-callback ~) :: -++ our-host .^(hart %e /(scot %p our)/host/fake) +++ our-host .^(hart %e /(scot %p our)/host/real) ++ oauth-callback ~& [%oauth-warning "Make sure this urbit ". "is running on {(en-purl:html our-host `~ ~)}"] diff --git a/lib/oauth2.hoon b/lib/oauth2.hoon index 54b949d2d..7a140a8ad 100644 --- a/lib/oauth2.hoon +++ b/lib/oauth2.hoon @@ -101,7 +101,7 @@ %+ rap 3 :- (wack a) (turn b |=(c/knot (cat 3 '_' (wack c)))) :: -++ our-host .^(hart %e /(scot %p our)/host/fake) +++ our-host .^(hart %e /(scot %p our)/host/real) ++ redirect-uri %- crip %- en-purl %^ into-url:interpolate 'https://our-host/~/ac/:domain/:user/in' From 14841db28da90d0ee026296de1f75018f3dc0625 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 28 Jun 2018 15:57:18 -0400 Subject: [PATCH 84/95] updates :dns to notify %eyre on new bindings --- app/dns.hoon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/dns.hoon b/app/dns.hoon index becd968eb..6a20b7d92 100644 --- a/app/dns.hoon +++ b/app/dns.hoon @@ -14,6 +14,7 @@ == += card $% [%tend wire ~] [%poke wire dock poke] + [%rule wire %turf %put turf] [%hiss wire [~ ~] %httr %hiss hiss:eyre] == :: +state: complete app state @@ -259,9 +260,8 @@ ?: =(for him) ~|(%bond-yoself !!) ?: =(our.bow him) - :: XX notify eyre/hood/acme etc ~& [%bound-us dom] - :- ~ + :- [[ost.bow %rule /bound %turf %put dom] ~] this(dom (~(put in ^dom) dom)) ?: =(our.bow for) ~& [%bound-him him dom] From 5a953aa01bacbab9390f3ab2a87e88badbfaac46 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 29 Jun 2018 16:30:08 -0400 Subject: [PATCH 85/95] fixes bug in +reserved predicate for ipv4 addresses --- app/dns.hoon | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/dns.hoon b/app/dns.hoon index 6a20b7d92..48b44e83f 100644 --- a/app/dns.hoon +++ b/app/dns.hoon @@ -56,17 +56,16 @@ ++ reserved |= a=@if ^- ? - =/ b (rip 3 a) - ?> ?=([@ @ @ @ ~] b) - ?| :: 0.0.0.0/8 (software) - :: - =(0 i.b) - :: 10.0.0.0/8 (private) + =/ b (flop (rip 3 a)) + :: 0.0.0.0/8 (software) + :: + ?. ?=([@ @ @ @ ~] b) & + ?| :: 10.0.0.0/8 (private) :: =(10 i.b) :: 100.64.0.0/10 (carrier-grade NAT) :: - &(=(100 i.b) (gte 64 i.t.b) (lte 127 i.t.b)) + &(=(100 i.b) (gte i.t.b 64) (lte i.t.b 127)) :: 127.0.0.0/8 (localhost) :: =(127 i.b) @@ -75,7 +74,7 @@ &(=(169 i.b) =(254 i.t.b)) :: 172.16.0.0/12 (private) :: - &(=(172 i.b) (gte 16 i.t.b) (lte 31 i.t.b)) + &(=(172 i.b) (gte i.t.b 16) (lte i.t.b 31)) :: 192.0.0.0/24 (protocol assignment) :: &(=(192 i.b) =(0 i.t.b) =(0 i.t.t.b)) @@ -101,7 +100,7 @@ :: 240.0.0.0/4 (reserved, future) :: 255.255.255.255/32 (broadcast) :: - (gte 224 i.b) + (gte i.b 224) == :: |gcloud: provider-specific functions :: From 6419f27e3a68a8eddd01803df9cba50e1ea96a0b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 10 Jul 2018 16:29:35 -0400 Subject: [PATCH 86/95] adds debug install/uninstall cert events --- app/acme.hoon | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/app/acme.hoon b/app/acme.hoon index cba797f9a..369f11fd8 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1917,8 +1917,110 @@ %poll check-order:effect %our (add-order (sy /org/urbit/(crip +:(scow %p our.bow)) ~)) %rule install:effect + %fake fake + %none none %test test == +++ none + ^+ this + (emit %rule /uninstall %cert ~) +++ fake + ^+ this + =/ key=wain + :~ '-----BEGIN RSA PRIVATE KEY-----' + 'MIIEpAIBAAKCAQEAisQPzzmGWNZSNNAwY59XrqK/bU0NKNZS2ETOiJeSpzPAHYl+' + 'c39V96/QUR0tra2zQI4QD6kpMYX/7R5nwuvsA4o7ypfYupNrlzLPThCKEHpZomDD' + '0Bb3T8u7YGrMjEX5cOmZIU2T/iy4GK/wWuBIy2TEp/0J+RoSCIr8Df/A7GIM8bwn' + 'v23Vq0kE2xBqqaT5LjvuQoXfiLJ42F33DDno9lVikKEyt55D/08rH41KpXvn3tWZ' + '46tZK6Ds7Zr1hEV1LbDx1CXDzQ6gKObBe54DWDV3h7TJhr0BSW68dFJhro7Y60Ns' + 'zTcFqY1RC9F0ePtsnKGFzMOe/U+fPvsGe2oWvwIDAQABAoIBACCf19ewfpWETe98' + 'wuOpIsQ8HyVjaCShvvh5tNUITcJhuFk5ajFdTqjc/O0VHxgmLm6O99e2vaiXCISH' + 'EX4SWXq7lTMcYCf9YN47Y+HGoa8eFNTIS0ExJRPtojAY695O1UZmpUnfI1wux1mG' + 'g8vZz0OCfXnBVAbsyjCX/IqOBp2MVzfMyMuaF/oQ2xiX4AZ1hDIMDpUTGw7OKX15' + 'JAUlTZUhzifmijPg1gViD8Lf5w42nlwYPC5j6wWKpJSx76CNUxLdJAaaZb3QYE96' + 'zu/jOCdy25sPHIux3XTdV6fqZ2iTvt31+bcnSAvmbDpmcujsZPVRXRu5OO/0xBh6' + 'GGlTLAECgYEAwSyNkbNk0mBRxet68IW02wXYaxIEVUWqhSeE2MGaXg4h9VSgh83q' + '7wly0ujy9Sj79aF2frkpMbIoeeGIOTIYI4RCYuBKx+/NNWFoggu4UK5xOMr0dfQK' + '2Ggr2agUH3KExvOpAW3rvWzepLl8ppySLNipLcFQHOJ0kxwPd2ig3Z8CgYEAt+WM' + 'JoW9dLxUu/zTih5Dacubl+fnnm8BsypKmv88mzcqEVwXOo6Z6bmlw0NeWxmlwHu7' + 'vs+XQ8MDUDvQvIul8sFagZk7RvWcXTlaHtPQ1D8/ztrg5d58TwxpwXshBytfR6NA' + 'tIZa+tNvzQF5AKVlB+lZEWF6E6FoI5NmGDAZ8uECgYB4FV4cCMzQCphK1Muj4TpA' + 'PS3/wT94Usph4+Mta4yuk1KA047HXTaCSflbKvx9cnDOjQTAWhJFll6bBZxNEdr3' + 'mSw7kvppt6R1Xow861Q0s3wmteOpv39Ob9Nyho2bzvDDTIzvGonFQ3xUIgpe+E3W' + 'GwlwLA/FJPEa0gK7VAtMOQKBgQCgcPtX2LM0l+Ntp+V/yWuTb/quC7w+tCbNhAZX' + 'OHxOB1ECmFAD3MpX6oq+05YM8VF1n/5rOX6Ftiy74ZP6C/Sa2Sr3ixL2k+76PsFr' + 'x+2YYB5xgPFaXEQkS3YxQhXMxYB5ZetcFSRnVfVi7Pf/Ik4FGweEbIEvg1DySPV4' + 'AO+CwQKBgQCFnjHsFeNZVvtiL2wONT6osjRCpMvaUiVecMW9oUBtjpLHI2gQr7+4' + 'dvCm2Sj7uq9OWO0rBz1px/kI+ONjhwsFPLK5v8hyVDoIE791Qg3qAY1a6JOXRl9P' + '6TBc3dQ2qUVqt8gi9RLCDFJU18Td6La4mkJSP5YrioGtwUJow0F07Q==' + '-----END RSA PRIVATE KEY-----' + == + + =/ cert=wain + :~ '-----BEGIN CERTIFICATE-----' + 'MIIF8jCCBNqgAwIBAgITAPrPc8Udwmv5dJ+hx2Uh+gZF1TANBgkqhkiG9w0BAQsF' + 'ADAiMSAwHgYDVQQDDBdGYWtlIExFIEludGVybWVkaWF0ZSBYMTAeFw0xODA3MDMx' + 'ODAyMTZaFw0xODEwMDExODAyMTZaMB8xHTAbBgNVBAMTFHpvZC5keW5kbnMudXJi' + 'aXQub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAisQPzzmGWNZS' + 'NNAwY59XrqK/bU0NKNZS2ETOiJeSpzPAHYl+c39V96/QUR0tra2zQI4QD6kpMYX/' + '7R5nwuvsA4o7ypfYupNrlzLPThCKEHpZomDD0Bb3T8u7YGrMjEX5cOmZIU2T/iy4' + 'GK/wWuBIy2TEp/0J+RoSCIr8Df/A7GIM8bwnv23Vq0kE2xBqqaT5LjvuQoXfiLJ4' + '2F33DDno9lVikKEyt55D/08rH41KpXvn3tWZ46tZK6Ds7Zr1hEV1LbDx1CXDzQ6g' + 'KObBe54DWDV3h7TJhr0BSW68dFJhro7Y60NszTcFqY1RC9F0ePtsnKGFzMOe/U+f' + 'PvsGe2oWvwIDAQABo4IDIjCCAx4wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG' + 'CCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTokXAU' + 'vPwcrbkLxcVBCNNQ588pfjAfBgNVHSMEGDAWgBTAzANGuVggzFxycPPhLssgpvVo' + 'OjB3BggrBgEFBQcBAQRrMGkwMgYIKwYBBQUHMAGGJmh0dHA6Ly9vY3NwLnN0Zy1p' + 'bnQteDEubGV0c2VuY3J5cHQub3JnMDMGCCsGAQUFBzAChidodHRwOi8vY2VydC5z' + 'dGctaW50LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYDVR0RBBgwFoIUem9kLmR5bmRu' + 'cy51cmJpdC5vcmcwgf4GA1UdIASB9jCB8zAIBgZngQwBAgEwgeYGCysGAQQBgt8T' + 'AQEBMIHWMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCB' + 'qwYIKwYBBQUHAgIwgZ4MgZtUaGlzIENlcnRpZmljYXRlIG1heSBvbmx5IGJlIHJl' + 'bGllZCB1cG9uIGJ5IFJlbHlpbmcgUGFydGllcyBhbmQgb25seSBpbiBhY2NvcmRh' + 'bmNlIHdpdGggdGhlIENlcnRpZmljYXRlIFBvbGljeSBmb3VuZCBhdCBodHRwczov' + 'L2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzCCAQIGCisGAQQB1nkCBAIEgfME' + 'gfAA7gB1ALDMg+Wl+X1rr3wJzChJBIcqx+iLEyxjULfG/SbhbGx3AAABZGGGG6QA' + 'AAQDAEYwRAIgJHrIawVea5/++wteocdbt1QUBxysW7uJqYgvnOWOQMgCIGRlioyE' + 'vzunUm/HZre3fF2jBsJr45C1tz5FTe/cYQwmAHUA3Zk0/KXnJIDJVmh9gTSZCEmy' + 'Sfe1adjHvKs/XMHzbmQAAAFkYYYjLQAABAMARjBEAiAWovIKERYeNbJlAKvNorwn' + 'RnSFP0lJ9sguwcpbcsYJ1gIgRJxTolkMOr0Fwq62q4UYnpREY8zu4hiL90Mhntky' + 'EwYwDQYJKoZIhvcNAQELBQADggEBAMYxvA+p4Qj0U23AHAe61W3+M6T1M0BfrGE2' + 'jJCaq4c3d7b9NEN1qFJHl8t/+Z/7RHUIzbm4CIOZynSM8mBxg2NgXymvXQkRrrBo' + 'fhO9u8Yxizx4+KOtiigt9JBVlpyCm6I9uifM+7rZYh45s2IkfDBPKd+M1tfIUOne' + 'YgUt1YguEkM2xqRG16JyHA0Xwn6mn+4pWiTdfNzlqol6vyGT7WfIvmV7cdGoYKjB' + 'wOt/g1wWMTwhSWBCVqCyn+f2rl8u3wbXrIUeRng2ryNVXO03nukTp7OLN3HUO6PR' + 'hC4NdS4o2geBNZr8RJiORtCelDaJprY7lhh2MFzVpsodc2eB5sQ=' + '-----END CERTIFICATE-----' + '' + '-----BEGIN CERTIFICATE-----' + 'MIIEqzCCApOgAwIBAgIRAIvhKg5ZRO08VGQx8JdhT+UwDQYJKoZIhvcNAQELBQAw' + 'GjEYMBYGA1UEAwwPRmFrZSBMRSBSb290IFgxMB4XDTE2MDUyMzIyMDc1OVoXDTM2' + 'MDUyMzIyMDc1OVowIjEgMB4GA1UEAwwXRmFrZSBMRSBJbnRlcm1lZGlhdGUgWDEw' + 'ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtWKySDn7rWZc5ggjz3ZB0' + '8jO4xti3uzINfD5sQ7Lj7hzetUT+wQob+iXSZkhnvx+IvdbXF5/yt8aWPpUKnPym' + 'oLxsYiI5gQBLxNDzIec0OIaflWqAr29m7J8+NNtApEN8nZFnf3bhehZW7AxmS1m0' + 'ZnSsdHw0Fw+bgixPg2MQ9k9oefFeqa+7Kqdlz5bbrUYV2volxhDFtnI4Mh8BiWCN' + 'xDH1Hizq+GKCcHsinDZWurCqder/afJBnQs+SBSL6MVApHt+d35zjBD92fO2Je56' + 'dhMfzCgOKXeJ340WhW3TjD1zqLZXeaCyUNRnfOmWZV8nEhtHOFbUCU7r/KkjMZO9' + 'AgMBAAGjgeMwgeAwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw' + 'HQYDVR0OBBYEFMDMA0a5WCDMXHJw8+EuyyCm9Wg6MHoGCCsGAQUFBwEBBG4wbDA0' + 'BggrBgEFBQcwAYYoaHR0cDovL29jc3Auc3RnLXJvb3QteDEubGV0c2VuY3J5cHQu' + 'b3JnLzA0BggrBgEFBQcwAoYoaHR0cDovL2NlcnQuc3RnLXJvb3QteDEubGV0c2Vu' + 'Y3J5cHQub3JnLzAfBgNVHSMEGDAWgBTBJnSkikSg5vogKNhcI5pFiBh54DANBgkq' + 'hkiG9w0BAQsFAAOCAgEABYSu4Il+fI0MYU42OTmEj+1HqQ5DvyAeyCA6sGuZdwjF' + 'UGeVOv3NnLyfofuUOjEbY5irFCDtnv+0ckukUZN9lz4Q2YjWGUpW4TTu3ieTsaC9' + 'AFvCSgNHJyWSVtWvB5XDxsqawl1KzHzzwr132bF2rtGtazSqVqK9E07sGHMCf+zp' + 'DQVDVVGtqZPHwX3KqUtefE621b8RI6VCl4oD30Olf8pjuzG4JKBFRFclzLRjo/h7' + 'IkkfjZ8wDa7faOjVXx6n+eUQ29cIMCzr8/rNWHS9pYGGQKJiY2xmVC9h12H99Xyf' + 'zWE9vb5zKP3MVG6neX1hSdo7PEAb9fqRhHkqVsqUvJlIRmvXvVKTwNCP3eCjRCCI' + 'PTAvjV+4ni786iXwwFYNz8l3PmPLCyQXWGohnJ8iBm+5nk7O2ynaPVW0U2W+pt2w' + 'SVuvdDM5zGv2f9ltNWUiYZHJ1mmO97jSY/6YfdOUH66iRtQtDkHBRdkNBsMbD+Em' + '2TgBldtHNSJBfB3pm9FblgOcJ0FSWcUDWJ7vO0+NTXlgrRofRT6pVywzxVo6dND0' + 'WzYlTWeUVsO40xJqhgUQRER9YLOLxJ0O6C8i0xFxAMKOtSdodMB3RIwt7RFQ0uyt' + 'n5Z5MqkYhlMI3J1tPRTp1nEt9fyGspBOO05gi148Qasp+3N+svqKomoQglNoAxU=' + '-----END CERTIFICATE-----' + == + (emit %rule /install %cert `[key cert]) :: +poke-path: for debugging :: ++ poke-path From 7ea4b5bc0b8d0679ba4e713d94cf4310f9c2d1d8 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 10 Jul 2018 23:39:13 -0400 Subject: [PATCH 87/95] adds authentication nonce to proxy notifications %wise and %that --- sys/vane/eyre.hoon | 4 ++-- sys/zuse.hoon | 22 +++++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/sys/vane/eyre.hoon b/sys/vane/eyre.hoon index 4d3f389c3..198644155 100644 --- a/sys/vane/eyre.hoon +++ b/sys/vane/eyre.hoon @@ -864,12 +864,12 @@ [[%$ deps+!>(dep)] [%vale res]] == :: - $not +>.$(mow :_(mow [ged [%give %that q.p.kyz p.u.mez q.u.mez]])) + $not +>.$(mow :_(mow [ged [%give %that q.p.kyz p.u.mez]])) == :: $wegh !! :: handled elsewhere :: - $wise (ames-gram p.kyz [%not ~] q.kyz r.kyz) :: proxy notification + $wise (ames-gram p.kyz [%not ~] q.kyz) :: proxy notification == :: ::++ axom :: old response diff --git a/sys/zuse.hoon b/sys/zuse.hoon index 6bea60e09..3ee0d0d28 100644 --- a/sys/zuse.hoon +++ b/sys/zuse.hoon @@ -669,7 +669,7 @@ [%mass p=mass] :: memory usage [%mack p=(unit tang)] :: message ack [%sigh p=cage] :: marked http response - [%that p=@p q=@ud r=?] :: get proxied request + [%that p=@p q=prox] :: get proxied request [%thou p=httr] :: raw http response [%thus p=@ud q=(unit hiss)] :: http request+cancel [%veer p=@ta q=path r=@t] :: drop-through @@ -693,7 +693,7 @@ [%well p=path q=(unit mime)] :: put/del .well-known [%went p=sack q=path r=@ud s=coop] :: response confirm [%west p=sack q=[path *]] :: network request - [%wise p=@p q=@ud r=?] :: proxy notification + [%wise p=ship q=prox] :: proxy notification == :: -- ::able :: @@ -731,7 +731,7 @@ [[%get-inner ~] p=@uvH q=beam r=mark] ::TODO details? [[%got-inner ~] p=@uvH q=(each (cask) tang)] ::TODO details? :: - [[%not ~] p=@ud q=?] :: proxy notification + [[%not ~] p=prox] :: proxy notification == :: ++ hart {p/? q/(unit @ud) r/host} :: http sec+port+host ++ hate {p/purl q/@p r/moth} :: semi-cooked request @@ -807,6 +807,22 @@ ++ octs {p/@ud q/@t} :: octet-stream ++ oryx @t :: CSRF secret ++ pork {p/(unit @ta) q/(list @t)} :: fully parsed url + :: +prox: proxy notification + :: + :: Used on both the proxy (ward) and upstream sides for + :: sending/receiving proxied-request notifications. + :: + += prox + $: :: por: tcp port + :: + por=@ud + :: sek: secure? + :: + sek=? + :: non: authentication nonce + :: + non=@uvJ + == ++ purf (pair purl (unit @t)) :: url with fragment ++ purl {p/hart q/pork r/quay} :: parsed url ++ quay (list {p/@t q/@t}) :: parsed url query From f5991978be337dbac9b9f933d7ec53561b5b3cd1 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Sun, 15 Jul 2018 17:00:21 -0400 Subject: [PATCH 88/95] retry %direct binding verification of 504 response (cttp timeout) --- app/dns.hoon | 45 +++++++++++++++++++++++++++++++++------------ sur/dns.hoon | 1 + 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/app/dns.hoon b/app/dns.hoon index 48b44e83f..2273db40c 100644 --- a/app/dns.hoon +++ b/app/dns.hoon @@ -6,17 +6,20 @@ :: |% += move (pair bone card) -+= poke $% [%dns-bind for=ship him=ship target] - [%dns-bond for=ship him=ship turf] - [%dns-authority authority] - :: XX some other notification channel? - [%helm-send-hi ship (unit tape)] - == -+= card $% [%tend wire ~] - [%poke wire dock poke] - [%rule wire %turf %put turf] - [%hiss wire [~ ~] %httr %hiss hiss:eyre] - == ++= poke + $% [%dns-bind for=ship him=ship target] + [%dns-bond for=ship him=ship turf] + [%dns-authority authority] + :: XX some other notification channel? + [%helm-send-hi ship (unit tape)] + == ++= card + $% [%tend wire ~] + [%wait wire @da] + [%poke wire dock poke] + [%rule wire %turf %put turf] + [%hiss wire [~ ~] %httr %hiss hiss:eyre] + == :: +state: complete app state :: += state @@ -192,6 +195,11 @@ =/ him=ship (slav %p i.t.wir) ?: =(200 p.rep) abet:~(bind tell [him (~(get by per) him)]) + :: cttp timeout + ?: =(504 p.rep) + :: XX backoff, refactor + :_ this :_ ~ + [ost.bow %wait wir (add now.bow ~m10)] :: XX specific messages per status code ~& %direct-confirm-fail abet:(~(fail tell [him (~(get by per) him)]) %failed-request) @@ -219,6 +227,16 @@ %- (slog saw) abet:(~(fail tell [him (~(get by per) him)]) %crash) == +:: +wake: timer callback +:: +++ wake + |= [wir=wire ~] + ^- (quip move _this) + ?. ?=([%check @ ~] wir) + ~& [%strange-wake wir] + [~ this] + =/ him=ship (slav %p i.t.wir) + abet:~(check tell [him (~(get by per) him)]) :: :: +poke-dns-authority: configure self as an authority :: @@ -405,7 +423,7 @@ !=(tar tar.u.rel) == this - =. rel `[wen=now.bow adr bon=| tar] + =. rel `[wen=now.bow adr bon=| try=0 tar] ?:(?=(%indirect -.tar) bind check) :: +check: confirm %direct target is accessible :: @@ -415,6 +433,9 @@ ?> ?=(%direct -.tar.u.rel) ?: (reserved p.tar.u.rel) (fail %reserved-ip) + ?: (gth try.u.rel 2) + (fail %unreachable) + =. try.u.rel +(try.u.rel) =/ wir=wire /check/(scot %p him) =/ url=purl:eyre diff --git a/sur/dns.hoon b/sur/dns.hoon index 474669174..e01652ab2 100644 --- a/sur/dns.hoon +++ b/sur/dns.hoon @@ -53,6 +53,7 @@ $: wen=@da wer=(unit @if) bon=? + try=@ud tar=target == -- From 36d15d296c93c1d0c323bc68b7f57e56c9d6ab4e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 16 Jul 2018 12:27:29 -0400 Subject: [PATCH 89/95] fixes pkcs8 ASN.1 en/de-coding (missing constant version) --- app/acme.hoon | 61 ++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 369f11fd8..0c05e5dca 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -703,6 +703,7 @@ |= k=key:rsa ^- spec:asn1 :~ %seq + [%int 0] [%seq [[%obj rsa:obj:asn1] [%nul ~] ~]] [%oct (ring:en:der:pkcs1 k)] == @@ -728,13 +729,13 @@ ++ ring |= a=spec:asn1 ^- (unit key:rsa) - ?. ?=([%seq [%seq *] [%oct *] ~] a) + ?. ?=([%seq [%int %0] [%seq *] [%oct *] ~] a) ~ - ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.seq.a) - =(rsa:obj:asn1 obj.i.seq.i.seq.a) + ?. ?& ?=([[%obj *] [%nul ~] ~] seq.i.t.seq.a) + =(rsa:obj:asn1 obj.i.seq.i.t.seq.a) == ~ - (ring:de:der:pkcs1 [len oct]:i.t.seq.a) + (ring:de:der:pkcs1 [len oct]:i.t.t.seq.a) -- -- :: |der:pkcs8: DER encoding for asymmetric keys @@ -2351,32 +2352,32 @@ == =/ pri=wain :~ '-----BEGIN PRIVATE KEY-----' - 'MIIEujANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDaMmnx2AArLlxLMMTg' - 'P5pRspmxCgyEhYjYgWUT4A7QYIEyKDmrHHYggA9UhxKLl+M4u1Mee4hljD6zTqp5' - 'vxAgpG+RlojCcDcvPlRSvGCH3qx7N1cIJIbsWd0gWyRxP7MbTQkv589F2U+O3VWD' - 'ZveSd6jloAowg/I5PNxjn3RRNz6W5DceGBKI0XeflhCHbh3eRLZg5ShJdDXf5hGW' - 'PE18GBdtX4Lv+A7yYXGmRp+GaCQgY15aWpP2gAhFr6A7HXe48CD4lv/yU9X1sZoW' - 'oa/G8EynfFQBKXNgeIOe1wHkyI49FboGggYjmoMVJhFkGTL1ysTtYBiCq0+2DbXO' - '/HAXAgMBAAECggEAfSrsYaKyPhMjOLLqTWXPBcy5o7iLA76CiQh5TlR6ywiBNJ+k' - 'rUbvcKdlo+y0M8XWv+Wdwd/Fl9NC6KNY4ew7uS37Hn5HR5sN3RkZUDjl+ys+sJRH' - 'ZdFmYNEQK459MkYDXcbsXUHSQlRt8huAAZggrzHbfpY3Iiue2TzThIalOCy0Kxnn' - 'WsrkYvp2JlVBt5TzTqg/VmHH/J7/81GZLkbSKKX/8fjWlXlYaiY5fSar38dgFmoK' - 'dyrMuSLoUV2ZfKSPPyye9dRHjRLwH5rQX8s37nj09J7Z2n2HQfHgcIk6wv0LIJCK' - 'aqqoTwo9DgFTPyrf4yHHXETJrEiU0f0QKCjUIQKBgQD6aLu9BHOy1gl6tuEK1p4W' - 's5H+fwN+3sXIU37khXsfaibLqB/TOvUZaOamHlHSww+Avy5VEYA1SuS5lm4KvfmJ' - 'jrNCl0IUHgP237NtO9OavG3ahVoTXr90gnpvxwfNHZCsSHy7Dn+sQrNYEIc1LwW9' - 'cc+9e+dpxNnktlErSyyyEQKBgQDfEZCcOWZHDJW2j/UNAwueMgxrNDvX2q0I7+l/' - 'gEd6pwNicjBhvnMsGPac9XwP2mozWkY5W46BwL0iKatsd54bCnWJJMfgC/EMiPoj' - 'KuZvPZ1veUZ0dWT3Eu9OJjOfYoraxjGYWXcNEEW60VDZjF12odsTcOz3pj+5FeGq' - 'PsjXpwKBgQDUBU3Acz6LU5LfJm1RQfrE+fJJa73H9FO+lIPCdgqTxMtocMfRj//r' - 'LdjtGorpS2Oa/UT7nj/R38HeKbKuwb/BauP5JB0871Un+KzxdlBqmdThyztDX1v4' - 'CGomrny6faf7V7zUnSgY8LjtfcEdlNzlVLIym/CKq7RaZMxBPftwIQKBgAIwRu3x' - 'djpuOi3PXcUh6YRE03Bd09R7VcVHrU/N72WZq+PUYPskhjbBi/HgSrZRG0ejtBqt' - '9kj5niFurTrkNY3oXVzaGoftNhE8as/bhOVEgn3sf69202XFLsnigBEpQ1mAJk5r' - 'WkqrhTOfCB8KTIR0dBTNv9VyMR/cwhkMgqXzAoGAGuwiOIO+mR+emZDt96EQkiL5' - 'XhIayQvEUfdlO+eAUWhivLd0vmBDqYWwN+ufiKAhwTLpsyklDeVvBK3LNxZkswmB' - '0jbcVOU9dMQbs9yVlK7EGlCm+DcyJU7OpVOuGdj5N6ZxJxLHk7p/fZoN85RZYLOb' - 'D+DO8nFRiUmqOp3t2VM=' + 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDaMmnx2AArLlxL' + 'MMTgP5pRspmxCgyEhYjYgWUT4A7QYIEyKDmrHHYggA9UhxKLl+M4u1Mee4hljD6z' + 'Tqp5vxAgpG+RlojCcDcvPlRSvGCH3qx7N1cIJIbsWd0gWyRxP7MbTQkv589F2U+O' + '3VWDZveSd6jloAowg/I5PNxjn3RRNz6W5DceGBKI0XeflhCHbh3eRLZg5ShJdDXf' + '5hGWPE18GBdtX4Lv+A7yYXGmRp+GaCQgY15aWpP2gAhFr6A7HXe48CD4lv/yU9X1' + 'sZoWoa/G8EynfFQBKXNgeIOe1wHkyI49FboGggYjmoMVJhFkGTL1ysTtYBiCq0+2' + 'DbXO/HAXAgMBAAECggEAfSrsYaKyPhMjOLLqTWXPBcy5o7iLA76CiQh5TlR6ywiB' + 'NJ+krUbvcKdlo+y0M8XWv+Wdwd/Fl9NC6KNY4ew7uS37Hn5HR5sN3RkZUDjl+ys+' + 'sJRHZdFmYNEQK459MkYDXcbsXUHSQlRt8huAAZggrzHbfpY3Iiue2TzThIalOCy0' + 'KxnnWsrkYvp2JlVBt5TzTqg/VmHH/J7/81GZLkbSKKX/8fjWlXlYaiY5fSar38dg' + 'FmoKdyrMuSLoUV2ZfKSPPyye9dRHjRLwH5rQX8s37nj09J7Z2n2HQfHgcIk6wv0L' + 'IJCKaqqoTwo9DgFTPyrf4yHHXETJrEiU0f0QKCjUIQKBgQD6aLu9BHOy1gl6tuEK' + '1p4Ws5H+fwN+3sXIU37khXsfaibLqB/TOvUZaOamHlHSww+Avy5VEYA1SuS5lm4K' + 'vfmJjrNCl0IUHgP237NtO9OavG3ahVoTXr90gnpvxwfNHZCsSHy7Dn+sQrNYEIc1' + 'LwW9cc+9e+dpxNnktlErSyyyEQKBgQDfEZCcOWZHDJW2j/UNAwueMgxrNDvX2q0I' + '7+l/gEd6pwNicjBhvnMsGPac9XwP2mozWkY5W46BwL0iKatsd54bCnWJJMfgC/EM' + 'iPojKuZvPZ1veUZ0dWT3Eu9OJjOfYoraxjGYWXcNEEW60VDZjF12odsTcOz3pj+5' + 'FeGqPsjXpwKBgQDUBU3Acz6LU5LfJm1RQfrE+fJJa73H9FO+lIPCdgqTxMtocMfR' + 'j//rLdjtGorpS2Oa/UT7nj/R38HeKbKuwb/BauP5JB0871Un+KzxdlBqmdThyztD' + 'X1v4CGomrny6faf7V7zUnSgY8LjtfcEdlNzlVLIym/CKq7RaZMxBPftwIQKBgAIw' + 'Ru3xdjpuOi3PXcUh6YRE03Bd09R7VcVHrU/N72WZq+PUYPskhjbBi/HgSrZRG0ej' + 'tBqt9kj5niFurTrkNY3oXVzaGoftNhE8as/bhOVEgn3sf69202XFLsnigBEpQ1mA' + 'Jk5rWkqrhTOfCB8KTIR0dBTNv9VyMR/cwhkMgqXzAoGAGuwiOIO+mR+emZDt96EQ' + 'kiL5XhIayQvEUfdlO+eAUWhivLd0vmBDqYWwN+ufiKAhwTLpsyklDeVvBK3LNxZk' + 'swmB0jbcVOU9dMQbs9yVlK7EGlCm+DcyJU7OpVOuGdj5N6ZxJxLHk7p/fZoN85RZ' + 'YLObD+DO8nFRiUmqOp3t2VM=' '-----END PRIVATE KEY-----' == =/ k=key:rsa From 22e5bb0366e50822e7ac427cbae0d36aa20480e6 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 16 Jul 2018 12:28:23 -0400 Subject: [PATCH 90/95] uses pkcs8 private keys for %eyre cert installation --- app/acme.hoon | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 0c05e5dca..b549ce2d1 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1510,8 +1510,7 @@ ^+ this ~| %install-effect-fail ?> ?=(^ liv) - :: XX use pkcs8 - =/ key=wain (ring:en:pem:pkcs1 key.u.liv) + =/ key=wain (ring:en:pem:pkcs8 key.u.liv) (emit %rule /install %cert `[key `wain`cer.u.liv]) :: +get-authz: get next ACME service domain authorization object :: @@ -2021,7 +2020,9 @@ 'n5Z5MqkYhlMI3J1tPRTp1nEt9fyGspBOO05gi148Qasp+3N+svqKomoQglNoAxU=' '-----END CERTIFICATE-----' == - (emit %rule /install %cert `[key cert]) + =/ k=key:rsa (need (ring:de:pem:pkcs1 key)) + =/ k8=wain (ring:en:pem:pkcs8 k) + (emit %rule /install %cert `[k8 cert]) :: +poke-path: for debugging :: ++ poke-path From 243c0a9a1015971aedf4aad931254c00b1d452fe Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 16 Jul 2018 17:11:14 -0400 Subject: [PATCH 91/95] ignores our own route updates in :dns --- app/dns.hoon | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/dns.hoon b/app/dns.hoon index 2273db40c..c741125d2 100644 --- a/app/dns.hoon +++ b/app/dns.hoon @@ -298,6 +298,9 @@ ++ rove |= [wir=wire p=ship q=lane:ames] ^- (quip move _this) + :: XX move to %ames + ?: =(our.bow p) + [~ this] ?. =(our.bow (sein:title p)) :: XX check will ~& [%rove-false p] [~ this] From 7aada841f417fa8d814541ce5319d5eff924dc3b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 16 Jul 2018 19:15:15 -0400 Subject: [PATCH 92/95] fix typo in error message --- app/acme.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/acme.hoon b/app/acme.hoon index b549ce2d1..6b4fe1eda 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1567,7 +1567,7 @@ :: ++ finalize-trial ^+ this - ~| %test-trial-effect-fail + ~| %finalize-trial-effect-fail ?. ?=(^ reg.act) ~|(%no-account !!) ?. ?=(^ rod) ~|(%no-active-order !!) ?. ?=(^ active.aut.u.rod) ~|(%no-active-authz !!) From 05050a09ffd31e7cc447df5b4f25962eaad18f57 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 16 Jul 2018 17:13:24 -0400 Subject: [PATCH 93/95] retry failed dns bindings in +hear:tell --- app/dns.hoon | 1 + 1 file changed, 1 insertion(+) diff --git a/app/dns.hoon b/app/dns.hoon index c741125d2..89c377d36 100644 --- a/app/dns.hoon +++ b/app/dns.hoon @@ -424,6 +424,7 @@ [%direct %if u.adr] ?. ?| ?=(~ rel) !=(tar tar.u.rel) + !bon.u.rel == this =. rel `[wen=now.bow adr bon=| try=0 tar] From ffe7970d745a8e3f9b50d48fa6a90e8725513f1b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 18 Jul 2018 17:24:08 -0400 Subject: [PATCH 94/95] retry failed domain validation token verification --- app/acme.hoon | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/acme.hoon b/app/acme.hoon index 6b4fe1eda..a30156aa5 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1800,9 +1800,9 @@ |= [wir=wire rep=httr] ^+ this ?. =(200 p.rep) - :: XX retry immediately? backoff? + :: XX count retries, backoff ~& [%test-trial-fail wir rep] - this + (retry:effect /test-trial (add now.bow ~m10)) ?> ?=(^ rod) ?> ?=(^ active.aut.u.rod) :: XX check content type and response body @@ -1844,6 +1844,7 @@ ~&(unknown-retry+wir this) :: XX do the needful [%directory ~] directory:effect + [%test-trial ~] test-trial:effect == -- :: +sigh-tang: handle http request failure From 4db7e486edc2f3639fd7e99b40723852a512139c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 19 Jul 2018 14:05:12 -0400 Subject: [PATCH 95/95] stub out :acme +sigh-recoverable-error rate-limit callback, print httr in mark --- app/acme.hoon | 8 ++++++++ mar/recoverable-error.hoon | 1 + 2 files changed, 9 insertions(+) diff --git a/app/acme.hoon b/app/acme.hoon index a30156aa5..7cec94e60 100644 --- a/app/acme.hoon +++ b/app/acme.hoon @@ -1855,6 +1855,14 @@ ~& [%sigh-tang wir] :: XX take evasive action [((slog saw) ~) this] +:: +sigh-recoverable-error: handle http rate-limit response +:: +++ sigh-recoverable-error + |= [wir=wire %429 %rate-limit lim=(unit @da)] + ^- (quip move _this) + ~& [%sigh-recoverable wir lim] + :: XX retry + [~ this] :: +sigh-httr: accept http response :: ++ sigh-httr diff --git a/mar/recoverable-error.hoon b/mar/recoverable-error.hoon index b0ce87138..0856593a3 100644 --- a/mar/recoverable-error.hoon +++ b/mar/recoverable-error.hoon @@ -15,6 +15,7 @@ ++ noun recoverable-error ++ httr |= a/^httr ^- recoverable-error + ~& [%recoverable-httr a] ~! a ?+ p.a ~|(non-recoverable+p.a !!) $429 :+ p.a %rate-limit