use of com.github.zhenwei.core.asn1.x509.AlgorithmIdentifier in project pac4j by pac4j.
the class SAML2ClientConfiguration method createSelfSignedCert.
/**
* Generate a self-signed certificate for dn using the provided signature algorithm and key pair.
*
* @param dn X.500 name to associate with certificate issuer/subject.
* @param sigName name of the signature algorithm to use.
* @param sigAlgID algorithm ID associated with the signature algorithm name.
* @param keyPair the key pair to associate with the certificate.
* @return an X509Certificate containing the public key in keyPair.
* @throws Exception
*/
private X509Certificate createSelfSignedCert(X500Name dn, String sigName, AlgorithmIdentifier sigAlgID, KeyPair keyPair) throws Exception {
V3TBSCertificateGenerator certGen = new V3TBSCertificateGenerator();
certGen.setSerialNumber(new ASN1Integer(BigInteger.valueOf(1)));
certGen.setIssuer(dn);
certGen.setSubject(dn);
certGen.setStartDate(new Time(new Date(System.currentTimeMillis() - 1000L)));
final Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.YEAR, 1);
certGen.setEndDate(new Time(c.getTime()));
certGen.setSignature(sigAlgID);
certGen.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
Signature sig = Signature.getInstance(sigName);
sig.initSign(keyPair.getPrivate());
sig.update(certGen.generateTBSCertificate().getEncoded(ASN1Encoding.DER));
TBSCertificate tbsCert = certGen.generateTBSCertificate();
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(tbsCert);
v.add(sigAlgID);
v.add(new DERBitString(sig.sign()));
X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(new DERSequence(v).getEncoded(ASN1Encoding.DER)));
// check the certificate - this will confirm the encoded sig algorithm ID is correct.
cert.verify(keyPair.getPublic());
return cert;
}
use of com.github.zhenwei.core.asn1.x509.AlgorithmIdentifier in project xipki by xipki.
the class XmlX509Certprofile method getExtensions.
@Override
public ExtensionValues getExtensions(Map<ASN1ObjectIdentifier, ExtensionControl> extensionOccurences, X500Name requestedSubject, X500Name grantedSubject, Extensions requestedExtensions, Date notBefore, Date notAfter, PublicCaInfo caInfo) throws CertprofileException, BadCertTemplateException {
ExtensionValues values = new ExtensionValues();
if (CollectionUtil.isEmpty(extensionOccurences)) {
return values;
}
ParamUtil.requireNonNull("requestedSubject", requestedSubject);
ParamUtil.requireNonNull("notBefore", notBefore);
ParamUtil.requireNonNull("notAfter", notAfter);
Set<ASN1ObjectIdentifier> occurences = new HashSet<>(extensionOccurences.keySet());
// AuthorityKeyIdentifier
// processed by the CA
// SubjectKeyIdentifier
// processed by the CA
// KeyUsage
// processed by the CA
// CertificatePolicies
ASN1ObjectIdentifier type = Extension.certificatePolicies;
if (certificatePolicies != null) {
if (occurences.remove(type)) {
values.addExtension(type, certificatePolicies);
}
}
// Policy Mappings
type = Extension.policyMappings;
if (policyMappings != null) {
if (occurences.remove(type)) {
values.addExtension(type, policyMappings);
}
}
// SubjectAltName
type = Extension.subjectAlternativeName;
if (occurences.contains(type)) {
GeneralNames genNames = createRequestedSubjectAltNames(requestedSubject, grantedSubject, requestedExtensions);
if (genNames != null) {
ExtensionValue value = new ExtensionValue(extensionControls.get(type).isCritical(), genNames);
values.addExtension(type, value);
occurences.remove(type);
}
}
// IssuerAltName
// processed by the CA
// Subject Directory Attributes
type = Extension.subjectDirectoryAttributes;
if (occurences.contains(type) && subjectDirAttrsControl != null) {
Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("no SubjectDirecotryAttributes extension is contained in the request");
}
ASN1GeneralizedTime dateOfBirth = null;
String placeOfBirth = null;
String gender = null;
List<String> countryOfCitizenshipList = new LinkedList<>();
List<String> countryOfResidenceList = new LinkedList<>();
Map<ASN1ObjectIdentifier, List<ASN1Encodable>> otherAttrs = new HashMap<>();
Vector<?> reqSubDirAttrs = SubjectDirectoryAttributes.getInstance(extension.getParsedValue()).getAttributes();
final int n = reqSubDirAttrs.size();
for (int i = 0; i < n; i++) {
Attribute attr = (Attribute) reqSubDirAttrs.get(i);
ASN1ObjectIdentifier attrType = attr.getAttrType();
ASN1Encodable attrVal = attr.getAttributeValues()[0];
if (ObjectIdentifiers.DN_DATE_OF_BIRTH.equals(attrType)) {
dateOfBirth = ASN1GeneralizedTime.getInstance(attrVal);
} else if (ObjectIdentifiers.DN_PLACE_OF_BIRTH.equals(attrType)) {
placeOfBirth = DirectoryString.getInstance(attrVal).getString();
} else if (ObjectIdentifiers.DN_GENDER.equals(attrType)) {
gender = DERPrintableString.getInstance(attrVal).getString();
} else if (ObjectIdentifiers.DN_COUNTRY_OF_CITIZENSHIP.equals(attrType)) {
String country = DERPrintableString.getInstance(attrVal).getString();
countryOfCitizenshipList.add(country);
} else if (ObjectIdentifiers.DN_COUNTRY_OF_RESIDENCE.equals(attrType)) {
String country = DERPrintableString.getInstance(attrVal).getString();
countryOfResidenceList.add(country);
} else {
List<ASN1Encodable> otherAttrVals = otherAttrs.get(attrType);
if (otherAttrVals == null) {
otherAttrVals = new LinkedList<>();
otherAttrs.put(attrType, otherAttrVals);
}
otherAttrVals.add(attrVal);
}
}
Vector<Attribute> attrs = new Vector<>();
for (ASN1ObjectIdentifier attrType : subjectDirAttrsControl.getTypes()) {
if (ObjectIdentifiers.DN_DATE_OF_BIRTH.equals(attrType)) {
if (dateOfBirth != null) {
String timeStirng = dateOfBirth.getTimeString();
if (!SubjectDnSpec.PATTERN_DATE_OF_BIRTH.matcher(timeStirng).matches()) {
throw new BadCertTemplateException("invalid dateOfBirth " + timeStirng);
}
attrs.add(new Attribute(attrType, new DERSet(dateOfBirth)));
continue;
}
} else if (ObjectIdentifiers.DN_PLACE_OF_BIRTH.equals(attrType)) {
if (placeOfBirth != null) {
ASN1Encodable attrVal = new DERUTF8String(placeOfBirth);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
continue;
}
} else if (ObjectIdentifiers.DN_GENDER.equals(attrType)) {
if (gender != null && !gender.isEmpty()) {
char ch = gender.charAt(0);
if (!(gender.length() == 1 && (ch == 'f' || ch == 'F' || ch == 'm' || ch == 'M'))) {
throw new BadCertTemplateException("invalid gender " + gender);
}
ASN1Encodable attrVal = new DERPrintableString(gender);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
continue;
}
} else if (ObjectIdentifiers.DN_COUNTRY_OF_CITIZENSHIP.equals(attrType)) {
if (!countryOfCitizenshipList.isEmpty()) {
for (String country : countryOfCitizenshipList) {
if (!SubjectDnSpec.isValidCountryAreaCode(country)) {
throw new BadCertTemplateException("invalid countryOfCitizenship code " + country);
}
ASN1Encodable attrVal = new DERPrintableString(country);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
}
continue;
}
} else if (ObjectIdentifiers.DN_COUNTRY_OF_RESIDENCE.equals(attrType)) {
if (!countryOfResidenceList.isEmpty()) {
for (String country : countryOfResidenceList) {
if (!SubjectDnSpec.isValidCountryAreaCode(country)) {
throw new BadCertTemplateException("invalid countryOfResidence code " + country);
}
ASN1Encodable attrVal = new DERPrintableString(country);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
}
continue;
}
} else if (otherAttrs.containsKey(attrType)) {
for (ASN1Encodable attrVal : otherAttrs.get(attrType)) {
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
}
continue;
}
throw new BadCertTemplateException("could not process type " + attrType.getId() + " in extension SubjectDirectoryAttributes");
}
SubjectDirectoryAttributes subjDirAttrs = new SubjectDirectoryAttributes(attrs);
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), subjDirAttrs);
values.addExtension(type, extValue);
occurences.remove(type);
}
// Basic Constraints
// processed by the CA
// Name Constraints
type = Extension.nameConstraints;
if (nameConstraints != null) {
if (occurences.remove(type)) {
values.addExtension(type, nameConstraints);
}
}
// PolicyConstrains
type = Extension.policyConstraints;
if (policyConstraints != null) {
if (occurences.remove(type)) {
values.addExtension(type, policyConstraints);
}
}
// ExtendedKeyUsage
// processed by CA
// CRL Distribution Points
// processed by the CA
// Inhibit anyPolicy
type = Extension.inhibitAnyPolicy;
if (inhibitAnyPolicy != null) {
if (occurences.remove(type)) {
values.addExtension(type, inhibitAnyPolicy);
}
}
// Freshest CRL
// processed by the CA
// Authority Information Access
// processed by the CA
// Subject Information Access
// processed by the CA
// Admission
type = ObjectIdentifiers.id_extension_admission;
if (occurences.contains(type) && admission != null) {
if (admission.isInputFromRequestRequired()) {
Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("No Admission extension is contained in the request");
}
Admissions[] reqAdmissions = org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax.getInstance(extension.getParsedValue()).getContentsOfAdmissions();
final int n = reqAdmissions.length;
List<List<String>> reqRegNumsList = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
Admissions reqAdmission = reqAdmissions[i];
ProfessionInfo[] reqPis = reqAdmission.getProfessionInfos();
List<String> reqNums = new ArrayList<>(reqPis.length);
reqRegNumsList.add(reqNums);
for (ProfessionInfo reqPi : reqPis) {
String reqNum = reqPi.getRegistrationNumber();
reqNums.add(reqNum);
}
}
values.addExtension(type, admission.getExtensionValue(reqRegNumsList));
occurences.remove(type);
} else {
values.addExtension(type, admission.getExtensionValue(null));
occurences.remove(type);
}
}
// OCSP Nocheck
// processed by the CA
// restriction
type = ObjectIdentifiers.id_extension_restriction;
if (restriction != null) {
if (occurences.remove(type)) {
values.addExtension(type, restriction);
}
}
// AdditionalInformation
type = ObjectIdentifiers.id_extension_additionalInformation;
if (additionalInformation != null) {
if (occurences.remove(type)) {
values.addExtension(type, additionalInformation);
}
}
// ValidityModel
type = ObjectIdentifiers.id_extension_validityModel;
if (validityModel != null) {
if (occurences.remove(type)) {
values.addExtension(type, validityModel);
}
}
// PrivateKeyUsagePeriod
type = Extension.privateKeyUsagePeriod;
if (occurences.contains(type)) {
Date tmpNotAfter;
if (privateKeyUsagePeriod == null) {
tmpNotAfter = notAfter;
} else {
tmpNotAfter = privateKeyUsagePeriod.add(notBefore);
if (tmpNotAfter.after(notAfter)) {
tmpNotAfter = notAfter;
}
}
ASN1EncodableVector vec = new ASN1EncodableVector();
vec.add(new DERTaggedObject(false, 0, new DERGeneralizedTime(notBefore)));
vec.add(new DERTaggedObject(false, 1, new DERGeneralizedTime(tmpNotAfter)));
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
values.addExtension(type, extValue);
occurences.remove(type);
}
// QCStatements
type = Extension.qCStatements;
if (occurences.contains(type) && (qcStatments != null || qcStatementsOption != null)) {
if (qcStatments != null) {
values.addExtension(type, qcStatments);
occurences.remove(type);
} else if (requestedExtensions != null && qcStatementsOption != null) {
// extract the euLimit data from request
Extension extension = requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("No QCStatement extension is contained in the request");
}
ASN1Sequence seq = ASN1Sequence.getInstance(extension.getParsedValue());
Map<String, int[]> qcEuLimits = new HashMap<>();
final int n = seq.size();
for (int i = 0; i < n; i++) {
QCStatement stmt = QCStatement.getInstance(seq.getObjectAt(i));
if (!ObjectIdentifiers.id_etsi_qcs_QcLimitValue.equals(stmt.getStatementId())) {
continue;
}
MonetaryValue monetaryValue = MonetaryValue.getInstance(stmt.getStatementInfo());
int amount = monetaryValue.getAmount().intValue();
int exponent = monetaryValue.getExponent().intValue();
Iso4217CurrencyCode currency = monetaryValue.getCurrency();
String currencyS = currency.isAlphabetic() ? currency.getAlphabetic().toUpperCase() : Integer.toString(currency.getNumeric());
qcEuLimits.put(currencyS, new int[] { amount, exponent });
}
ASN1EncodableVector vec = new ASN1EncodableVector();
for (QcStatementOption m : qcStatementsOption) {
if (m.getStatement() != null) {
vec.add(m.getStatement());
continue;
}
MonetaryValueOption monetaryOption = m.getMonetaryValueOption();
String currencyS = monetaryOption.getCurrencyString();
int[] limit = qcEuLimits.get(currencyS);
if (limit == null) {
throw new BadCertTemplateException("no EuLimitValue is specified for currency '" + currencyS + "'");
}
int amount = limit[0];
Range2Type range = monetaryOption.getAmountRange();
if (amount < range.getMin() || amount > range.getMax()) {
throw new BadCertTemplateException("amount for currency '" + currencyS + "' is not within [" + range.getMin() + ", " + range.getMax() + "]");
}
int exponent = limit[1];
range = monetaryOption.getExponentRange();
if (exponent < range.getMin() || exponent > range.getMax()) {
throw new BadCertTemplateException("exponent for currency '" + currencyS + "' is not within [" + range.getMin() + ", " + range.getMax() + "]");
}
MonetaryValue monetaryVale = new MonetaryValue(monetaryOption.getCurrency(), amount, exponent);
QCStatement qcStatment = new QCStatement(m.getStatementId(), monetaryVale);
vec.add(qcStatment);
}
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
values.addExtension(type, extValue);
occurences.remove(type);
} else {
throw new RuntimeException("should not reach here");
}
}
// BiometricData
type = Extension.biometricInfo;
if (occurences.contains(type) && biometricInfo != null) {
Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("no biometricInfo extension is contained in the request");
}
ASN1Sequence seq = ASN1Sequence.getInstance(extension.getParsedValue());
final int n = seq.size();
if (n < 1) {
throw new BadCertTemplateException("biometricInfo extension in request contains empty sequence");
}
ASN1EncodableVector vec = new ASN1EncodableVector();
for (int i = 0; i < n; i++) {
BiometricData bd = BiometricData.getInstance(seq.getObjectAt(i));
TypeOfBiometricData bdType = bd.getTypeOfBiometricData();
if (!biometricInfo.isTypePermitted(bdType)) {
throw new BadCertTemplateException("biometricInfo[" + i + "].typeOfBiometricData is not permitted");
}
ASN1ObjectIdentifier hashAlgo = bd.getHashAlgorithm().getAlgorithm();
if (!biometricInfo.isHashAlgorithmPermitted(hashAlgo)) {
throw new BadCertTemplateException("biometricInfo[" + i + "].hashAlgorithm is not permitted");
}
int expHashValueSize;
try {
expHashValueSize = AlgorithmUtil.getHashOutputSizeInOctets(hashAlgo);
} catch (NoSuchAlgorithmException ex) {
throw new CertprofileException("should not happen, unknown hash algorithm " + hashAlgo);
}
byte[] hashValue = bd.getBiometricDataHash().getOctets();
if (hashValue.length != expHashValueSize) {
throw new BadCertTemplateException("biometricInfo[" + i + "].biometricDataHash has incorrect length");
}
DERIA5String sourceDataUri = bd.getSourceDataUri();
switch(biometricInfo.getSourceDataUriOccurrence()) {
case FORBIDDEN:
sourceDataUri = null;
break;
case REQUIRED:
if (sourceDataUri == null) {
throw new BadCertTemplateException("biometricInfo[" + i + "].sourceDataUri is not specified in request but is required");
}
break;
case OPTIONAL:
break;
default:
throw new BadCertTemplateException("could not reach here, unknown tripleState");
}
AlgorithmIdentifier newHashAlg = new AlgorithmIdentifier(hashAlgo, DERNull.INSTANCE);
BiometricData newBiometricData = new BiometricData(bdType, newHashAlg, new DEROctetString(hashValue), sourceDataUri);
vec.add(newBiometricData);
}
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
values.addExtension(type, extValue);
occurences.remove(type);
}
// TlsFeature
type = ObjectIdentifiers.id_pe_tlsfeature;
if (tlsFeature != null) {
if (occurences.remove(type)) {
values.addExtension(type, tlsFeature);
}
}
// AuthorizationTemplate
type = ObjectIdentifiers.id_xipki_ext_authorizationTemplate;
if (authorizationTemplate != null) {
if (occurences.remove(type)) {
values.addExtension(type, authorizationTemplate);
}
}
// SMIME
type = ObjectIdentifiers.id_smimeCapabilities;
if (smimeCapabilities != null) {
if (occurences.remove(type)) {
values.addExtension(type, smimeCapabilities);
}
}
// constant extensions
if (constantExtensions != null) {
for (ASN1ObjectIdentifier m : constantExtensions.keySet()) {
if (!occurences.remove(m)) {
continue;
}
ExtensionValue extensionValue = constantExtensions.get(m);
if (extensionValue != null) {
values.addExtension(m, extensionValue);
}
}
}
ExtensionValues extraExtensions = getExtraExtensions(extensionOccurences, requestedSubject, grantedSubject, requestedExtensions, notBefore, notAfter, caInfo);
if (extraExtensions != null) {
for (ASN1ObjectIdentifier m : extraExtensions.getExtensionTypes()) {
values.addExtension(m, extraExtensions.getExtensionValue(m));
}
}
return values;
}
use of com.github.zhenwei.core.asn1.x509.AlgorithmIdentifier in project xipki by xipki.
the class CmpRequestor method verifyProtection.
private ProtectionVerificationResult verifyProtection(String tid, GeneralPKIMessage pkiMessage) throws CMPException, InvalidKeyException, OperatorCreationException {
ProtectedPKIMessage protectedMsg = new ProtectedPKIMessage(pkiMessage);
if (protectedMsg.hasPasswordBasedMacProtection()) {
LOG.warn("NOT_SIGNAUTRE_BASED: {}", pkiMessage.getHeader().getProtectionAlg().getAlgorithm().getId());
return new ProtectionVerificationResult(null, ProtectionResult.NOT_SIGNATURE_BASED);
}
PKIHeader header = protectedMsg.getHeader();
if (recipientName != null) {
boolean authorizedResponder = true;
if (header.getSender().getTagNo() != GeneralName.directoryName) {
authorizedResponder = false;
} else {
X500Name msgSender = X500Name.getInstance(header.getSender().getName());
authorizedResponder = recipientName.equals(msgSender);
}
if (!authorizedResponder) {
LOG.warn("tid={}: not authorized responder '{}'", tid, header.getSender());
return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
}
}
AlgorithmIdentifier protectionAlgo = protectedMsg.getHeader().getProtectionAlg();
if (!responder.getSigAlgoValidator().isAlgorithmPermitted(protectionAlgo)) {
String algoName;
try {
algoName = AlgorithmUtil.getSignatureAlgoName(protectionAlgo);
} catch (NoSuchAlgorithmException ex) {
algoName = protectionAlgo.getAlgorithm().getId();
}
LOG.warn("tid={}: response protected by untrusted protection algorithm '{}'", tid, algoName);
return new ProtectionVerificationResult(null, ProtectionResult.INVALID);
}
X509Certificate cert = responder.getCert();
ContentVerifierProvider verifierProvider = securityFactory.getContentVerifierProvider(cert);
if (verifierProvider == null) {
LOG.warn("tid={}: not authorized responder '{}'", tid, header.getSender());
return new ProtectionVerificationResult(cert, ProtectionResult.SENDER_NOT_AUTHORIZED);
}
boolean signatureValid = protectedMsg.verify(verifierProvider);
ProtectionResult protRes = signatureValid ? ProtectionResult.VALID : ProtectionResult.INVALID;
return new ProtectionVerificationResult(cert, protRes);
}
use of com.github.zhenwei.core.asn1.x509.AlgorithmIdentifier in project xipki by xipki.
the class PrivateKeyCryptor method decrypt.
PrivateKey decrypt(PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo) throws P11TokenException {
ParamUtil.requireNonNull("encryptedPrivateKeyInfo", encryptedPrivateKeyInfo);
PrivateKeyInfo privateKeyInfo;
synchronized (decryptorProvider) {
try {
privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptorProvider);
} catch (PKCSException ex) {
throw new P11TokenException(ex.getMessage(), ex);
}
}
AlgorithmIdentifier keyAlg = privateKeyInfo.getPrivateKeyAlgorithm();
ASN1ObjectIdentifier keyAlgOid = keyAlg.getAlgorithm();
String algoName;
if (PKCSObjectIdentifiers.rsaEncryption.equals(keyAlgOid)) {
algoName = "RSA";
} else if (X9ObjectIdentifiers.id_dsa.equals(keyAlgOid)) {
algoName = "DSA";
} else if (X9ObjectIdentifiers.id_ecPublicKey.equals(keyAlgOid)) {
algoName = "EC";
} else {
throw new P11TokenException("unknown private key algorithm " + keyAlgOid.getId());
}
try {
KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance(algoName, "BC");
return keyFactory.generatePrivate(keySpec);
} catch (IOException | NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException ex) {
throw new P11TokenException(ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
use of com.github.zhenwei.core.asn1.x509.AlgorithmIdentifier in project xipki by xipki.
the class OcspStatusCmd method processResponse.
@Override
protected Object processResponse(OCSPResp response, X509Certificate respIssuer, IssuerHash issuerHash, List<BigInteger> serialNumbers, Map<BigInteger, byte[]> encodedCerts) throws Exception {
ParamUtil.requireNonNull("response", response);
ParamUtil.requireNonNull("issuerHash", issuerHash);
ParamUtil.requireNonNull("serialNumbers", serialNumbers);
BasicOCSPResp basicResp = OcspUtils.extractBasicOcspResp(response);
boolean extendedRevoke = basicResp.getExtension(ObjectIdentifiers.id_pkix_ocsp_extendedRevoke) != null;
SingleResp[] singleResponses = basicResp.getResponses();
if (singleResponses == null || singleResponses.length == 0) {
throw new CmdFailure("received no status from server");
}
final int n = singleResponses.length;
if (n != serialNumbers.size()) {
throw new CmdFailure("received status with " + n + " single responses from server, but " + serialNumbers.size() + " were requested");
}
Date[] thisUpdates = new Date[n];
for (int i = 0; i < n; i++) {
thisUpdates[i] = singleResponses[i].getThisUpdate();
}
// check the signature if available
if (null == basicResp.getSignature()) {
println("response is not signed");
} else {
X509CertificateHolder[] responderCerts = basicResp.getCerts();
if (responderCerts == null || responderCerts.length < 1) {
throw new CmdFailure("no responder certificate is contained in the response");
}
ResponderID respId = basicResp.getResponderId().toASN1Primitive();
X500Name respIdByName = respId.getName();
byte[] respIdByKey = respId.getKeyHash();
X509CertificateHolder respSigner = null;
for (X509CertificateHolder cert : responderCerts) {
if (respIdByName != null) {
if (cert.getSubject().equals(respIdByName)) {
respSigner = cert;
}
} else {
byte[] spkiSha1 = HashAlgo.SHA1.hash(cert.getSubjectPublicKeyInfo().getPublicKeyData().getBytes());
if (Arrays.equals(respIdByKey, spkiSha1)) {
respSigner = cert;
}
}
if (respSigner != null) {
break;
}
}
if (respSigner == null) {
throw new CmdFailure("no responder certificate match the ResponderId");
}
boolean validOn = true;
for (Date thisUpdate : thisUpdates) {
validOn = respSigner.isValidOn(thisUpdate);
if (!validOn) {
throw new CmdFailure("responder certificate is not valid on " + thisUpdate);
}
}
if (validOn) {
PublicKey responderPubKey = KeyUtil.generatePublicKey(respSigner.getSubjectPublicKeyInfo());
ContentVerifierProvider cvp = securityFactory.getContentVerifierProvider(responderPubKey);
boolean sigValid = basicResp.isSignatureValid(cvp);
if (!sigValid) {
throw new CmdFailure("response is equipped with invalid signature");
}
// verify the OCSPResponse signer
if (respIssuer != null) {
boolean certValid = true;
X509Certificate jceRespSigner = X509Util.toX509Cert(respSigner.toASN1Structure());
if (X509Util.issues(respIssuer, jceRespSigner)) {
try {
jceRespSigner.verify(respIssuer.getPublicKey());
} catch (SignatureException ex) {
certValid = false;
}
}
if (!certValid) {
throw new CmdFailure("response is equipped with valid signature but the" + " OCSP signer is not trusted");
}
} else {
println("response is equipped with valid signature");
}
// end if(respIssuer)
}
if (verbose.booleanValue()) {
println("responder is " + X509Util.getRfc4519Name(responderCerts[0].getSubject()));
}
}
for (int i = 0; i < n; i++) {
if (n > 1) {
println("---------------------------- " + i + "----------------------------");
}
SingleResp singleResp = singleResponses[i];
CertificateStatus singleCertStatus = singleResp.getCertStatus();
String status;
if (singleCertStatus == null) {
status = "good";
} else if (singleCertStatus instanceof RevokedStatus) {
RevokedStatus revStatus = (RevokedStatus) singleCertStatus;
Date revTime = revStatus.getRevocationTime();
Date invTime = null;
Extension ext = singleResp.getExtension(Extension.invalidityDate);
if (ext != null) {
invTime = ASN1GeneralizedTime.getInstance(ext.getParsedValue()).getDate();
}
if (revStatus.hasRevocationReason()) {
int reason = revStatus.getRevocationReason();
if (extendedRevoke && reason == CrlReason.CERTIFICATE_HOLD.getCode() && revTime.getTime() == 0) {
status = "unknown (RFC6960)";
} else {
status = StringUtil.concatObjects("revoked, reason = ", CrlReason.forReasonCode(reason).getDescription(), ", revocationTime = ", revTime, (invTime == null ? "" : ", invalidityTime = " + invTime));
}
} else {
status = "revoked, no reason, revocationTime = " + revTime;
}
} else if (singleCertStatus instanceof UnknownStatus) {
status = "unknown (RFC2560)";
} else {
status = "ERROR";
}
StringBuilder msg = new StringBuilder();
CertificateID certId = singleResp.getCertID();
HashAlgo hashAlgo = HashAlgo.getNonNullInstance(certId.getHashAlgOID());
boolean issuerMatch = issuerHash.match(hashAlgo, certId.getIssuerNameHash(), certId.getIssuerKeyHash());
BigInteger serialNumber = certId.getSerialNumber();
msg.append("issuer matched: ").append(issuerMatch);
msg.append("\nserialNumber: ").append(LogUtil.formatCsn(serialNumber));
msg.append("\nCertificate status: ").append(status);
if (verbose.booleanValue()) {
msg.append("\nthisUpdate: ").append(singleResp.getThisUpdate());
msg.append("\nnextUpdate: ").append(singleResp.getNextUpdate());
Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash);
if (extension != null) {
msg.append("\nCertHash is provided:\n");
ASN1Encodable extensionValue = extension.getParsedValue();
CertHash certHash = CertHash.getInstance(extensionValue);
ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm();
byte[] hashValue = certHash.getCertificateHash();
msg.append("\tHash algo : ").append(hashAlgOid.getId()).append("\n");
msg.append("\tHash value: ").append(Hex.encode(hashValue)).append("\n");
if (encodedCerts != null) {
byte[] encodedCert = encodedCerts.get(serialNumber);
MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId());
byte[] expectedHashValue = md.digest(encodedCert);
if (Arrays.equals(expectedHashValue, hashValue)) {
msg.append("\tThis matches the requested certificate");
} else {
msg.append("\tThis differs from the requested certificate");
}
}
}
// end if (extension != null)
extension = singleResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff);
if (extension != null) {
ASN1Encodable extensionValue = extension.getParsedValue();
ASN1GeneralizedTime time = ASN1GeneralizedTime.getInstance(extensionValue);
msg.append("\nArchive-CutOff: ");
msg.append(time.getTimeString());
}
AlgorithmIdentifier sigAlg = basicResp.getSignatureAlgorithmID();
if (sigAlg == null) {
msg.append(("\nresponse is not signed"));
} else {
String sigAlgName = AlgorithmUtil.getSignatureAlgoName(sigAlg);
if (sigAlgName == null) {
sigAlgName = "unknown";
}
msg.append("\nresponse is signed with ").append(sigAlgName);
}
// extensions
msg.append("\nExtensions: ");
List<?> extensionOids = basicResp.getExtensionOIDs();
if (extensionOids == null || extensionOids.size() == 0) {
msg.append("-");
} else {
int size = extensionOids.size();
for (int j = 0; j < size; j++) {
ASN1ObjectIdentifier extensionOid = (ASN1ObjectIdentifier) extensionOids.get(j);
String name = EXTENSION_OIDNAME_MAP.get(extensionOid);
if (name == null) {
msg.append(extensionOid.getId());
} else {
msg.append(name);
}
if (j != size - 1) {
msg.append(", ");
}
}
}
}
// end if (verbose.booleanValue())
println(msg.toString());
}
// end for
println("");
return null;
}
Aggregations