/*
*
* Copyright (c) 2013 - 2017 Lijun Liao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
*
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* THE AUTHOR LIJUN LIAO. LIJUN LIAO DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
* OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the XiPKI software without
* disclosing the source code of your own applications.
*
* For more information, please contact Lijun Liao at this
* address: lijun.liao@gmail.com
*/
package org.xipki.pki.ca.server.mgmt.api.x509;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;
import org.bouncycastle.util.encoders.Base64;
import org.xipki.commons.common.util.CompareUtil;
import org.xipki.commons.common.util.LogUtil;
import org.xipki.commons.common.util.ParamUtil;
import org.xipki.commons.security.CertRevocationInfo;
import org.xipki.commons.security.HashAlgoType;
import org.xipki.commons.security.KeyUsage;
import org.xipki.commons.security.util.X509Util;
import org.xipki.pki.ca.api.NameId;
import org.xipki.pki.ca.server.mgmt.api.CaEntry;
import org.xipki.pki.ca.server.mgmt.api.CaMgmtException;
/**
* @author Lijun Liao
* @since 2.0.0
*/
public class X509CaEntry extends CaEntry {
private List<String> crlUris;
private List<String> deltaCrlUris;
private List<String> ocspUris;
private List<String> cacertUris;
private X509Certificate cert;
private String crlSignerName;
private int serialNoBitLen;
private long nextCrlNumber;
private int numCrls;
private CertRevocationInfo revocationInfo;
private String subject;
private String hexSha1OfCert;
public X509CaEntry(final NameId nameId, final int serialNoBitLen,
final long nextCrlNumber, final String signerType, final String signerConf,
final X509CaUris caUris, final int numCrls, final int expirationPeriod)
throws CaMgmtException {
super(nameId, signerType, signerConf, expirationPeriod);
init(serialNoBitLen, nextCrlNumber, caUris, numCrls);
}
private void init(final int serialNoBitLen, final long nextCrlNumber, final X509CaUris caUris,
final int numCrls) throws CaMgmtException {
this.numCrls = ParamUtil.requireMin("numCrls", numCrls, 1);
this.serialNoBitLen = ParamUtil.requireRange("serialNoBitLen", serialNoBitLen, 63, 159);
this.nextCrlNumber = ParamUtil.requireMin("nextCrlNumber", nextCrlNumber, 1);
this.cacertUris = caUris.getCacertUris();
this.ocspUris = caUris.getOcspUris();
this.crlUris = caUris.getCrlUris();
this.deltaCrlUris = caUris.getDeltaCrlUris();
}
public void setCertificate(final X509Certificate certificate) throws CaMgmtException {
if (certificate == null) {
this.cert = null;
this.subject = null;
this.hexSha1OfCert = null;
} else {
if (!X509Util.hasKeyusage(certificate, KeyUsage.keyCertSign)) {
throw new CaMgmtException("CA certificate does not have keyusage keyCertSign");
}
this.cert = certificate;
this.subject = X509Util.getRfc4519Name(certificate.getSubjectX500Principal());
byte[] encodedCert;
try {
encodedCert = certificate.getEncoded();
} catch (CertificateEncodingException ex) {
throw new CaMgmtException("could not encoded certificate", ex);
}
this.hexSha1OfCert = HashAlgoType.SHA1.hexHash(encodedCert);
}
}
public int getSerialNoBitLen() {
return serialNoBitLen;
}
public void setSerialNoBitLen(final int serialNoBitLen) {
this.serialNoBitLen = ParamUtil.requireMin("serialNoBitLen", serialNoBitLen, 63);
}
public long getNextCrlNumber() {
return nextCrlNumber;
}
public void setNextCrlNumber(final long crlNumber) {
this.nextCrlNumber = crlNumber;
}
public List<String> getCrlUris() {
return crlUris;
}
public String getCrlUrisAsString() {
return toString(crlUris);
}
public List<String> getDeltaCrlUris() {
return deltaCrlUris;
}
public String getDeltaCrlUrisAsString() {
return toString(deltaCrlUris);
}
public List<String> getOcspUris() {
return ocspUris;
}
public String getOcspUrisAsString() {
return toString(ocspUris);
}
public List<String> getCacertUris() {
return cacertUris;
}
public String getCacertUrisAsString() {
return toString(cacertUris);
}
public X509Certificate getCertificate() {
return cert;
}
public int getNumCrls() {
return numCrls;
}
public String getCrlSignerName() {
return crlSignerName;
}
public void setCrlSignerName(final String crlSignerName) {
this.crlSignerName = (crlSignerName == null) ? null : crlSignerName.toUpperCase();
}
public String toString(final boolean verbose, final boolean ignoreSensitiveInfo) {
StringBuilder sb = new StringBuilder(1000);
sb.append(super.toString(verbose, ignoreSensitiveInfo));
if (sb.charAt(sb.length() - 1) != '\n') {
sb.append('\n');
}
sb.append("serialNoBitLen: ").append(serialNoBitLen).append('\n');
sb.append("nextCrlNumber: ").append(nextCrlNumber).append('\n');
sb.append("deltaCrlUris: ").append(getDeltaCrlUrisAsString()).append('\n');
sb.append("crlUris: ").append(getCrlUrisAsString()).append('\n');
sb.append("ocspUris: ").append(getOcspUrisAsString()).append('\n');
sb.append("caCertUris: ").append(getCacertUrisAsString()).append('\n');
sb.append("cert: ").append("\n");
if (cert == null) {
sb.append("\tnull").append("\n");
} else {
sb.append("\tissuer: ").append(
X509Util.getRfc4519Name(cert.getIssuerX500Principal())).append("\n");
sb.append("\tserialNumber: ").append(LogUtil.formatCsn(cert.getSerialNumber()))
.append("\n");
sb.append("\tsubject: ").append(subject).append("\n");
sb.append("\tnotBefore: ").append(cert.getNotBefore()).append("\n");
sb.append("\tnotAfter: ").append(cert.getNotAfter()).append("\n");
if (verbose) {
String b64EncodedCert = null;
try {
b64EncodedCert = Base64.toBase64String(cert.getEncoded());
} catch (CertificateEncodingException ex) {
b64EncodedCert = "ERROR, could not encode the certificate";
}
sb.append("\tencoded: ").append(b64EncodedCert).append("\n");
}
}
sb.append("crlSignerName: ").append(crlSignerName).append('\n');
sb.append("revocation: ");
sb.append(revocationInfo == null ? "not revoked" : "revoked");
sb.append("\n");
if (revocationInfo != null) {
sb.append("\treason: ").append(revocationInfo.getReason().getDescription())
.append("\n");
sb.append("\trevoked at ").append(revocationInfo.getRevocationTime()).append("\n");
}
return sb.toString();
} // method toString
public CertRevocationInfo getRevocationInfo() {
return revocationInfo;
}
public void setRevocationInfo(final CertRevocationInfo revocationInfo) {
this.revocationInfo = revocationInfo;
}
public Date getCrlBaseTime() {
return (cert == null) ? null : cert.getNotBefore();
}
public String getSubject() {
return subject;
}
public String getHexSha1OfCert() {
return hexSha1OfCert;
}
@Override
public void setExtraControl(final String extraControl) {
super.setExtraControl(extraControl);
}
@Override
public boolean equals(Object obj) {
return equals(obj, false);
}
public boolean equals(Object obj, boolean ignoreDynamicFields) {
if (! (obj instanceof X509CaEntry)) {
return false;
}
if (!super.equals(obj)) {
return false;
}
X509CaEntry objB = (X509CaEntry) obj;
if (!ignoreDynamicFields) {
if (nextCrlNumber != objB.nextCrlNumber) {
return false;
}
}
if (!CompareUtil.equalsObject(crlUris, objB.crlUris)) {
return false;
}
if (!CompareUtil.equalsObject(deltaCrlUris, objB.deltaCrlUris)) {
return false;
}
if (!CompareUtil.equalsObject(ocspUris, objB.ocspUris)) {
return false;
}
if (!CompareUtil.equalsObject(cacertUris, objB.cacertUris)) {
return false;
}
if (!CompareUtil.equalsObject(cert, objB.cert)) {
return false;
}
if (!CompareUtil.equalsObject(crlSignerName, objB.crlSignerName)) {
return false;
}
if (serialNoBitLen != objB.serialNoBitLen) {
return false;
}
if (numCrls != objB.numCrls) {
return false;
}
if (!CompareUtil.equalsObject(revocationInfo, objB.revocationInfo)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return getIdent().hashCode();
}
}