Account extends AcmeJsonResource { public void changeKey(KeyPair newKeyPair) throws AcmeException { Objects.requireNonNull(newKeyPair, "newKeyPair"); if (Arrays.equals(getLogin().getKeyPair().getPrivate().getEncoded(), newKeyPair.getPrivate().getEncoded())) { throw new IllegalArgumentException("newKeyPair must actually be a new key pair"); } LOG.debug("key-change"); try (Connection conn = getSession().connect()) { URL keyChangeUrl = getSession().resourceUrl(Resource.KEY_CHANGE); JSONBuilder payloadClaim = new JSONBuilder(); payloadClaim.put("account", getLocation()); payloadClaim.putKey("oldKey", getLogin().getKeyPair().getPublic()); JSONBuilder jose = JoseUtils.createJoseRequest(keyChangeUrl, newKeyPair, payloadClaim, null, null); conn.sendSignedRequest(keyChangeUrl, jose, getLogin()); getLogin().setKeyPair(newKeyPair); } } protected  Account(Login login); @Nullable Boolean getTermsOfServiceAgreed(); List<URI> getContacts(); Status getStatus(); boolean hasExternalAccountBinding(); @Nullable String getKeyIdentifier(); Iterator<Order> getOrders(); OrderBuilder newOrder(); Authorization preAuthorizeDomain(String domain); Authorization preAuthorize(Identifier identifier); void changeKey(KeyPair newKeyPair); void deactivate(); EditableAccount modify();  }
@Test public void testChangeKey() throws Exception { final KeyPair oldKeyPair = TestUtils.createKeyPair(); final KeyPair newKeyPair = TestUtils.createDomainKeyPair(); final TestableConnectionProvider provider = new TestableConnectionProvider() { @Override public int sendSignedRequest(URL url, JSONBuilder payload, Login login) { try { assertThat(url, is(locationUrl)); assertThat(login, is(notNullValue())); assertThat(login.getKeyPair(), is(sameInstance(oldKeyPair))); JSON json = payload.toJSON(); String encodedHeader = json.get("protected").asString(); String encodedSignature = json.get("signature").asString(); String encodedPayload = json.get("payload").asString(); String serialized = CompactSerializer.serialize(encodedHeader, encodedPayload, encodedSignature); JsonWebSignature jws = new JsonWebSignature(); jws.setCompactSerialization(serialized); jws.setKey(newKeyPair.getPublic()); assertThat(jws.verifySignature(), is(true)); String decodedPayload = jws.getPayload(); StringBuilder expectedPayload = new StringBuilder(); expectedPayload.append('{'); expectedPayload.append("\"account\":\"").append(locationUrl).append("\","); expectedPayload.append("\"oldKey\":{"); expectedPayload.append("\"kty\":\"").append(TestUtils.KTY).append("\","); expectedPayload.append("\"e\":\"").append(TestUtils.E).append("\","); expectedPayload.append("\"n\":\"").append(TestUtils.N).append("\""); expectedPayload.append("}}"); assertThat(decodedPayload, sameJSONAs(expectedPayload.toString())); } catch (JoseException ex) { fail("decoding inner payload failed"); } return HttpURLConnection.HTTP_OK; } @Override public URL getLocation() { return resourceUrl; } }; provider.putTestResource(Resource.KEY_CHANGE, locationUrl); Session session = TestUtils.session(provider); Login login = new Login(locationUrl, oldKeyPair, session); assertThat(login.getKeyPair(), is(sameInstance(oldKeyPair))); Account account = new Account(login); account.changeKey(newKeyPair); assertThat(login.getKeyPair(), is(sameInstance(newKeyPair))); }
@Test(expected = IllegalArgumentException.class) public void testChangeSameKey() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider(); Login login = provider.createLogin(); Account account = new Account(login); account.changeKey(login.getKeyPair()); provider.close(); }