All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.idsec.signservice.security.sign.pdf.impl.DefaultPDFSigner Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2019-2024 IDsec Solutions AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package se.idsec.signservice.security.sign.pdf.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import se.idsec.signservice.security.sign.pdf.PDFSigner;
import se.idsec.signservice.security.sign.pdf.PDFSignerParameters;
import se.idsec.signservice.security.sign.pdf.PDFSignerResult;
import se.idsec.signservice.security.sign.pdf.configuration.PDFAlgorithmRegistry;
import se.idsec.signservice.security.sign.pdf.utils.PDFSigningProcessor;
import se.swedenconnect.security.credential.PkiCredential;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.List;

/**
 * Default PDF Signer for signing PDF documents
 *
 * @author Martin Lindström ([email protected])
 * @author Stefan Santesson ([email protected])
 */
@Slf4j
public class DefaultPDFSigner implements PDFSigner {

  /** The signing credential. */
  private final PkiCredential signingCredential;

  /** The signature algorithm. */
  private final String signatureAlgorithm;

  /**
   * Should the certificate chain/path be included in the signature (if available from
   * {@link PkiCredential#getCertificateChain()}). The default is {@code false} (only the entity certificate is
   * included).
   */
  private boolean includeCertificateChain = false;

  /**
   * Constructor.
   *
   * @param signingCredential the signing credential to use
   * @param signatureAlgorithm the URI identifier for the requested signature algorithm
   * @throws NoSuchAlgorithmException if the supplied signature algorithm is not supported
   */
  public DefaultPDFSigner(final PkiCredential signingCredential, final String signatureAlgorithm)
      throws NoSuchAlgorithmException {
    this.signingCredential = signingCredential;
    if (PDFAlgorithmRegistry.isAlgoSupported(signatureAlgorithm)) {
      this.signatureAlgorithm = signatureAlgorithm;
    }
    else {
      throw new NoSuchAlgorithmException("Signature algorithm is not supported");
    }
  }

  /**
   * Constructor.
   *
   * @param signingCredential the signing credential to use
   * @param signatureAlgorithm the object identifier for the requested signature algorithm
   * @throws NoSuchAlgorithmException if the supplied signature algorithm is not supported
   */
  public DefaultPDFSigner(final PkiCredential signingCredential, final AlgorithmIdentifier signatureAlgorithm)
      throws NoSuchAlgorithmException {
    this.signingCredential = signingCredential;
    this.signatureAlgorithm = PDFAlgorithmRegistry.getAlgorithmURI(signatureAlgorithm);
  }

  /**
   * Sets whether the certificate chain/path be included in the signature (if available from
   * {@link PkiCredential#getCertificateChain()}). The default is {@code false} (only the entity certificate is
   * included).
   *
   * @param includeCertificateChain whether the certificate chain should be included
   */
  public void setIncludeCertificateChain(final boolean includeCertificateChain) {
    this.includeCertificateChain = includeCertificateChain;
  }

  /** {@inheritDoc} */
  @Override
  public PkiCredential getSigningCredential() {
    return this.signingCredential;
  }

  /** {@inheritDoc} */
  @Override
  public PDFSignerResult sign(final byte[] document) throws SignatureException {
    return this.sign(document, new PDFSignerParameters());
  }

  /** {@inheritDoc} */
  @Override
  public PDFSignerResult sign(final byte[] document, final PDFSignerParameters parameters) throws SignatureException {

    if (parameters == null) {
      return this.sign(document);
    }
    try (final PDDocument pdfDocument = Loader.loadPDF(document)) {
      final List signingCertChain = this.includeCertificateChain
          ? this.signingCredential.getCertificateChain()
          : Collections.singletonList(this.signingCredential.getCertificate());

      final DefaultPDFBoxSignatureInterface signatureProvider = new DefaultPDFBoxSignatureInterface(
          this.signingCredential.getPrivateKey(),
          signingCertChain,
          this.signatureAlgorithm,
          parameters.getPadesType());

      final long signingTime = System.currentTimeMillis();

      final PDFSigningProcessor.Result signatureResult =
          PDFSigningProcessor.signPdfDocument(pdfDocument, signatureProvider, signingTime,
              parameters.getVisibleSignatureImage());

      final DefaultPDFSignerResult result = new DefaultPDFSignerResult();
      result.setSignedDocument(signatureResult.getDocument());
      result.setSignerCertificate(this.signingCredential.getCertificate());
      if (this.includeCertificateChain) {
        result.setSignerCertificateChain(signingCertChain);
      }
      result.setSigningTime(signingTime);
      result.setSignedAttributes(signatureResult.getCmsSignedAttributes());
      result.setSignedData(signatureResult.getCmsSignedData());
      return result;
    }
    catch (final IOException e) {
      final String msg = String.format("Failed to load PDF document to sign - %s", e.getMessage());
      log.error("{}", msg, e);
      throw new SignatureException(msg, e);
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy