public BodyHasher newBodyHasher()

in main/src/main/java/org/apache/james/jdkim/DKIMVerifier.java [236:316]


    public BodyHasher newBodyHasher(Headers messageHeaders) throws FailException {
        List<String> fields = messageHeaders.getFields("DKIM-Signature");
        if (fields == null || fields.isEmpty()) {
            return null;
        }

        // For each DKIM-signature we prepare an hashjob.
        // We calculate all hashes concurrently so to read
        // the inputstream only once.
        Map<String, BodyHasherImpl> bodyHashJobs = new HashMap<>();
        Hashtable<String, FailException> signatureExceptions = new Hashtable<>();
        for (String signatureField : fields) {
            try {
                int pos = signatureField.indexOf(':');
                if (pos > 0) {
                    String v = signatureField.substring(pos + 1);
                    SignatureRecord signatureRecord = null;
                    try {
                        signatureRecord = newSignatureRecord(v);
                    } catch (IllegalStateException e) {
                        throw new PermFailException("Invalid signature record: " + e.getMessage(), signatureRecord, e);
                    }

                    // Specification say we MAY refuse to verify the signature.
                    if (signatureRecord.getSignatureTimestamp() != null) {
                        long signedTime = signatureRecord.getSignatureTimestamp();
                        long elapsed = (System.currentTimeMillis() / 1000 - signedTime);
                        if (elapsed < -3600 * 24 * 365 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / (3600 * 24 * 365) + " years in the future.", signatureRecord);
                        } else if (elapsed < -3600 * 24 * 30 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / (3600 * 24 * 30) + " months in the future.", signatureRecord);
                        } else if (elapsed < -3600 * 24 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / (3600 * 24) + " days in the future.", signatureRecord);
                        } else if (elapsed < -3600 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / 3600 + " hours in the future.", signatureRecord);
                        } else if (elapsed < -60 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / 60 + " minutes in the future.", signatureRecord);
                        } else if (elapsed < 0) {
                            throw new PermFailException("Signature date is "
                                    + elapsed + " seconds in the future.", signatureRecord);
                        }
                    }

                    // TODO here we could check more parameters for
                    // validation before running a network operation like the
                    // dns lookup.
                    // e.g: the canonicalization method could be checked now.
                    PublicKeyRecord publicKeyRecord = publicRecordLookup(signatureRecord);

                    List<CharSequence> signedHeadersList = signatureRecord.getHeaders();

                    byte[] decoded = signatureRecord.getSignature();
                    signatureVerify(messageHeaders, signatureRecord, decoded,
                            publicKeyRecord, signedHeadersList);

                    // we track all canonicalizations+limit+bodyHash we
                    // see so to be able to check all of them in a single
                    // stream run.
                    BodyHasherImpl bhj = newBodyHasher(signatureRecord);

                    bodyHashJobs.put(signatureField, bhj);

                } else {
                    throw new PermFailException(
                            "unexpected bad signature field");
                }
            } catch (TempFailException | PermFailException e) {
                signatureExceptions.put(signatureField, e);
            } catch (RuntimeException e) {
                signatureExceptions.put(signatureField, new PermFailException(
                        "Unexpected exception processing signature", e));
            }
        }

        return new CompoundBodyHasher(bodyHashJobs, signatureExceptions);
    }