/**
   * Signs a SoapMessage with the holder-of-key configuration provided on class creation. This
   * method changes the SoapMessage.
   *
   * @param message cannot be null
   * @return The signed SoapMessage
   * @throws ParserException
   * @throws SignatureException
   */
  @Override
  public final SoapMessage sign(SoapMessage message) throws ParserException, SignatureException {

    assert message != null;

    Provider securityProvider = holderOfKeyConfig.getSecurityProvider();
    XMLSignatureFactory xmlSigFactory =
        (securityProvider != null)
            ? XMLSignatureFactory.getInstance("DOM", securityProvider)
            : XMLSignatureFactory.getInstance();

    try {
      String bodyUuid = createSoapBodyUuid(message);
      CanonicalizationMethod canonicalizationMethod =
          xmlSigFactory.newCanonicalizationMethod(
              CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null);
      SignatureMethod signatureMethod = getSignatureMethod(xmlSigFactory);
      ArrayList<String> refList = new ArrayList<String>();
      refList.add(bodyUuid);
      refList.add(createTimestampUuid(message));
      List<Reference> references = createSignatureReferences(xmlSigFactory, refList);
      SignedInfo signedInfo =
          xmlSigFactory.newSignedInfo(canonicalizationMethod, signatureMethod, references);

      KeyInfoFactory kif = KeyInfoFactory.getInstance();
      KeyInfo ki =
          kif.newKeyInfo(
              Collections.singletonList(new DOMStructure(createKeyInfoContent(message))));

      XMLSignature signature =
          xmlSigFactory.newXMLSignature(signedInfo, ki, null, addUseKeySignatureId(message), null);

      DOMSignContext dsc =
          new DOMSignContext(
              holderOfKeyConfig.getPrivateKey(), message.getHeader().getFirstChild());
      dsc.putNamespacePrefix(XMLSignature.XMLNS, DIGITAL_SIGNATURE_NAMESPACE_PREFIX);

      signature.sign(dsc);

      log.debug("Message with SOAPBody id: " + bodyUuid + " is signed.");
    } catch (NoSuchAlgorithmException e) {
      log.debug(CREATING_SIGNATURE_ERR_MSG);
      throw new SignatureException(CREATING_SIGNATURE_ERR_MSG, e);
    } catch (InvalidAlgorithmParameterException e) {
      log.debug(CREATING_SIGNATURE_ERR_MSG);
      throw new SignatureException(CREATING_SIGNATURE_ERR_MSG, e);
    } catch (MarshalException e) {
      log.debug(CREATING_SIGNATURE_ERR_MSG);
      throw new SignatureException(CREATING_SIGNATURE_ERR_MSG, e);
    } catch (XMLSignatureException e) {
      log.debug(CREATING_SIGNATURE_ERR_MSG);
      throw new SignatureException(CREATING_SIGNATURE_ERR_MSG, e);
    }

    return message;
  }
 /**
  * @param xmlSigFactory
  * @return return the signature method based on the public key size
  * @throws NoSuchAlgorithmException
  * @throws InvalidAlgorithmParameterException
  */
 private SignatureMethod getSignatureMethod(XMLSignatureFactory xmlSigFactory)
     throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
   SignatureMethod signatureMethod;
   PublicKey publicKey = holderOfKeyConfig.getCertificate().getPublicKey();
   if (publicKey instanceof RSAPublicKey
       && ((RSAPublicKey) publicKey).getModulus().bitCount() <= 512) {
     signatureMethod = xmlSigFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
   } else {
     signatureMethod = xmlSigFactory.newSignatureMethod(RSA_WITH_SHA512, null);
   }
   return signatureMethod;
 }