Letsencrypt Auth-Servlet
Java servlet that can run independent from the letsencrypt client and response with the challenge solution
to the simplehttp challenge. It only require access to the users private key. Use full for example if the client
run on another machine or other the server should not be interfered. ACME is the protocol used by
Letsencrypt
public final class WellKnownAcmeChallenge implements Servlet,ServletContainerInitializer {
private ServletConfig sc = null;
private final String name = "WellKnownAcmeChallenge";
@Override public void destroy() { this.sc = null; }
@Override public ServletConfig getServletConfig() { return this.sc; }
@Override public String getServletInfo() { return this.name; }
@Override public void init(final ServletConfig v) throws ServletException { this.sc = v; }
@Override public void service(final ServletRequest req, final ServletResponse res) throws ServletException, IOException {
http((HttpServletRequest)req, (HttpServletResponse)res);
}
@Override public void onStartup(final Set<Class<?>> $, final ServletContext sc) throws ServletException {
sc.addServlet(this.getClass().getSimpleName(), this).addMapping("/.well-known/acme-challenge/*");
}
private static String base64UrlEncode(final byte[] v) { return Base64.getUrlEncoder().encodeToString(v).replaceAll("=*$", ""); }
public void http(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
final PrivateKey pk = MyX509Provider.getKeyManager().getPrivateKey("letsencryptUserAlias");
final String token = req.getPathInfo().replaceAll(".*/", "");
final String header = "{\"alg\":\"RS256\"}";
final String prot = base64UrlEncode("{}".getBytes());
final String payload = base64UrlEncode(("{\"type\":\"simpleHttp\",\"token\":\""+token+"\",\"tls\":true}").getBytes());
try {
final Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(pk);
sig.update(prot.getBytes());
sig.update(".".getBytes());
sig.update(payload.getBytes());
final String signature = base64UrlEncode(sig.sign());
final String body = "{\"header\": "+header+", \"protected\": \""+prot+"\", \"payload\": \""+payload+"\", \"signature\": \""+signature+"\"}";
res.setContentType("application/jose+json");
res.getOutputStream().write(body.getBytes());
} catch(final Throwable t) {
t.printStackTrace(System.out);
res.setStatus(500);
}
}
}