8296901: Do not create unsigned certificate and CRL
Reviewed-by: mullan
This commit is contained in:
parent
7b3984cb5a
commit
ab6b7ef988
src/java.base/share/classes/sun/security
test/jdk/sun/security
ec/ed
pkcs/pkcs7
provider/X509Factory
rsa/pss
util/HostnameChecker
x509
@ -335,12 +335,11 @@ public final class CertAndKeyGen {
|
||||
}
|
||||
if (ext != null) info.setExtensions(ext);
|
||||
|
||||
cert = new X509CertImpl(info);
|
||||
if (signerFlag) {
|
||||
// use signer's private key to sign
|
||||
cert.sign(signerPrivateKey, sigAlg);
|
||||
cert = X509CertImpl.newSigned(info, signerPrivateKey, sigAlg);
|
||||
} else {
|
||||
cert.sign(privateKey, sigAlg);
|
||||
cert = X509CertImpl.newSigned(info, privateKey, sigAlg);
|
||||
}
|
||||
|
||||
return cert;
|
||||
|
@ -1536,8 +1536,8 @@ public final class Main {
|
||||
subjectPubKey,
|
||||
signerSubjectKeyId);
|
||||
info.setExtensions(ext);
|
||||
X509CertImpl cert = new X509CertImpl(info);
|
||||
cert.sign(privateKey, sigAlgName);
|
||||
X509CertImpl cert = X509CertImpl
|
||||
.newSigned(info, privateKey, sigAlgName);
|
||||
dumpCert(cert, out);
|
||||
for (Certificate ca: keyStore.getCertificateChain(alias)) {
|
||||
if (ca instanceof X509Certificate xca) {
|
||||
@ -1589,8 +1589,9 @@ public final class Main {
|
||||
badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate);
|
||||
}
|
||||
}
|
||||
X509CRLImpl crl = new X509CRLImpl(owner, firstDate, lastDate, badCerts);
|
||||
crl.sign(privateKey, sigAlgName);
|
||||
X509CRLImpl crl = X509CRLImpl.newSigned(
|
||||
new X509CRLImpl.TBSCertList(owner, firstDate, lastDate, badCerts),
|
||||
privateKey, sigAlgName);
|
||||
if (rfc) {
|
||||
out.println("-----BEGIN X509 CRL-----");
|
||||
out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal()));
|
||||
@ -3228,8 +3229,8 @@ public final class Main {
|
||||
null);
|
||||
certInfo.setExtensions(ext);
|
||||
// Sign the new certificate
|
||||
X509CertImpl newCert = new X509CertImpl(certInfo);
|
||||
newCert.sign(privKey, sigAlgName);
|
||||
X509CertImpl newCert = X509CertImpl.newSigned(
|
||||
certInfo, privKey, sigAlgName);
|
||||
|
||||
// Store the new certificate as a single-element certificate chain
|
||||
keyStore.setKeyEntry(alias, privKey,
|
||||
|
@ -26,7 +26,6 @@
|
||||
package sun.security.x509;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.cert.Certificate;
|
||||
@ -88,20 +87,262 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
private byte[] tbsCertList = null; // DER encoded "to-be-signed" CRL
|
||||
private AlgorithmId sigAlgId = null; // sig alg in CRL
|
||||
|
||||
// crl information
|
||||
private int version;
|
||||
private AlgorithmId infoSigAlgId; // sig alg in "to-be-signed" crl
|
||||
private X500Name issuer = null;
|
||||
private X500Principal issuerPrincipal = null;
|
||||
private Date thisUpdate = null;
|
||||
private Date nextUpdate = null;
|
||||
private final Map<X509IssuerSerial,X509CRLEntry> revokedMap =
|
||||
new TreeMap<>();
|
||||
private final List<X509CRLEntry> revokedList = new LinkedList<>();
|
||||
private CRLExtensions extensions = null;
|
||||
private static final boolean isExplicit = true;
|
||||
private TBSCertList info;
|
||||
|
||||
private boolean readOnly = false;
|
||||
// crl information
|
||||
public static class TBSCertList {
|
||||
private int version;
|
||||
private AlgorithmId infoSigAlgId; // sig alg in "to-be-signed" crl
|
||||
private X500Name issuer = null;
|
||||
private X500Principal issuerPrincipal = null;
|
||||
private Date thisUpdate = null;
|
||||
private Date nextUpdate = null;
|
||||
private final Map<X509IssuerSerial, X509CRLEntry> revokedMap =
|
||||
new TreeMap<>();
|
||||
private final List<X509CRLEntry> revokedList = new LinkedList<>();
|
||||
private CRLExtensions extensions = null;
|
||||
|
||||
/**
|
||||
* Initial TBSCertList constructor, no revoked certs, and no extensions.
|
||||
*
|
||||
* @param issuer the name of the CA issuing this CRL.
|
||||
* @param thisDate the Date of this issue.
|
||||
* @param nextDate the Date of the next CRL.
|
||||
*/
|
||||
public TBSCertList(X500Name issuer, Date thisDate, Date nextDate) {
|
||||
this.issuer = issuer;
|
||||
this.thisUpdate = thisDate;
|
||||
this.nextUpdate = nextDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* TBSCertList constructor, revoked certs, no extensions.
|
||||
*
|
||||
* @param issuer the name of the CA issuing this CRL.
|
||||
* @param thisDate the Date of this issue.
|
||||
* @param nextDate the Date of the next CRL.
|
||||
* @param badCerts the array of CRL entries.
|
||||
*
|
||||
* @exception CRLException on parsing/construction errors.
|
||||
*/
|
||||
public TBSCertList(X500Name issuer, Date thisDate, Date nextDate,
|
||||
X509CRLEntry[] badCerts)
|
||||
throws CRLException
|
||||
{
|
||||
this.issuer = issuer;
|
||||
this.thisUpdate = thisDate;
|
||||
this.nextUpdate = nextDate;
|
||||
if (badCerts != null) {
|
||||
X500Principal crlIssuer = getIssuerX500Principal();
|
||||
X500Principal badCertIssuer = crlIssuer;
|
||||
for (int i = 0; i < badCerts.length; i++) {
|
||||
X509CRLEntryImpl badCert = (X509CRLEntryImpl)badCerts[i];
|
||||
badCertIssuer = getCertIssuer(badCert, badCertIssuer);
|
||||
badCert.setCertificateIssuer(crlIssuer, badCertIssuer);
|
||||
X509IssuerSerial issuerSerial = new X509IssuerSerial
|
||||
(badCertIssuer, badCert.getSerialNumber());
|
||||
this.revokedMap.put(issuerSerial, badCert);
|
||||
this.revokedList.add(badCert);
|
||||
if (badCert.hasExtensions()) {
|
||||
this.version = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBSCertList constructor, revoked certs and extensions.
|
||||
*
|
||||
* @param issuer the name of the CA issuing this CRL.
|
||||
* @param thisDate the Date of this issue.
|
||||
* @param nextDate the Date of the next CRL.
|
||||
* @param badCerts the array of CRL entries.
|
||||
* @param crlExts the CRL extensions.
|
||||
*
|
||||
* @exception CRLException on parsing/construction errors.
|
||||
*/
|
||||
public TBSCertList(X500Name issuer, Date thisDate, Date nextDate,
|
||||
X509CRLEntry[] badCerts, CRLExtensions crlExts)
|
||||
throws CRLException
|
||||
{
|
||||
this(issuer, thisDate, nextDate, badCerts);
|
||||
if (crlExts != null) {
|
||||
this.extensions = crlExts;
|
||||
this.version = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs from the encoding.
|
||||
*/
|
||||
public TBSCertList(DerValue value) throws IOException, CRLException {
|
||||
|
||||
if (value.tag != DerValue.tag_Sequence)
|
||||
throw new CRLException("signed CRL fields invalid");
|
||||
|
||||
// parse the information
|
||||
DerInputStream derStrm = value.data;
|
||||
DerValue tmp;
|
||||
byte nextByte;
|
||||
|
||||
// version (optional if v1)
|
||||
version = 0; // by default, version = v1 == 0
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if (nextByte == DerValue.tag_Integer) {
|
||||
version = derStrm.getInteger();
|
||||
if (version != 1) // i.e. v2
|
||||
throw new CRLException("Invalid version");
|
||||
}
|
||||
tmp = derStrm.getDerValue();
|
||||
|
||||
// signature
|
||||
infoSigAlgId = AlgorithmId.parse(tmp);
|
||||
|
||||
// issuer
|
||||
issuer = new X500Name(derStrm);
|
||||
if (issuer.isEmpty()) {
|
||||
throw new CRLException("Empty issuer DN not allowed in X509CRLs");
|
||||
}
|
||||
|
||||
// thisUpdate
|
||||
// check if UTCTime encoded or GeneralizedTime
|
||||
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if (nextByte == DerValue.tag_UtcTime) {
|
||||
thisUpdate = derStrm.getUTCTime();
|
||||
} else if (nextByte == DerValue.tag_GeneralizedTime) {
|
||||
thisUpdate = derStrm.getGeneralizedTime();
|
||||
} else {
|
||||
throw new CRLException("Invalid encoding for thisUpdate"
|
||||
+ " (tag=" + nextByte + ")");
|
||||
}
|
||||
|
||||
if (derStrm.available() == 0)
|
||||
return; // done parsing no more optional fields present
|
||||
|
||||
// nextUpdate (optional)
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if (nextByte == DerValue.tag_UtcTime) {
|
||||
nextUpdate = derStrm.getUTCTime();
|
||||
} else if (nextByte == DerValue.tag_GeneralizedTime) {
|
||||
nextUpdate = derStrm.getGeneralizedTime();
|
||||
} // else it is not present
|
||||
|
||||
if (derStrm.available() == 0)
|
||||
return; // done parsing no more optional fields present
|
||||
|
||||
// revokedCertificates (optional)
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if ((nextByte == DerValue.tag_SequenceOf)
|
||||
&& (! ((nextByte & 0x0c0) == 0x080))) {
|
||||
DerValue[] badCerts = derStrm.getSequence(4);
|
||||
|
||||
X500Principal crlIssuer = getIssuerX500Principal();
|
||||
X500Principal badCertIssuer = crlIssuer;
|
||||
for (int i = 0; i < badCerts.length; i++) {
|
||||
X509CRLEntryImpl entry = new X509CRLEntryImpl(badCerts[i]);
|
||||
badCertIssuer = getCertIssuer(entry, badCertIssuer);
|
||||
entry.setCertificateIssuer(crlIssuer, badCertIssuer);
|
||||
X509IssuerSerial issuerSerial = new X509IssuerSerial
|
||||
(badCertIssuer, entry.getSerialNumber());
|
||||
revokedMap.put(issuerSerial, entry);
|
||||
revokedList.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (derStrm.available() == 0)
|
||||
return; // done parsing no extensions
|
||||
|
||||
// crlExtensions (optional)
|
||||
tmp = derStrm.getDerValue();
|
||||
if (tmp.isConstructed() && tmp.isContextSpecific((byte)0)) {
|
||||
extensions = new CRLExtensions(tmp.data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the issuer as X500Principal.
|
||||
*/
|
||||
public X500Principal getIssuerX500Principal() {
|
||||
if (issuerPrincipal == null) {
|
||||
issuerPrincipal = issuer.asX500Principal();
|
||||
}
|
||||
return issuerPrincipal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X500 certificate issuer DN of a CRL entry.
|
||||
*
|
||||
* @param entry the entry to check
|
||||
* @param prevCertIssuer the previous entry's certificate issuer
|
||||
* @return the X500Principal in a CertificateIssuerExtension, or
|
||||
* prevCertIssuer if it does not exist
|
||||
*/
|
||||
private X500Principal getCertIssuer(X509CRLEntryImpl entry,
|
||||
X500Principal prevCertIssuer) {
|
||||
|
||||
CertificateIssuerExtension ciExt =
|
||||
entry.getCertificateIssuerExtension();
|
||||
if (ciExt != null) {
|
||||
GeneralNames names = ciExt.getNames();
|
||||
X500Name issuerDN = (X500Name) names.get(0).getName();
|
||||
return issuerDN.asX500Principal();
|
||||
} else {
|
||||
return prevCertIssuer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the "to-be-signed" TBSCertList to the OutputStream.
|
||||
*
|
||||
* @exception CRLException on encoding errors.
|
||||
*/
|
||||
public byte[] encodeInfo() throws CRLException {
|
||||
try {
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
DerOutputStream rCerts = new DerOutputStream();
|
||||
DerOutputStream seq = new DerOutputStream();
|
||||
|
||||
if (version != 0) // v2 crl encode version
|
||||
tmp.putInteger(version);
|
||||
infoSigAlgId.encode(tmp);
|
||||
if ((version == 0) && (issuer.toString() == null))
|
||||
throw new CRLException("Null Issuer DN not allowed in v1 CRL");
|
||||
issuer.encode(tmp);
|
||||
|
||||
if (thisUpdate.getTime() < CertificateValidity.YR_2050)
|
||||
tmp.putUTCTime(thisUpdate);
|
||||
else
|
||||
tmp.putGeneralizedTime(thisUpdate);
|
||||
|
||||
if (nextUpdate != null) {
|
||||
if (nextUpdate.getTime() < CertificateValidity.YR_2050)
|
||||
tmp.putUTCTime(nextUpdate);
|
||||
else
|
||||
tmp.putGeneralizedTime(nextUpdate);
|
||||
}
|
||||
|
||||
if (!revokedList.isEmpty()) {
|
||||
for (X509CRLEntry entry : revokedList) {
|
||||
((X509CRLEntryImpl)entry).encode(rCerts);
|
||||
}
|
||||
tmp.write(DerValue.tag_Sequence, rCerts);
|
||||
}
|
||||
|
||||
if (extensions != null)
|
||||
extensions.encode(tmp, isExplicit);
|
||||
|
||||
seq.write(DerValue.tag_Sequence, tmp);
|
||||
|
||||
return seq.toByteArray();
|
||||
} catch (IOException e) {
|
||||
throw new CRLException("Encoding error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final boolean isExplicit = true;
|
||||
|
||||
/**
|
||||
* PublicKey that has previously been used to successfully verify
|
||||
@ -117,10 +358,17 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
private String verifiedProvider;
|
||||
|
||||
/**
|
||||
* Not to be used. As it would lead to cases of uninitialized
|
||||
* CRL objects.
|
||||
* Constructor simply setting all (non-cache) fields. Only used in
|
||||
* {@link #newSigned}.
|
||||
*/
|
||||
private X509CRLImpl() { }
|
||||
public X509CRLImpl(TBSCertList info, AlgorithmId sigAlgId, byte[] signature,
|
||||
byte[] tbsCertList, byte[] signedCRL) {
|
||||
this.info = info;
|
||||
this.sigAlgId = sigAlgId;
|
||||
this.signature = signature;
|
||||
this.tbsCertList = tbsCertList;
|
||||
this.signedCRL = Objects.requireNonNull(signedCRL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshals an X.509 CRL from its encoded form, parsing the encoded
|
||||
@ -136,7 +384,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
try {
|
||||
parse(new DerValue(crlData));
|
||||
} catch (IOException e) {
|
||||
signedCRL = null;
|
||||
throw new CRLException("Parsing error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@ -151,7 +398,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
try {
|
||||
parse(val);
|
||||
} catch (IOException e) {
|
||||
signedCRL = null;
|
||||
throw new CRLException("Parsing error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@ -167,79 +413,12 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
try {
|
||||
parse(new DerValue(inStrm));
|
||||
} catch (IOException e) {
|
||||
signedCRL = null;
|
||||
throw new CRLException("Parsing error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial CRL constructor, no revoked certs, and no extensions.
|
||||
*
|
||||
* @param issuer the name of the CA issuing this CRL.
|
||||
* @param thisDate the Date of this issue.
|
||||
* @param nextDate the Date of the next CRL.
|
||||
*/
|
||||
public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate) {
|
||||
this.issuer = issuer;
|
||||
this.thisUpdate = thisDate;
|
||||
this.nextUpdate = nextDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* CRL constructor, revoked certs, no extensions.
|
||||
*
|
||||
* @param issuer the name of the CA issuing this CRL.
|
||||
* @param thisDate the Date of this issue.
|
||||
* @param nextDate the Date of the next CRL.
|
||||
* @param badCerts the array of CRL entries.
|
||||
*
|
||||
* @exception CRLException on parsing/construction errors.
|
||||
*/
|
||||
public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate,
|
||||
X509CRLEntry[] badCerts)
|
||||
throws CRLException
|
||||
{
|
||||
this.issuer = issuer;
|
||||
this.thisUpdate = thisDate;
|
||||
this.nextUpdate = nextDate;
|
||||
if (badCerts != null) {
|
||||
X500Principal crlIssuer = getIssuerX500Principal();
|
||||
X500Principal badCertIssuer = crlIssuer;
|
||||
for (int i = 0; i < badCerts.length; i++) {
|
||||
X509CRLEntryImpl badCert = (X509CRLEntryImpl)badCerts[i];
|
||||
badCertIssuer = getCertIssuer(badCert, badCertIssuer);
|
||||
badCert.setCertificateIssuer(crlIssuer, badCertIssuer);
|
||||
X509IssuerSerial issuerSerial = new X509IssuerSerial
|
||||
(badCertIssuer, badCert.getSerialNumber());
|
||||
this.revokedMap.put(issuerSerial, badCert);
|
||||
this.revokedList.add(badCert);
|
||||
if (badCert.hasExtensions()) {
|
||||
this.version = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CRL constructor, revoked certs and extensions.
|
||||
*
|
||||
* @param issuer the name of the CA issuing this CRL.
|
||||
* @param thisDate the Date of this issue.
|
||||
* @param nextDate the Date of the next CRL.
|
||||
* @param badCerts the array of CRL entries.
|
||||
* @param crlExts the CRL extensions.
|
||||
*
|
||||
* @exception CRLException on parsing/construction errors.
|
||||
*/
|
||||
public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate,
|
||||
X509CRLEntry[] badCerts, CRLExtensions crlExts)
|
||||
throws CRLException
|
||||
{
|
||||
this(issuer, thisDate, nextDate, badCerts);
|
||||
if (crlExts != null) {
|
||||
this.extensions = crlExts;
|
||||
this.version = 1;
|
||||
}
|
||||
public TBSCertList info() {
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,9 +427,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* code.
|
||||
*/
|
||||
public byte[] getEncodedInternal() throws CRLException {
|
||||
if (signedCRL == null) {
|
||||
throw new CRLException("Null CRL to encode");
|
||||
}
|
||||
return signedCRL;
|
||||
}
|
||||
|
||||
@ -263,56 +439,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
return getEncodedInternal().clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the "to-be-signed" CRL to the OutputStream.
|
||||
*
|
||||
* @param out the OutputStream to write to.
|
||||
* @exception CRLException on encoding errors.
|
||||
*/
|
||||
public void encodeInfo(OutputStream out) throws CRLException {
|
||||
try {
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
DerOutputStream rCerts = new DerOutputStream();
|
||||
DerOutputStream seq = new DerOutputStream();
|
||||
|
||||
if (version != 0) // v2 crl encode version
|
||||
tmp.putInteger(version);
|
||||
infoSigAlgId.encode(tmp);
|
||||
if ((version == 0) && (issuer.toString() == null))
|
||||
throw new CRLException("Null Issuer DN not allowed in v1 CRL");
|
||||
issuer.encode(tmp);
|
||||
|
||||
if (thisUpdate.getTime() < CertificateValidity.YR_2050)
|
||||
tmp.putUTCTime(thisUpdate);
|
||||
else
|
||||
tmp.putGeneralizedTime(thisUpdate);
|
||||
|
||||
if (nextUpdate != null) {
|
||||
if (nextUpdate.getTime() < CertificateValidity.YR_2050)
|
||||
tmp.putUTCTime(nextUpdate);
|
||||
else
|
||||
tmp.putGeneralizedTime(nextUpdate);
|
||||
}
|
||||
|
||||
if (!revokedList.isEmpty()) {
|
||||
for (X509CRLEntry entry : revokedList) {
|
||||
((X509CRLEntryImpl)entry).encode(rCerts);
|
||||
}
|
||||
tmp.write(DerValue.tag_Sequence, rCerts);
|
||||
}
|
||||
|
||||
if (extensions != null)
|
||||
extensions.encode(tmp, isExplicit);
|
||||
|
||||
seq.write(DerValue.tag_Sequence, tmp);
|
||||
|
||||
tbsCertList = seq.toByteArray();
|
||||
out.write(tbsCertList);
|
||||
} catch (IOException e) {
|
||||
throw new CRLException("Encoding error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that this CRL was signed using the
|
||||
* private key that corresponds to the given public key.
|
||||
@ -362,9 +488,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (signedCRL == null) {
|
||||
throw new CRLException("Uninitialized CRL");
|
||||
}
|
||||
Signature sigVerf;
|
||||
String sigName = sigAlgId.getName();
|
||||
if (sigProvider.isEmpty()) {
|
||||
@ -415,9 +538,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
SignatureException {
|
||||
|
||||
if (signedCRL == null) {
|
||||
throw new CRLException("Uninitialized CRL");
|
||||
}
|
||||
Signature sigVerf;
|
||||
String sigName = sigAlgId.getName();
|
||||
if (sigProvider == null) {
|
||||
@ -448,10 +568,12 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes an X.509 CRL, and signs it using the given key.
|
||||
* Creates a new X.509 CRL, which is signed using the given key.
|
||||
*
|
||||
* @param info the TBSCertList to sign
|
||||
* @param key the private key used for signing.
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
* @return a newly signed CRL
|
||||
*
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
@ -459,18 +581,20 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CRLException if any mandatory data was omitted.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm)
|
||||
public static X509CRLImpl newSigned(TBSCertList info, PrivateKey key, String algorithm)
|
||||
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
sign(key, algorithm, null);
|
||||
return newSigned(info, key, algorithm, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes an X.509 CRL, and signs it using the given key.
|
||||
* Creates a new X.509 CRL, which is signed using the given key.
|
||||
*
|
||||
* @param info the TBSCertList to sign
|
||||
* @param key the private key used for signing.
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
* @param provider (optional) the name of the provider.
|
||||
* @return a newly signed CRL
|
||||
*
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
@ -478,36 +602,35 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CRLException if any mandatory data was omitted.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm, String provider)
|
||||
public static X509CRLImpl newSigned(TBSCertList info, PrivateKey key, String algorithm, String provider)
|
||||
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
try {
|
||||
if (readOnly)
|
||||
throw new CRLException("cannot over-write existing CRL");
|
||||
|
||||
Signature sigEngine = SignatureUtil.fromKey(algorithm, key, provider);
|
||||
sigAlgId = SignatureUtil.fromSignature(sigEngine, key);
|
||||
infoSigAlgId = sigAlgId;
|
||||
AlgorithmId sigAlgId = SignatureUtil.fromSignature(sigEngine, key);
|
||||
info.infoSigAlgId = sigAlgId;
|
||||
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
|
||||
// encode crl info
|
||||
encodeInfo(tmp);
|
||||
byte[] tbsCertList = info.encodeInfo();
|
||||
tmp.writeBytes(tbsCertList);
|
||||
|
||||
// encode algorithm identifier
|
||||
sigAlgId.encode(tmp);
|
||||
|
||||
// Create and encode the signature itself.
|
||||
sigEngine.update(tbsCertList, 0, tbsCertList.length);
|
||||
signature = sigEngine.sign();
|
||||
byte[] signature = sigEngine.sign();
|
||||
tmp.putBitString(signature);
|
||||
|
||||
// Wrap the signed data in a SEQUENCE { data, algorithm, sig }
|
||||
out.write(DerValue.tag_Sequence, tmp);
|
||||
signedCRL = out.toByteArray();
|
||||
readOnly = true;
|
||||
byte[] signedCRL = out.toByteArray();
|
||||
|
||||
return new X509CRLImpl(info, sigAlgId, signature,
|
||||
tbsCertList, signedCRL);
|
||||
} catch (IOException e) {
|
||||
throw new CRLException("Error while encoding data: " +
|
||||
e.getMessage());
|
||||
@ -527,7 +650,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
public String toStringWithAlgName(String name) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("X.509 CRL v")
|
||||
.append(version+1)
|
||||
.append(info.version+1)
|
||||
.append('\n');
|
||||
if (sigAlgId != null)
|
||||
sb.append("Signature Algorithm: ")
|
||||
@ -535,33 +658,33 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
.append(", OID=")
|
||||
.append(sigAlgId.getOID())
|
||||
.append('\n');
|
||||
if (issuer != null)
|
||||
if (info.issuer != null)
|
||||
sb.append("Issuer: ")
|
||||
.append(issuer)
|
||||
.append(info.issuer)
|
||||
.append('\n');
|
||||
if (thisUpdate != null)
|
||||
if (info.thisUpdate != null)
|
||||
sb.append("\nThis Update: ")
|
||||
.append(thisUpdate)
|
||||
.append(info.thisUpdate)
|
||||
.append('\n');
|
||||
if (nextUpdate != null)
|
||||
if (info.nextUpdate != null)
|
||||
sb.append("Next Update: ")
|
||||
.append(nextUpdate)
|
||||
.append(info.nextUpdate)
|
||||
.append('\n');
|
||||
if (revokedList.isEmpty())
|
||||
if (info.revokedList.isEmpty())
|
||||
sb.append("\nNO certificates have been revoked\n");
|
||||
else {
|
||||
sb.append("\nRevoked Certificates: ")
|
||||
.append(revokedList.size());
|
||||
.append(info.revokedList.size());
|
||||
int i = 1;
|
||||
for (X509CRLEntry entry: revokedList) {
|
||||
for (X509CRLEntry entry: info.revokedList) {
|
||||
sb.append("\n[")
|
||||
.append(i++)
|
||||
.append("] ")
|
||||
.append(entry);
|
||||
}
|
||||
}
|
||||
if (extensions != null) {
|
||||
Collection<Extension> allExts = extensions.getAllExtensions();
|
||||
if (info.extensions != null) {
|
||||
Collection<Extension> allExts = info.extensions.getAllExtensions();
|
||||
Object[] objs = allExts.toArray();
|
||||
sb.append("\nCRL Extensions: ")
|
||||
.append(objs.length);
|
||||
@ -609,12 +732,12 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean isRevoked(Certificate cert) {
|
||||
if (revokedMap.isEmpty() ||
|
||||
if (info.revokedMap.isEmpty() ||
|
||||
(!(cert instanceof X509Certificate xcert))) {
|
||||
return false;
|
||||
}
|
||||
X509IssuerSerial issuerSerial = new X509IssuerSerial(xcert);
|
||||
return revokedMap.containsKey(issuerSerial);
|
||||
return info.revokedMap.containsKey(issuerSerial);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -628,7 +751,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @return the version number, i.e. 1 or 2.
|
||||
*/
|
||||
public int getVersion() {
|
||||
return version+1;
|
||||
return info.version+1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -661,7 +784,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public Principal getIssuerDN() {
|
||||
return issuer;
|
||||
return info.issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -669,10 +792,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* to provide a slightly more efficient version.
|
||||
*/
|
||||
public X500Principal getIssuerX500Principal() {
|
||||
if (issuerPrincipal == null) {
|
||||
issuerPrincipal = issuer.asX500Principal();
|
||||
}
|
||||
return issuerPrincipal;
|
||||
return info.getIssuerX500Principal();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -682,7 +802,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @return the thisUpdate date from the CRL.
|
||||
*/
|
||||
public Date getThisUpdate() {
|
||||
return new Date(thisUpdate.getTime());
|
||||
return new Date(info.thisUpdate.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -692,9 +812,9 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* not present.
|
||||
*/
|
||||
public Date getNextUpdate() {
|
||||
if (nextUpdate == null)
|
||||
if (info.nextUpdate == null)
|
||||
return null;
|
||||
return new Date(nextUpdate.getTime());
|
||||
return new Date(info.nextUpdate.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -705,24 +825,24 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @see X509CRLEntry
|
||||
*/
|
||||
public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) {
|
||||
if (revokedMap.isEmpty()) {
|
||||
if (info.revokedMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// assume this is a direct CRL entry (cert and CRL issuer are the same)
|
||||
X509IssuerSerial issuerSerial = new X509IssuerSerial
|
||||
(getIssuerX500Principal(), serialNumber);
|
||||
return revokedMap.get(issuerSerial);
|
||||
return info.revokedMap.get(issuerSerial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CRL entry for the given certificate.
|
||||
*/
|
||||
public X509CRLEntry getRevokedCertificate(X509Certificate cert) {
|
||||
if (revokedMap.isEmpty()) {
|
||||
if (info.revokedMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
X509IssuerSerial issuerSerial = new X509IssuerSerial(cert);
|
||||
return revokedMap.get(issuerSerial);
|
||||
return info.revokedMap.get(issuerSerial);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -734,10 +854,10 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @see X509CRLEntry
|
||||
*/
|
||||
public Set<X509CRLEntry> getRevokedCertificates() {
|
||||
if (revokedList.isEmpty()) {
|
||||
if (info.revokedList.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return new TreeSet<>(revokedList);
|
||||
return new TreeSet<>(info.revokedList);
|
||||
}
|
||||
}
|
||||
|
||||
@ -929,9 +1049,9 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* not supported, otherwise return false.
|
||||
*/
|
||||
public boolean hasUnsupportedCriticalExtension() {
|
||||
if (extensions == null)
|
||||
if (info.extensions == null)
|
||||
return false;
|
||||
return extensions.hasUnsupportedCriticalExtension();
|
||||
return info.extensions.hasUnsupportedCriticalExtension();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -943,11 +1063,11 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* CRL that are marked critical.
|
||||
*/
|
||||
public Set<String> getCriticalExtensionOIDs() {
|
||||
if (extensions == null) {
|
||||
if (info.extensions == null) {
|
||||
return null;
|
||||
}
|
||||
Set<String> extSet = new TreeSet<>();
|
||||
for (Extension ex : extensions.getAllExtensions()) {
|
||||
for (Extension ex : info.extensions.getAllExtensions()) {
|
||||
if (ex.isCritical()) {
|
||||
extSet.add(ex.getExtensionId().toString());
|
||||
}
|
||||
@ -964,11 +1084,11 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* CRL that are NOT marked critical.
|
||||
*/
|
||||
public Set<String> getNonCriticalExtensionOIDs() {
|
||||
if (extensions == null) {
|
||||
if (info.extensions == null) {
|
||||
return null;
|
||||
}
|
||||
Set<String> extSet = new TreeSet<>();
|
||||
for (Extension ex : extensions.getAllExtensions()) {
|
||||
for (Extension ex : info.extensions.getAllExtensions()) {
|
||||
if (!ex.isCritical()) {
|
||||
extSet.add(ex.getExtensionId().toString());
|
||||
}
|
||||
@ -988,7 +1108,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @return the der encoded octet string of the extension value.
|
||||
*/
|
||||
public byte[] getExtensionValue(String oid) {
|
||||
if (extensions == null)
|
||||
if (info.extensions == null)
|
||||
return null;
|
||||
try {
|
||||
String extAlias = OIDMap.getName(ObjectIdentifier.of(oid));
|
||||
@ -996,7 +1116,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
|
||||
if (extAlias == null) { // may be unknown
|
||||
ObjectIdentifier findOID = ObjectIdentifier.of(oid);
|
||||
for (Extension ex : extensions.getAllExtensions()) {
|
||||
for (Extension ex : info.extensions.getAllExtensions()) {
|
||||
ObjectIdentifier inCertOID = ex.getExtensionId();
|
||||
if (inCertOID.equals(findOID)) {
|
||||
crlExt = ex;
|
||||
@ -1004,7 +1124,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
}
|
||||
}
|
||||
} else
|
||||
crlExt = extensions.getExtension(extAlias);
|
||||
crlExt = info.extensions.getExtension(extAlias);
|
||||
if (crlExt == null)
|
||||
return null;
|
||||
byte[] extData = crlExt.getExtensionValue();
|
||||
@ -1025,20 +1145,17 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
* @return Object of type {@code <extension>} or null, if not found
|
||||
*/
|
||||
public Object getExtension(ObjectIdentifier oid) {
|
||||
if (extensions == null)
|
||||
if (info.extensions == null)
|
||||
return null;
|
||||
|
||||
// XXX Consider cloning this
|
||||
return extensions.getExtension(OIDMap.getName(oid));
|
||||
return info.extensions.getExtension(OIDMap.getName(oid));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses an X.509 CRL, should be used only by constructors.
|
||||
*/
|
||||
private void parse(DerValue val) throws CRLException, IOException {
|
||||
// check if we can overwrite the certificate
|
||||
if (readOnly)
|
||||
throw new CRLException("cannot over-write existing CRL");
|
||||
|
||||
if ( val.getData() == null || val.tag != DerValue.tag_Sequence)
|
||||
throw new CRLException("Invalid DER-encoded CRL data");
|
||||
@ -1054,10 +1171,14 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
throw new CRLException("signed overrun, bytes = "
|
||||
+ val.data.available());
|
||||
|
||||
if (seq[0].tag != DerValue.tag_Sequence)
|
||||
throw new CRLException("signed CRL fields invalid");
|
||||
info = new TBSCertList(seq[0]);
|
||||
|
||||
sigAlgId = AlgorithmId.parse(seq[1]);
|
||||
// the "inner" and "outer" signature algorithms must match
|
||||
if (!sigAlgId.equals(info.infoSigAlgId)) {
|
||||
throw new CRLException("Signature algorithm mismatch");
|
||||
}
|
||||
|
||||
signature = seq[2].getBitString();
|
||||
|
||||
if (seq[1].data.available() != 0)
|
||||
@ -1069,90 +1190,7 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
// the tbsCertsList
|
||||
tbsCertList = seq[0].toByteArray();
|
||||
|
||||
// parse the information
|
||||
DerInputStream derStrm = seq[0].data;
|
||||
DerValue tmp;
|
||||
byte nextByte;
|
||||
|
||||
// version (optional if v1)
|
||||
version = 0; // by default, version = v1 == 0
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if (nextByte == DerValue.tag_Integer) {
|
||||
version = derStrm.getInteger();
|
||||
if (version != 1) // i.e. v2
|
||||
throw new CRLException("Invalid version");
|
||||
}
|
||||
tmp = derStrm.getDerValue();
|
||||
|
||||
// signature
|
||||
AlgorithmId tmpId = AlgorithmId.parse(tmp);
|
||||
|
||||
// the "inner" and "outer" signature algorithms must match
|
||||
if (! tmpId.equals(sigAlgId))
|
||||
throw new CRLException("Signature algorithm mismatch");
|
||||
infoSigAlgId = tmpId;
|
||||
|
||||
// issuer
|
||||
issuer = new X500Name(derStrm);
|
||||
if (issuer.isEmpty()) {
|
||||
throw new CRLException("Empty issuer DN not allowed in X509CRLs");
|
||||
}
|
||||
|
||||
// thisUpdate
|
||||
// check if UTCTime encoded or GeneralizedTime
|
||||
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if (nextByte == DerValue.tag_UtcTime) {
|
||||
thisUpdate = derStrm.getUTCTime();
|
||||
} else if (nextByte == DerValue.tag_GeneralizedTime) {
|
||||
thisUpdate = derStrm.getGeneralizedTime();
|
||||
} else {
|
||||
throw new CRLException("Invalid encoding for thisUpdate"
|
||||
+ " (tag=" + nextByte + ")");
|
||||
}
|
||||
|
||||
if (derStrm.available() == 0)
|
||||
return; // done parsing no more optional fields present
|
||||
|
||||
// nextUpdate (optional)
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if (nextByte == DerValue.tag_UtcTime) {
|
||||
nextUpdate = derStrm.getUTCTime();
|
||||
} else if (nextByte == DerValue.tag_GeneralizedTime) {
|
||||
nextUpdate = derStrm.getGeneralizedTime();
|
||||
} // else it is not present
|
||||
|
||||
if (derStrm.available() == 0)
|
||||
return; // done parsing no more optional fields present
|
||||
|
||||
// revokedCertificates (optional)
|
||||
nextByte = (byte)derStrm.peekByte();
|
||||
if ((nextByte == DerValue.tag_SequenceOf)
|
||||
&& (! ((nextByte & 0x0c0) == 0x080))) {
|
||||
DerValue[] badCerts = derStrm.getSequence(4);
|
||||
|
||||
X500Principal crlIssuer = getIssuerX500Principal();
|
||||
X500Principal badCertIssuer = crlIssuer;
|
||||
for (int i = 0; i < badCerts.length; i++) {
|
||||
X509CRLEntryImpl entry = new X509CRLEntryImpl(badCerts[i]);
|
||||
badCertIssuer = getCertIssuer(entry, badCertIssuer);
|
||||
entry.setCertificateIssuer(crlIssuer, badCertIssuer);
|
||||
X509IssuerSerial issuerSerial = new X509IssuerSerial
|
||||
(badCertIssuer, entry.getSerialNumber());
|
||||
revokedMap.put(issuerSerial, entry);
|
||||
revokedList.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (derStrm.available() == 0)
|
||||
return; // done parsing no extensions
|
||||
|
||||
// crlExtensions (optional)
|
||||
tmp = derStrm.getDerValue();
|
||||
if (tmp.isConstructed() && tmp.isContextSpecific((byte)0)) {
|
||||
extensions = new CRLExtensions(tmp.data);
|
||||
}
|
||||
readOnly = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1212,32 +1250,8 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X500 certificate issuer DN of a CRL entry.
|
||||
*
|
||||
* @param entry the entry to check
|
||||
* @param prevCertIssuer the previous entry's certificate issuer
|
||||
* @return the X500Principal in a CertificateIssuerExtension, or
|
||||
* prevCertIssuer if it does not exist
|
||||
*/
|
||||
private X500Principal getCertIssuer(X509CRLEntryImpl entry,
|
||||
X500Principal prevCertIssuer) {
|
||||
|
||||
CertificateIssuerExtension ciExt =
|
||||
entry.getCertificateIssuerExtension();
|
||||
if (ciExt != null) {
|
||||
GeneralNames names = ciExt.getNames();
|
||||
X500Name issuerDN = (X500Name) names.get(0).getName();
|
||||
return issuerDN.asX500Principal();
|
||||
} else {
|
||||
return prevCertIssuer;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(DerOutputStream out) throws IOException {
|
||||
if (signedCRL == null)
|
||||
throw new IOException("Null CRL to encode");
|
||||
out.write(signedCRL.clone());
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,7 @@
|
||||
|
||||
package sun.security.x509;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.cert.*;
|
||||
@ -79,10 +74,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
|
||||
public static final String NAME = "x509";
|
||||
|
||||
// when we sign and decode we set this to true
|
||||
// this is our means to make certificates immutable
|
||||
private boolean readOnly = false;
|
||||
|
||||
// Certificate data, and its envelope
|
||||
private byte[] signedCert = null;
|
||||
protected X509CertInfo info = null;
|
||||
@ -124,9 +115,16 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
private boolean verificationResult;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* Constructor simply setting all (non-cache) fields. Only used in
|
||||
* {@link #newSigned}.
|
||||
*/
|
||||
public X509CertImpl() { }
|
||||
public X509CertImpl(X509CertInfo info, AlgorithmId algId, byte[] signature,
|
||||
byte[] signedCert) {
|
||||
this.info = info;
|
||||
this.algId = algId;
|
||||
this.signature = signature;
|
||||
this.signedCert = Objects.requireNonNull(signedCert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshals a certificate from its encoded form, parsing the
|
||||
@ -144,13 +142,28 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
try {
|
||||
parse(new DerValue(certData));
|
||||
} catch (IOException e) {
|
||||
signedCert = null;
|
||||
throw new CertificateException("Unable to initialize, " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unmarshals an X.509 certificate from an input stream. If the
|
||||
* Unmarshals a certificate from its encoded form, parsing a DER value.
|
||||
* This form of constructor is used by agents which need to examine
|
||||
* and use certificate contents.
|
||||
*
|
||||
* @param derVal the der value containing the encoded cert.
|
||||
* @exception CertificateException on parsing and initialization errors.
|
||||
*/
|
||||
public X509CertImpl(DerValue derVal) throws CertificateException {
|
||||
try {
|
||||
parse(derVal);
|
||||
} catch (IOException e) {
|
||||
throw new CertificateException("Unable to initialize, " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshals an X.509 certificate from an input stream. If the
|
||||
* certificate is RFC1421 hex-encoded, then it must begin with
|
||||
* the line X509Factory.BEGIN_CERT and end with the line
|
||||
* X509Factory.END_CERT.
|
||||
@ -235,37 +248,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
return der;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an initialized X509 Certificate. The certificate is stored
|
||||
* in raw form and has to be signed to be useful.
|
||||
*
|
||||
* The ALGORITHM_ID attribute will be rewritten when signed. The initial
|
||||
* value is ignored.
|
||||
*
|
||||
* @param certInfo the X509CertificateInfo which the Certificate is to be
|
||||
* created from.
|
||||
*/
|
||||
public X509CertImpl(X509CertInfo certInfo) {
|
||||
this.info = certInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmarshal a certificate from its encoded form, parsing a DER value.
|
||||
* This form of constructor is used by agents which need to examine
|
||||
* and use certificate contents.
|
||||
*
|
||||
* @param derVal the der value containing the encoded cert.
|
||||
* @exception CertificateException on parsing and initialization errors.
|
||||
*/
|
||||
public X509CertImpl(DerValue derVal) throws CertificateException {
|
||||
try {
|
||||
parse(derVal);
|
||||
} catch (IOException e) {
|
||||
signedCert = null;
|
||||
throw new CertificateException("Unable to initialize, " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
// helper method to record certificate, if necessary, after construction
|
||||
public static X509CertImpl newX509CertImpl(byte[] certData) throws CertificateException {
|
||||
var cert = new X509CertImpl(certData);
|
||||
@ -283,8 +265,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
*/
|
||||
@Override
|
||||
public void encode(DerOutputStream out) throws IOException {
|
||||
if (signedCert == null)
|
||||
throw new IOException("Null certificate to encode");
|
||||
out.write(signedCert.clone());
|
||||
}
|
||||
|
||||
@ -306,10 +286,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
* code.
|
||||
*/
|
||||
public byte[] getEncodedInternal() throws CertificateEncodingException {
|
||||
if (signedCert == null) {
|
||||
throw new CertificateEncodingException(
|
||||
"Null certificate to encode");
|
||||
}
|
||||
return signedCert;
|
||||
}
|
||||
|
||||
@ -367,9 +343,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (signedCert == null) {
|
||||
throw new CertificateEncodingException("Uninitialized certificate");
|
||||
}
|
||||
// Verify the signature ...
|
||||
Signature sigVerf;
|
||||
String sigName = algId.getName();
|
||||
@ -421,9 +394,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
public synchronized void verify(PublicKey key, Provider sigProvider)
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, SignatureException {
|
||||
if (signedCert == null) {
|
||||
throw new CertificateEncodingException("Uninitialized certificate");
|
||||
}
|
||||
// Verify the signature ...
|
||||
Signature sigVerf;
|
||||
String sigName = algId.getName();
|
||||
@ -455,13 +425,15 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an X.509 certificate, and signs it using the given key
|
||||
* Creates a new X.509 certificate, which is signed using the given key
|
||||
* (associating a signature algorithm and an X.500 name).
|
||||
* This operation is used to implement the certificate generation
|
||||
* functionality of a certificate authority.
|
||||
*
|
||||
* @param info the X509CertInfo to sign
|
||||
* @param key the private key used for signing.
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
* @return the newly signed certificate
|
||||
*
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
@ -469,21 +441,23 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CertificateException on encoding errors.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm)
|
||||
public static X509CertImpl newSigned(X509CertInfo info, PrivateKey key, String algorithm)
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
sign(key, algorithm, null);
|
||||
return newSigned(info, key, algorithm, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an X.509 certificate, and signs it using the given key
|
||||
* Creates a new X.509 certificate, which is signed using the given key
|
||||
* (associating a signature algorithm and an X.500 name).
|
||||
* This operation is used to implement the certificate generation
|
||||
* functionality of a certificate authority.
|
||||
*
|
||||
* @param info the X509CertInfo to sign
|
||||
* @param key the private key used for signing.
|
||||
* @param algorithm the name of the signature algorithm used.
|
||||
* @param provider (optional) the name of the provider.
|
||||
* @return the newly signed certificate
|
||||
*
|
||||
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
|
||||
* @exception InvalidKeyException on incorrect key.
|
||||
@ -491,17 +465,13 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
* @exception SignatureException on signature errors.
|
||||
* @exception CertificateException on encoding errors.
|
||||
*/
|
||||
public void sign(PrivateKey key, String algorithm, String provider)
|
||||
public static X509CertImpl newSigned(X509CertInfo info, PrivateKey key, String algorithm, String provider)
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
try {
|
||||
if (readOnly) {
|
||||
throw new CertificateEncodingException(
|
||||
"cannot over-write existing certificate");
|
||||
}
|
||||
Signature sigEngine = SignatureUtil.fromKey(
|
||||
algorithm, key, provider);
|
||||
algId = SignatureUtil.fromSignature(sigEngine, key);
|
||||
AlgorithmId algId = SignatureUtil.fromSignature(sigEngine, key);
|
||||
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
DerOutputStream tmp = new DerOutputStream();
|
||||
@ -516,14 +486,14 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
|
||||
// Create and encode the signature itself.
|
||||
sigEngine.update(rawCert, 0, rawCert.length);
|
||||
signature = sigEngine.sign();
|
||||
byte[] signature = sigEngine.sign();
|
||||
tmp.putBitString(signature);
|
||||
|
||||
// Wrap the signed data in a SEQUENCE { data, algorithm, sig }
|
||||
out.write(DerValue.tag_Sequence, tmp);
|
||||
signedCert = out.toByteArray();
|
||||
readOnly = true;
|
||||
byte[] signedCert = out.toByteArray();
|
||||
|
||||
return new X509CertImpl(info, algId, signature, signedCert);
|
||||
} catch (IOException e) {
|
||||
throw new CertificateEncodingException(e.toString());
|
||||
}
|
||||
@ -1160,7 +1130,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
@Override
|
||||
public synchronized List<String> getExtendedKeyUsage()
|
||||
throws CertificateParsingException {
|
||||
if (readOnly && extKeyUsage != null) {
|
||||
if (extKeyUsage != null) {
|
||||
return extKeyUsage;
|
||||
}
|
||||
ExtendedKeyUsageExtension ext = (ExtendedKeyUsageExtension)
|
||||
@ -1351,7 +1321,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
public synchronized Collection<List<?>> getSubjectAlternativeNames()
|
||||
throws CertificateParsingException {
|
||||
// return cached value if we can
|
||||
if (readOnly && subjectAlternativeNames != null) {
|
||||
if (subjectAlternativeNames != null) {
|
||||
return cloneAltNames(subjectAlternativeNames);
|
||||
}
|
||||
SubjectAlternativeNameExtension subjectAltNameExt =
|
||||
@ -1403,7 +1373,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
public synchronized Collection<List<?>> getIssuerAlternativeNames()
|
||||
throws CertificateParsingException {
|
||||
// return cached value if we can
|
||||
if (readOnly && issuerAlternativeNames != null) {
|
||||
if (issuerAlternativeNames != null) {
|
||||
return cloneAltNames(issuerAlternativeNames);
|
||||
}
|
||||
IssuerAlternativeNameExtension issuerAltNameExt =
|
||||
@ -1463,11 +1433,8 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
* parts away for later verification.
|
||||
*/
|
||||
private void parse(DerValue val)
|
||||
throws CertificateException, IOException {
|
||||
throws CertificateException, IOException {
|
||||
// check if we can overwrite the certificate
|
||||
if (readOnly)
|
||||
throw new CertificateParsingException(
|
||||
"cannot over-write existing certificate");
|
||||
|
||||
if (val.data == null || val.tag != DerValue.tag_Sequence)
|
||||
throw new CertificateParsingException(
|
||||
@ -1504,7 +1471,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
|
||||
AlgorithmId infoSigAlg = info.getAlgorithmId().getAlgId();
|
||||
if (! algId.equals(infoSigAlg))
|
||||
throw new CertificateException("Signature algorithm mismatch");
|
||||
readOnly = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,9 +79,10 @@ public class EdCRLSign {
|
||||
System.out.printf("Case Algo:%s, Param:%s, Intitiate with random:%s%n",
|
||||
name, param, initWithRandom);
|
||||
KeyPair kp = genKeyPair(provider, name, param, initWithRandom);
|
||||
X509CRLImpl crl = new X509CRLImpl(
|
||||
new X500Name("CN=Issuer"), new Date(), new Date());
|
||||
crl.sign(kp.getPrivate(), name);
|
||||
X509CRLImpl crl = X509CRLImpl.newSigned(
|
||||
new X509CRLImpl.TBSCertList(new X500Name("CN=Issuer"),
|
||||
new Date(), new Date()),
|
||||
kp.getPrivate(), name);
|
||||
crl.verify(kp.getPublic());
|
||||
System.out.println("Passed.");
|
||||
}
|
||||
|
@ -254,8 +254,7 @@ class SimpleSigner {
|
||||
info.setValidity(interval);
|
||||
info.setIssuer(agent);
|
||||
|
||||
certLocal = new X509CertImpl(info);
|
||||
certLocal.sign(privateKey, algId.getName());
|
||||
certLocal = X509CertImpl.newSigned(info, privateKey, algId.getName());
|
||||
|
||||
return certLocal;
|
||||
}
|
||||
|
@ -69,8 +69,9 @@ public class BigCRL {
|
||||
badCerts[i] = new X509CRLEntryImpl(
|
||||
BigInteger.valueOf(i), date, ext);
|
||||
}
|
||||
X509CRLImpl crl = new X509CRLImpl(owner, date, date, badCerts);
|
||||
crl.sign(privateKey, sigAlgName);
|
||||
X509CRLImpl crl = X509CRLImpl.newSigned(
|
||||
new X509CRLImpl.TBSCertList(owner, date, date, badCerts),
|
||||
privateKey, sigAlgName);
|
||||
byte[] data = crl.getEncodedInternal();
|
||||
|
||||
// Make sure the CRL is big enough
|
||||
|
@ -49,8 +49,8 @@ public class DefaultParamSpec {
|
||||
new MGF1ParameterSpec("SHA-384"),
|
||||
48, PSSParameterSpec.TRAILER_FIELD_BC)));
|
||||
|
||||
X509CRLImpl crl = new X509CRLImpl(
|
||||
new X500Name("CN=Issuer"), new Date(), new Date());
|
||||
crl.sign(kpg.generateKeyPair().getPrivate(), "RSASSA-PSS");
|
||||
X509CRLImpl crl = X509CRLImpl.newSigned(
|
||||
new X509CRLImpl.TBSCertList(new X500Name("CN=Issuer"), new Date(), new Date()),
|
||||
kpg.generateKeyPair().getPrivate(), "RSASSA-PSS");
|
||||
}
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ public class TestHostnameChecker {
|
||||
}
|
||||
|
||||
private static X509Certificate mock(String domain) {
|
||||
return new X509CertImpl() {
|
||||
return new X509CertImpl(null, null, null, new byte[0]) {
|
||||
@Override
|
||||
public Collection<List<?>> getSubjectAlternativeNames() {
|
||||
return List.of(List.of(2, domain));
|
||||
|
@ -55,9 +55,10 @@ public class OrderAndDup {
|
||||
new Date(System.currentTimeMillis()+i*1000));
|
||||
}
|
||||
X500Name owner = new X500Name("CN=CA");
|
||||
X509CRLImpl crl = new X509CRLImpl(owner, new Date(), new Date(), badCerts);
|
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
|
||||
crl.sign(kpg.genKeyPair().getPrivate(), "SHA1withRSA");
|
||||
X509CRLImpl crl = X509CRLImpl.newSigned(
|
||||
new X509CRLImpl.TBSCertList(owner, new Date(), new Date(), badCerts),
|
||||
kpg.genKeyPair().getPrivate(), "SHA1withRSA");
|
||||
byte[] data = crl.getEncodedInternal();
|
||||
|
||||
// Check the encoding
|
||||
|
@ -205,8 +205,7 @@ public class V3Certificate {
|
||||
cert.setExtensions(exts);
|
||||
|
||||
// Generate and sign X509CertImpl
|
||||
X509CertImpl crt = new X509CertImpl(cert);
|
||||
crt.sign(privateKey, sigAlg);
|
||||
X509CertImpl crt = X509CertImpl.newSigned(cert, privateKey, sigAlg);
|
||||
crt.verify(publicKey);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE));
|
||||
|
Loading…
x
Reference in New Issue
Block a user