001/*
002 * acme4j - Java ACME client
003 *
004 * Copyright (C) 2018 Richard "Shred" K├Ârber
005 *   http://acme4j.shredzone.org
006 *
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
013 */
014package org.shredzone.acme4j.challenge;
015
016import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
017
018import java.io.IOException;
019import java.security.KeyPair;
020import java.security.cert.X509Certificate;
021
022import org.shredzone.acme4j.Identifier;
023import org.shredzone.acme4j.Login;
024import org.shredzone.acme4j.toolbox.JSON;
025import org.shredzone.acme4j.util.CertificateUtils;
026
027/**
028 * Implements the {@value TYPE} challenge. It requires a specific certificate that can be
029 * retrieved from the domain via HTTPS request. See the acme4j documentation for a
030 * detailed explanation.
031 *
032 * @since 2.1
033 */
034public class TlsAlpn01Challenge extends TokenChallenge {
035    private static final long serialVersionUID = -5590351078176091228L;
036
037    /**
038     * Challenge type name: {@value}
039     */
040    public static final String TYPE = "tls-alpn-01";
041
042    /**
043     * OID of the {@code acmeValidation} extension.
044     */
045    public static final String ACME_VALIDATION_OID = "1.3.6.1.5.5.7.1.31";
046
047    /**
048     * {@code acme-tls/1} protocol.
049     */
050    public static final String ACME_TLS_1_PROTOCOL = "acme-tls/1";
051
052    /**
053     * Creates a new generic {@link TlsAlpn01Challenge} object.
054     *
055     * @param login
056     *            {@link Login} the resource is bound with
057     * @param data
058     *            {@link JSON} challenge data
059     */
060    public TlsAlpn01Challenge(Login login, JSON data) {
061        super(login, data);
062    }
063
064    /**
065     * Returns the value that is to be used as {@code acmeValidation} extension in
066     * the test certificate.
067     */
068    public byte[] getAcmeValidation() {
069        return sha256hash(getAuthorization());
070    }
071
072    /**
073     * Creates a self-signed {@link X509Certificate} for this challenge. The certificate
074     * is valid for 7 days.
075     *
076     * @param keypair
077     *         A domain {@link KeyPair} to be used for the challenge
078     * @param id
079     *         The {@link Identifier} that is to be validated
080     * @return Created certificate
081     * @since 3.0.0
082     */
083    public X509Certificate createCertificate(KeyPair keypair, Identifier id) {
084        try {
085            return CertificateUtils.createTlsAlpn01Certificate(keypair, id, getAcmeValidation());
086        } catch (IOException ex) {
087            throw new IllegalArgumentException("Bad certificate parameters", ex);
088        }
089    }
090
091    @Override
092    protected boolean acceptable(String type) {
093        return TYPE.equals(type);
094    }
095
096}