public FormValidation verifySignature()

in core/src/main/java/jenkins/util/JSONSignatureValidator.java [58:141]


    public FormValidation verifySignature(JSONObject o) throws IOException {
        try {
            FormValidation warning = null;

            JSONObject signature = o.getJSONObject("signature");
            if (signature.isNullObject()) {
                return FormValidation.error("No signature block found in "+name);
            }
            o.remove("signature");

            List<X509Certificate> certs = new ArrayList<>();
            {// load and verify certificates
                CertificateFactory cf = CertificateFactory.getInstance("X509");
                for (Object cert : signature.getJSONArray("certificates")) {
                    try {
                        X509Certificate c = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(Base64.getDecoder().decode(cert.toString().getBytes(StandardCharsets.UTF_8))));
                        try {
                            c.checkValidity();
                        } catch (CertificateExpiredException e) { // even if the certificate isn't valid yet, we'll proceed it anyway
                            warning = FormValidation.warning(e, String.format("Certificate %s has expired in %s", cert.toString(), name));
                        } catch (CertificateNotYetValidException e) {
                            warning = FormValidation.warning(e, String.format("Certificate %s is not yet valid in %s", cert.toString(), name));
                        }
                        LOGGER.log(Level.FINE, "Add certificate found in JSON document:\n\tsubjectDN: {0}\n\tissuer: {1}\n\tnotBefore: {2}\n\tnotAfter: {3}",
                                new Object[] { c.getSubjectDN(), c.getIssuerDN(), c.getNotBefore(), c.getNotAfter() });
                        LOGGER.log(Level.FINEST, () -> "Certificate from JSON document: " + c);
                        certs.add(c);
                    } catch (IllegalArgumentException ex) {
                        throw new IOException("Could not decode certificate", ex);
                    }
                }

                CertificateUtil.validatePath(certs, loadTrustAnchors(cf));
            }

            if (certs.isEmpty()) {
                return FormValidation.error("No certificate found in %s. Cannot verify the signature", name);
            }

            // check the better digest first
            FormValidation resultSha512 = null;
            try {
                MessageDigest digest = MessageDigest.getInstance("SHA-512");
                Signature sig = Signature.getInstance("SHA512withRSA");
                sig.initVerify(certs.get(0));
                resultSha512 = checkSpecificSignature(o, signature, digest, "correct_digest512", sig, "correct_signature512", "SHA-512");
                switch (resultSha512.kind) {
                    case ERROR:
                        return resultSha512;
                    case WARNING:
                        LOGGER.log(Level.INFO, "JSON data source '" + name + "' does not provide a SHA-512 content checksum or signature. Looking for SHA-1.");
                        break;
                    case OK:
                        // fall through
                }
            } catch (NoSuchAlgorithmException nsa) {
                LOGGER.log(Level.WARNING, "Failed to verify potential SHA-512 digest/signature, falling back to SHA-1", nsa);
            }

            // if we get here, SHA-512 passed, wasn't provided, or the JRE is terrible.

            MessageDigest digest = MessageDigest.getInstance("SHA1");
            Signature sig = Signature.getInstance("SHA1withRSA");
            sig.initVerify(certs.get(0));
            FormValidation resultSha1 = checkSpecificSignature(o, signature, digest, "correct_digest", sig, "correct_signature", "SHA-1");

            switch (resultSha1.kind) {
                case ERROR:
                    return resultSha1;
                case WARNING:
                    if (resultSha512.kind == FormValidation.Kind.WARNING) {
                        // neither signature provided
                        return FormValidation.error("No correct_signature or correct_signature512 entry found in '" + name + "'.");
                    }
                case OK:
                    // fall through
            }

            if (warning!=null)  return warning;
            return FormValidation.ok();
        } catch (GeneralSecurityException e) {
            return FormValidation.error(e, "Signature verification failed in "+name);
        }
    }