ocspresponse.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 731 行 · 第 1/2 页

JAVA
731
字号
            boolean usedCertFromResponse = false;            if (x509Certs != null && x509Certs[0] != null) {                /*                 * If there is a certificate specified in the response having                 * "OCSP Signing" in the extended key usages field, we verify                 * it first and if it is trusted then use it to verify the                 * signature on the OCSP response.                 */                X509Certificate certFromResponse = null;                for (int i = 0; i < x509Certs.length; i++) {                    int extKeyUsage = x509Certs[i].getExtKeyUsage();                    if (extKeyUsage != -1 &&                            (extKeyUsage & X509Certificate.OCSP_EXT_KEY_USAGE)                                 == extKeyUsage) {                        certFromResponse = x509Certs[i];                        break;                    }                }                if (certFromResponse != null) {                    /*                     * Check whether the cert returned by the responder                     * is trusted.                     */                    Vector respCertVector = new Vector(1);                    respCertVector.addElement(certFromResponse);                    try {                        /*                         * Check if the key used to sign the response                         * is issued by known CA.                          */                        X509Certificate.verifyChain(respCertVector,                                        X509Certificate.DIGITAL_SIG_KEY_USAGE,                                        X509Certificate.OCSP_EXT_KEY_USAGE,                                        keyStore, null);                        /*                         * When checking the signature, use the certificate                         * from the response first.                         */                        certs.insertElementAt(x509Certs[0], 0);                        usedCertFromResponse = true;                    } catch (CertificateException ce) {                        /*                         * The key used to sign the response can belong to                         * the CA who issued the certificate in question.                         */                        respCertVector.addElement(issuerCert);                        try {                            X509Certificate.verifyChain(respCertVector,                                        X509Certificate.DIGITAL_SIG_KEY_USAGE,                                        X509Certificate.OCSP_EXT_KEY_USAGE,                                        keyStore, null);                            certs.insertElementAt(x509Certs[0], 0);                            usedCertFromResponse = true;                        } catch (CertificateException cex) {                            // ignore, don't use the certificate from the resp.                        }                    }                }            }            if (certs != null) {                // Confirm that the signed response was generated using                // the public key from the trusted cert                boolean verified = false;                for (int i = 0; (!verified) && (i < certs.size()); i++) {                    try {                        X509Certificate currCert =                            (X509Certificate)certs.elementAt(i);                        verified = verifyResponse(responseDataDer,                            currCert.getPublicKey(), sigAlgId, signature);                    }  catch (SignatureException e) {                       /*                        * IMPL_NOTE: if the key usage does not include                        * KP_OCSP_SIGNING_OID then SignatureException                        * is thrown. We should check the key usages first                        * and remove this try-catch, but certificates                        * in certs vector don't contain this information.                        */                        verified = false;                    }                }                if (usedCertFromResponse) {                    /*                     * Remove the certificate we've previously added to certs                     * to prevent modification of the vector passed as a                     * parameter to this function.                     */                    certs.removeElementAt(0);                }                if (!verified) {                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {                        Logging.report(Logging.INFORMATION,                                LogChannels.LC_SECURITY,                                "Error verifying OCSP Responder's signature");                    }                    throw new OCSPException(                        OCSPException.CANNOT_VERIFY_SIGNATURE,                            "Error verifying OCSP Responder's signature");                }            } else {                // Need responder's cert in order to verify the signature                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {                    Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY,                               "Unable to verify OCSP Responder's signature");                }                throw new OCSPException(OCSPException.CANNOT_VERIFY_SIGNATURE,                    "Unable to verify OCSP Responder's signature");            }        } catch (OCSPException e) {            // e.printStackTrace();            throw e;        } catch (Exception e) {            throw new OCSPException(OCSPException.UNKNOWN_ERROR,                    e.getMessage());        }    }    private String parsex500Name(DerInputStream in) throws IOException {        /*         * X.500 names are a "SEQUENCE OF" RDNs, which means zero or         * more and order matters.  We scan them in order, which         * conventionally is big-endian.         */        DerValue[] nameseq = null;        byte[] derBytes = in.toByteArray();        try {            nameseq = in.getSequence(5);        } catch (IOException ioe) {            if (derBytes == null) {                nameseq = null;            } else {                DerValue derVal = new DerValue(DerValue.tag_Sequence,                                           derBytes);                derBytes = derVal.toByteArray();                nameseq = new DerInputStream(derBytes).getSequence(5);            }        }        if (nameseq == null) {            return null;        } else {            StringBuffer sb = new StringBuffer();            for (int i = 0; i < nameseq.length; i++) {                if (nameseq[i].tag != DerValue.tag_Set) {                     throw new IOException("X500 RDN");                 }                 DerInputStream dis = new DerInputStream(nameseq[i].toByteArray());                 DerValue[] avaset = dis.getSet(5);                 for (int j = 0; j < avaset.length; j++) {                     // Individual attribute value assertions are SEQUENCE of two values.                     // That'd be a "struct" outside of ASN.1.                     if (avaset[j].tag != DerValue.tag_Sequence) {                         throw new IOException("AVA not a sequence");                     }                     if (j != 0) {                         sb.append(" + ");                     }                     sb.append(avaset[j].data.getOID().toString());                     sb.append(avaset[j].data.getDerValue().getAsString());                     if (avaset[j].data.available() != 0) {                         throw new IOException("AVA, extra bytes = "                             + avaset[j].data.available());                     }                 }                sb.append(";");            }            return sb.toString();        }    }    /*     * Verify the signature of the OCSP response.     * The responder's cert is implicitly trusted.     */    private boolean verifyResponse(byte[] responseData, PublicKey pubKey,            AlgorithmId sigAlgId, byte[] signBytes)                    throws SignatureException, CertificateException {        try {            Signature respSignature = Signature.getInstance(sigAlgId.getName());            respSignature.initVerify(pubKey);            respSignature.update(responseData, 0, responseData.length);            if (respSignature.verify(signBytes)) {                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {                    Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY,                               "Verified signature of OCSP Responder");                }                return true;            } else {                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {                    Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY,                           "Error verifying signature of OCSP Responder");                }                return false;            }        } catch (InvalidKeyException ike) {            throw new SignatureException("Invalid key: " + ike.getMessage());        } catch (NoSuchAlgorithmException nsae) {            throw new SignatureException("Invalid algorithm: " +                                         nsae.getMessage());        }    }    /*     * Return the revocation status code for a given certificate.     */    // used by OCSPValidatorImpl    int getCertStatus() {        return singleResponse.getStatus();    }    // used by OCSPValidatorImpl    CertId getCertId() {        return singleResponse.getCertId();    }    /*     * Map a certificate's revocation status code to a string.     */    // used by OCSPValidatorImpl    static String certStatusToText(int certStatus) {        switch (certStatus)  {        case CertStatus.GOOD:            return "Good";        case CertStatus.REVOKED:            return "Revoked";        case CertStatus.UNKNOWN:            return "Unknown";        default:            return ("Unknown certificate status code: " + certStatus);        }    }    /*     * A class representing a single OCSP response.     */    private class SingleResponse {        private CertId certId;        private int certStatus;        private Date thisUpdate;        private Date nextUpdate;        private SingleResponse(DerValue der) throws IOException {            if (der.tag != DerValue.tag_Sequence) {                throw new IOException("Bad ASN.1 encoding in SingleResponse");            }            DerInputStream tmp = der.data;            certId = new CertId(tmp.getDerValue().data);            DerValue derVal = tmp.getDerValue();            short tag = (byte)(derVal.tag & 0x1f);            if (tag == CertStatus.GOOD) {                certStatus = CertStatus.GOOD;            } else if (tag == CertStatus.REVOKED) {                certStatus = CertStatus.REVOKED;                // RevokedInfo                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {                    Date revocationTime = derVal.data.getGeneralizedTime();                    Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY,                               "Revocation time: " + revocationTime);                }            } else if (tag == CertStatus.UNKNOWN) {                certStatus = CertStatus.UNKNOWN;            } else {                throw new IOException("Invalid certificate status: " + tag);            }            thisUpdate = tmp.getGeneralizedTime();            if (tmp.available() == 0)  {                // we are done            } else {                derVal = tmp.getDerValue();                tag = (byte)(derVal.tag & 0x1f);                if (tag == 0) {                    // next update                    nextUpdate = derVal.data.getGeneralizedTime();                    if (tmp.available() == 0)  {                        return;                    } else {                        derVal = tmp.getDerValue();                        tag = (byte)(derVal.tag & 0x1f);                    }                }                // ignore extensions            }            Date now = new Date();            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {                String until = "";                if (nextUpdate != null) {                    until = " until " + nextUpdate;                }                Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY,                    "Response's validity interval is from " +                            thisUpdate + until);            }            // Check that the test date is within the validity interval            if ((thisUpdate != null && (now.getTime() < thisUpdate.getTime())) ||                (nextUpdate != null && (now.getTime() > nextUpdate.getTime()))) {                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {                    Logging.report(Logging.INFORMATION, LogChannels.LC_SECURITY,                               "Response is unreliable: " +                                       "its validity interval is out-of-date");                }                                throw new IOException("Response is unreliable: its validity " +                    "interval is out-of-date");            }        }        /*         * Return the certificate's revocation status code         */        private int getStatus() {            return certStatus;        }        private CertId getCertId() {            return certId;        }        /**         * Construct a string representation of a single OCSP response.         */        public String toString() {            StringBuffer sb = new StringBuffer();            sb.append("SingleResponse:  \n");            sb.append(certId);            sb.append("\nCertStatus: ");            sb.append(certStatusToText(getCertStatus()));            sb.append("\n");            sb.append("thisUpdate is ");            sb.append(thisUpdate);            sb.append("\n");            if (nextUpdate != null) {                sb.append("nextUpdate is ");                sb.append(nextUpdate);                sb.append("\n");            }            return sb.toString();        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?