{"action":"created","comment":{"url":"https://api.github.com/repos/letsencrypt/pebble/pulls/comments/209343568","pull_request_review_id":145343111,"id":209343568,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwOTM0MzU2OA==","diff_hunk":"@@ -712,6 +731,109 @@ func (wfe *WebFrontEndImpl) UpdateAccount(\n \t}\n }\n \n+func (wfe *WebFrontEndImpl) verifyKeyRollover(\n+\tinnerPayload []byte,\n+\texistingAcct *core.Account,\n+\tnewKey *jose.JSONWebKey,\n+\trequest *http.Request) *acme.ProblemDetails {\n+\tvar innerContent struct {\n+\t\tAccount string\n+\t\tOldKey  jose.JSONWebKey\n+\t}\n+\terr := json.Unmarshal([]byte(innerPayload), &innerContent)\n+\tif err != nil {\n+\t\treturn acme.MalformedProblem(\"Error unmarshaling key roll-over inner JWS body\")\n+\t}\n+\n+\t// Check account ID\n+\tprefix := wfe.relativeEndpoint(request, acctPath)\n+\tif !strings.HasPrefix(innerContent.Account, prefix) {\n+\t\treturn acme.MalformedProblem(fmt.Sprintf(\"Key ID (account) in inner JWS body missing expected URL prefix (provided account value: %q)\", innerContent.Account))\n+\t}\n+\taccountID := strings.TrimPrefix(innerContent.Account, prefix)\n+\tif accountID == \"\" {\n+\t\treturn acme.MalformedProblem(fmt.Sprintf(\"No key ID (account) in inner JWS body (provided account value: %q)\", innerContent.Account))\n+\t}\n+\tif accountID != existingAcct.ID {\n+\t\treturn acme.MalformedProblem(fmt.Sprintf(\"Key roll-over inner JWS body contains wrong account ID (provided account value: %q)\", innerContent.Account))\n+\t}\n+\n+\t// Verify inner key\n+\tif !keyDigestEquals(innerContent.OldKey, *existingAcct.Key) {\n+\t\treturn acme.MalformedProblem(\"Key roll-over inner JWS body JSON contains wrong old key\")\n+\t}\n+\n+\t// Check for same key\n+\tif keyDigestEquals(innerContent.OldKey, newKey) {\n+\t\treturn acme.MalformedProblem(\"New and old key are identical\")\n+\t}\n+\n+\treturn nil\n+}\n+\n+func (wfe *WebFrontEndImpl) KeyRollover(\n+\tctx context.Context,\n+\tlogEvent *requestEvent,\n+\tresponse http.ResponseWriter,\n+\trequest *http.Request) {\n+\t// Extract and parse outer JWS, and retrieve account\n+\tbody, outerHeaderURL, key, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)\n+\tif prob != nil {\n+\t\twfe.sendError(prob, response)\n+\t\treturn\n+\t}\n+\n+\texistingAcct, prob := wfe.getAcctByKey(key)\n+\tif prob != nil {\n+\t\twfe.sendError(prob, response)\n+\t\treturn\n+\t}\n+\n+\t// Extract inner JWS\n+\tparsedInnerJWS, err := wfe.parseJWS(string(body))\n+\tif err != nil {\n+\t\twfe.sendError(acme.MalformedProblem(err.Error()), response)\n+\t\treturn\n+\t}\n+\n+\tnewPubKey, prob := wfe.extractJWK(request, parsedInnerJWS)\n+\tif prob != nil {\n+\t\twfe.sendError(prob, response)\n+\t\treturn\n+\t}\n+\n+\tinnerPayload, innerHeaderURL, prob := wfe.verifyJWSLight(newPubKey, parsedInnerJWS, \"Inner \")\n+\tif prob != nil {\n+\t\twfe.sendError(prob, response)\n+\t\treturn\n+\t}\n+\n+\tif innerHeaderURL != outerHeaderURL {\n+\t\twfe.sendError(acme.MalformedProblem(\"JWS header parameter 'url' differs for inner and outer JWS.\"), response)","path":"wfe/wfe.go","position":226,"original_position":226,"commit_id":"ff6afb2a347304c6a97714a1fea46bd634c99005","original_commit_id":"ff6afb2a347304c6a97714a1fea46bd634c99005","user":{"login":"cpu","id":292650,"node_id":"MDQ6VXNlcjI5MjY1MA==","avatar_url":"https://avatars1.githubusercontent.com/u/292650?v=4","gravatar_id":"","url":"https://api.github.com/users/cpu","html_url":"https://github.com/cpu","followers_url":"https://api.github.com/users/cpu/followers","following_url":"https://api.github.com/users/cpu/following{/other_user}","gists_url":"https://api.github.com/users/cpu/gists{/gist_id}","starred_url":"https://api.github.com/users/cpu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpu/subscriptions","organizations_url":"https://api.github.com/users/cpu/orgs","repos_url":"https://api.github.com/users/cpu/repos","events_url":"https://api.github.com/users/cpu/events{/privacy}","received_events_url":"https://api.github.com/users/cpu/received_events","type":"User","site_admin":false},"body":"I think you missed a `return` after this `wfe.sendError` and control flow will continue when the inner header and outer header don't match","created_at":"2018-08-10T18:12:09Z","updated_at":"2018-08-10T18:12:55Z","html_url":"https://github.com/letsencrypt/pebble/pull/151#discussion_r209343568","pull_request_url":"https://api.github.com/repos/letsencrypt/pebble/pulls/151","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/letsencrypt/pebble/pulls/comments/209343568"},"html":{"href":"https://github.com/letsencrypt/pebble/pull/151#discussion_r209343568"},"pull_request":{"href":"https://api.github.com/repos/letsencrypt/pebble/pulls/151"}}},"pull_request":{"url":"https://api.github.com/repos/letsencrypt/pebble/pulls/151","id":204506510,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA0NTA2NTEw","html_url":"https://github.com/letsencrypt/pebble/pull/151","diff_url":"https://github.com/letsencrypt/pebble/pull/151.diff","patch_url":"https://github.com/letsencrypt/pebble/pull/151.patch","issue_url":"https://api.github.com/repos/letsencrypt/pebble/issues/151","number":151,"state":"open","locked":false,"title":"Adding account key roll-over","user":{"login":"felixfontein","id":5781356,"node_id":"MDQ6VXNlcjU3ODEzNTY=","avatar_url":"https://avatars0.githubusercontent.com/u/5781356?v=4","gravatar_id":"","url":"https://api.github.com/users/felixfontein","html_url":"https://github.com/felixfontein","followers_url":"https://api.github.com/users/felixfontein/followers","following_url":"https://api.github.com/users/felixfontein/following{/other_user}","gists_url":"https://api.github.com/users/felixfontein/gists{/gist_id}","starred_url":"https://api.github.com/users/felixfontein/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/felixfontein/subscriptions","organizations_url":"https://api.github.com/users/felixfontein/orgs","repos_url":"https://api.github.com/users/felixfontein/repos","events_url":"https://api.github.com/users/felixfontein/events{/privacy}","received_events_url":"https://api.github.com/users/felixfontein/received_events","type":"User","site_admin":false},"body":"Adds [ACME-13](https://tools.ietf.org/html/draft-ietf-acme-acme-13#section-7.3.6) account key roll-over to Pebble.\r\n\r\nFixes #150.","created_at":"2018-07-27T18:27:11Z","updated_at":"2018-08-10T18:12:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ddfa19f6c45c4d720874fbe312cd507425937ece","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/letsencrypt/pebble/pulls/151/commits","review_comments_url":"https://api.github.com/repos/letsencrypt/pebble/pulls/151/comments","review_comment_url":"https://api.github.com/repos/letsencrypt/pebble/pulls/comments{/number}","comments_url":"https://api.github.com/repos/letsencrypt/pebble/issues/151/comments","statuses_url":"https://api.github.com/repos/letsencrypt/pebble/statuses/ff6afb2a347304c6a97714a1fea46bd634c99005","head":{"label":"felixfontein:add-key-rollover","ref":"add-key-rollover","sha":"ff6afb2a347304c6a97714a1fea46bd634c99005","user":{"login":"felixfontein","id":5781356,"node_id":"MDQ6VXNlcjU3ODEzNTY=","avatar_url":"https://avatars0.githubusercontent.com/u/5781356?v=4","gravatar_id":"","url":"https://api.github.com/users/felixfontein","html_url":"https://github.com/felixfontein","followers_url":"https://api.github.com/users/felixfontein/followers","following_url":"https://api.github.com/users/felixfontein/following{/other_user}","gists_url":"https://api.github.com/users/felixfontein/gists{/gist_id}","starred_url":"https://api.github.com/users/felixfontein/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/felixfontein/subscriptions","organizations_url":"https://api.github.com/users/felixfontein/orgs","repos_url":"https://api.github.com/users/felixfontein/repos","events_url":"https://api.github.com/users/felixfontein/events{/privacy}","received_events_url":"https://api.github.com/users/felixfontein/received_events","type":"User","site_admin":false},"repo":{"id":138690759,"node_id":"MDEwOlJlcG9zaXRvcnkxMzg2OTA3NTk=","name":"pebble","full_name":"felixfontein/pebble","owner":{"login":"felixfontein","id":5781356,"node_id":"MDQ6VXNlcjU3ODEzNTY=","avatar_url":"https://avatars0.githubusercontent.com/u/5781356?v=4","gravatar_id":"","url":"https://api.github.com/users/felixfontein","html_url":"https://github.com/felixfontein","followers_url":"https://api.github.com/users/felixfontein/followers","following_url":"https://api.github.com/users/felixfontein/following{/other_user}","gists_url":"https://api.github.com/users/felixfontein/gists{/gist_id}","starred_url":"https://api.github.com/users/felixfontein/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/felixfontein/subscriptions","organizations_url":"https://api.github.com/users/felixfontein/orgs","repos_url":"https://api.github.com/users/felixfontein/repos","events_url":"https://api.github.com/users/felixfontein/events{/privacy}","received_events_url":"https://api.github.com/users/felixfontein/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/felixfontein/pebble","description":"A miniature version of Boulder, Pebble is a small ACME test server not suited for a production CA","fork":true,"url":"https://api.github.com/repos/felixfontein/pebble","forks_url":"https://api.github.com/repos/felixfontein/pebble/forks","keys_url":"https://api.github.com/repos/felixfontein/pebble/keys{/key_id}","collaborators_url":"https://api.github.com/repos/felixfontein/pebble/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/felixfontein/pebble/teams","hooks_url":"https://api.github.com/repos/felixfontein/pebble/hooks","issue_events_url":"https://api.github.com/repos/felixfontein/pebble/issues/events{/number}","events_url":"https://api.github.com/repos/felixfontein/pebble/events","assignees_url":"https://api.github.com/repos/felixfontein/pebble/assignees{/user}","branches_url":"https://api.github.com/repos/felixfontein/pebble/branches{/branch}","tags_url":"https://api.github.com/repos/felixfontein/pebble/tags","blobs_url":"https://api.github.com/repos/felixfontein/pebble/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/felixfontein/pebble/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/felixfontein/pebble/git/refs{/sha}","trees_url":"https://api.github.com/repos/felixfontein/pebble/git/trees{/sha}","statuses_url":"https://api.github.com/repos/felixfontein/pebble/statuses/{sha}","languages_url":"https://api.github.com/repos/felixfontein/pebble/languages","stargazers_url":"https://api.github.com/repos/felixfontein/pebble/stargazers","contributors_url":"https://api.github.com/repos/felixfontein/pebble/contributors","subscribers_url":"https://api.github.com/repos/felixfontein/pebble/subscribers","subscription_url":"https://api.github.com/repos/felixfontein/pebble/subscription","commits_url":"https://api.github.com/repos/felixfontein/pebble/commits{/sha}","git_commits_url":"https://api.github.com/repos/felixfontein/pebble/git/commits{/sha}","comments_url":"https://api.github.com/repos/felixfontein/pebble/comments{/number}","issue_comment_url":"https://api.github.com/repos/felixfontein/pebble/issues/comments{/number}","contents_url":"https://api.github.com/repos/felixfontein/pebble/contents/{+path}","compare_url":"https://api.github.com/repos/felixfontein/pebble/compare/{base}...{head}","merges_url":"https://api.github.com/repos/felixfontein/pebble/merges","archive_url":"https://api.github.com/repos/felixfontein/pebble/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/felixfontein/pebble/downloads","issues_url":"https://api.github.com/repos/felixfontein/pebble/issues{/number}","pulls_url":"https://api.github.com/repos/felixfontein/pebble/pulls{/number}","milestones_url":"https://api.github.com/repos/felixfontein/pebble/milestones{/number}","notifications_url":"https://api.github.com/repos/felixfontein/pebble/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/felixfontein/pebble/labels{/name}","releases_url":"https://api.github.com/repos/felixfontein/pebble/releases{/id}","deployments_url":"https://api.github.com/repos/felixfontein/pebble/deployments","created_at":"2018-06-26T05:52:11Z","updated_at":"2018-08-03T14:43:22Z","pushed_at":"2018-08-08T15:41:29Z","git_url":"git://github.com/felixfontein/pebble.git","ssh_url":"git@github.com:felixfontein/pebble.git","clone_url":"https://github.com/felixfontein/pebble.git","svn_url":"https://github.com/felixfontein/pebble","homepage":null,"size":476,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"mpl-2.0","name":"Mozilla Public License 2.0","spdx_id":"MPL-2.0","url":"https://api.github.com/licenses/mpl-2.0","node_id":"MDc6TGljZW5zZTE0"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"letsencrypt:master","ref":"master","sha":"99805214c7a327cbe2e520e6e9c4ce31612df1dc","user":{"login":"letsencrypt","id":9289019,"node_id":"MDEyOk9yZ2FuaXphdGlvbjkyODkwMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/9289019?v=4","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"repo":{"id":74700504,"node_id":"MDEwOlJlcG9zaXRvcnk3NDcwMDUwNA==","name":"pebble","full_name":"letsencrypt/pebble","owner":{"login":"letsencrypt","id":9289019,"node_id":"MDEyOk9yZ2FuaXphdGlvbjkyODkwMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/9289019?v=4","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/letsencrypt/pebble","description":"A miniature version of Boulder, Pebble is a small ACME test server not suited for a production CA","fork":false,"url":"https://api.github.com/repos/letsencrypt/pebble","forks_url":"https://api.github.com/repos/letsencrypt/pebble/forks","keys_url":"https://api.github.com/repos/letsencrypt/pebble/keys{/key_id}","collaborators_url":"https://api.github.com/repos/letsencrypt/pebble/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/letsencrypt/pebble/teams","hooks_url":"https://api.github.com/repos/letsencrypt/pebble/hooks","issue_events_url":"https://api.github.com/repos/letsencrypt/pebble/issues/events{/number}","events_url":"https://api.github.com/repos/letsencrypt/pebble/events","assignees_url":"https://api.github.com/repos/letsencrypt/pebble/assignees{/user}","branches_url":"https://api.github.com/repos/letsencrypt/pebble/branches{/branch}","tags_url":"https://api.github.com/repos/letsencrypt/pebble/tags","blobs_url":"https://api.github.com/repos/letsencrypt/pebble/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/letsencrypt/pebble/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/letsencrypt/pebble/git/refs{/sha}","trees_url":"https://api.github.com/repos/letsencrypt/pebble/git/trees{/sha}","statuses_url":"https://api.github.com/repos/letsencrypt/pebble/statuses/{sha}","languages_url":"https://api.github.com/repos/letsencrypt/pebble/languages","stargazers_url":"https://api.github.com/repos/letsencrypt/pebble/stargazers","contributors_url":"https://api.github.com/repos/letsencrypt/pebble/contributors","subscribers_url":"https://api.github.com/repos/letsencrypt/pebble/subscribers","subscription_url":"https://api.github.com/repos/letsencrypt/pebble/subscription","commits_url":"https://api.github.com/repos/letsencrypt/pebble/commits{/sha}","git_commits_url":"https://api.github.com/repos/letsencrypt/pebble/git/commits{/sha}","comments_url":"https://api.github.com/repos/letsencrypt/pebble/comments{/number}","issue_comment_url":"https://api.github.com/repos/letsencrypt/pebble/issues/comments{/number}","contents_url":"https://api.github.com/repos/letsencrypt/pebble/contents/{+path}","compare_url":"https://api.github.com/repos/letsencrypt/pebble/compare/{base}...{head}","merges_url":"https://api.github.com/repos/letsencrypt/pebble/merges","archive_url":"https://api.github.com/repos/letsencrypt/pebble/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/letsencrypt/pebble/downloads","issues_url":"https://api.github.com/repos/letsencrypt/pebble/issues{/number}","pulls_url":"https://api.github.com/repos/letsencrypt/pebble/pulls{/number}","milestones_url":"https://api.github.com/repos/letsencrypt/pebble/milestones{/number}","notifications_url":"https://api.github.com/repos/letsencrypt/pebble/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/letsencrypt/pebble/labels{/name}","releases_url":"https://api.github.com/repos/letsencrypt/pebble/releases{/id}","deployments_url":"https://api.github.com/repos/letsencrypt/pebble/deployments","created_at":"2016-11-24T19:37:28Z","updated_at":"2018-08-10T18:02:33Z","pushed_at":"2018-08-08T15:41:30Z","git_url":"git://github.com/letsencrypt/pebble.git","ssh_url":"git@github.com:letsencrypt/pebble.git","clone_url":"https://github.com/letsencrypt/pebble.git","svn_url":"https://github.com/letsencrypt/pebble","homepage":null,"size":443,"stargazers_count":93,"watchers_count":93,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":33,"mirror_url":null,"archived":false,"open_issues_count":9,"license":{"key":"mpl-2.0","name":"Mozilla Public License 2.0","spdx_id":"MPL-2.0","url":"https://api.github.com/licenses/mpl-2.0","node_id":"MDc6TGljZW5zZTE0"},"forks":33,"open_issues":9,"watchers":93,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/letsencrypt/pebble/pulls/151"},"html":{"href":"https://github.com/letsencrypt/pebble/pull/151"},"issue":{"href":"https://api.github.com/repos/letsencrypt/pebble/issues/151"},"comments":{"href":"https://api.github.com/repos/letsencrypt/pebble/issues/151/comments"},"review_comments":{"href":"https://api.github.com/repos/letsencrypt/pebble/pulls/151/comments"},"review_comment":{"href":"https://api.github.com/repos/letsencrypt/pebble/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/letsencrypt/pebble/pulls/151/commits"},"statuses":{"href":"https://api.github.com/repos/letsencrypt/pebble/statuses/ff6afb2a347304c6a97714a1fea46bd634c99005"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"cpu"}}