@Override
  public SignableXMLObject setSignature(
      SignableXMLObject signableXMLObject,
      String signatureAlgorithm,
      String digestAlgorithm,
      X509Credential cred)
      throws IdentityException {

    Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);
    signature.setSigningCredential(cred);
    signature.setSignatureAlgorithm(signatureAlgorithm);
    signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

    KeyInfo keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
    X509Data data = (X509Data) buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);
    X509Certificate cert = (X509Certificate) buildXMLObject(X509Certificate.DEFAULT_ELEMENT_NAME);

    String value;
    try {
      value = org.apache.xml.security.utils.Base64.encode(cred.getEntityCertificate().getEncoded());
    } catch (CertificateEncodingException e) {
      throw IdentityException.error("Error occurred while retrieving encoded cert", e);
    }

    cert.setValue(value);
    data.getX509Certificates().add(cert);
    keyInfo.getX509Datas().add(data);
    signature.setKeyInfo(keyInfo);

    signableXMLObject.setSignature(signature);
    ((SAMLObjectContentReference) signature.getContentReferences().get(0))
        .setDigestAlgorithm(digestAlgorithm);

    List<Signature> signatureList = new ArrayList<Signature>();
    signatureList.add(signature);

    MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
    Marshaller marshaller = marshallerFactory.getMarshaller(signableXMLObject);

    try {
      marshaller.marshall(signableXMLObject);
    } catch (MarshallingException e) {
      throw IdentityException.error("Unable to marshall the request", e);
    }

    org.apache.xml.security.Init.init();
    try {
      Signer.signObjects(signatureList);
    } catch (SignatureException e) {
      throw IdentityException.error("Error occurred while signing request", e);
    }

    return signableXMLObject;
  }
  /**
   * Sign the SAML AuthnRequest message
   *
   * @param logoutRequest
   * @param signatureAlgorithm
   * @param cred
   * @return
   * @throws SAMLSSOException
   */
  public static LogoutRequest setSignature(
      LogoutRequest logoutRequest, String signatureAlgorithm, X509Credential cred)
      throws SAMLSSOException {
    try {
      Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);
      signature.setSigningCredential(cred);
      signature.setSignatureAlgorithm(signatureAlgorithm);
      signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

      try {
        KeyInfo keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
        X509Data data = (X509Data) buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);
        org.opensaml.xml.signature.X509Certificate cert =
            (org.opensaml.xml.signature.X509Certificate)
                buildXMLObject(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME);
        String value =
            org.apache.xml.security.utils.Base64.encode(cred.getEntityCertificate().getEncoded());
        cert.setValue(value);
        data.getX509Certificates().add(cert);
        keyInfo.getX509Datas().add(data);
        signature.setKeyInfo(keyInfo);
      } catch (CertificateEncodingException e) {
        throw new SAMLSSOException("Error getting certificate", e);
      }

      logoutRequest.setSignature(signature);

      List<Signature> signatureList = new ArrayList<Signature>();
      signatureList.add(signature);

      // Marshall and Sign
      MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
      Marshaller marshaller = marshallerFactory.getMarshaller(logoutRequest);

      marshaller.marshall(logoutRequest);

      org.apache.xml.security.Init.init();
      Signer.signObjects(signatureList);
      return logoutRequest;

    } catch (Exception e) {
      throw new SAMLSSOException("Error while signing the Logout Request message", e);
    }
  }
  /**
   * Generates an XML Object representing an enveloped or detached XML Digital Signature.
   *
   * @param signatureAlgorithm the algorithm used to compute the signature
   * @param credential the signature signing credentials
   * @return an XML Object representing an enveloped or detached XML Digital Signature
   * @throws SSOException if an error occurs while getting the signature
   */
  private static Signature setSignatureRaw(String signatureAlgorithm, X509Credential credential)
      throws SSOException {
    Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);
    signature.setSigningCredential(credential);
    signature.setSignatureAlgorithm(signatureAlgorithm);
    signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

    try {
      KeyInfo keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
      X509Data data = (X509Data) buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);
      X509Certificate cert = (X509Certificate) buildXMLObject(X509Certificate.DEFAULT_ELEMENT_NAME);
      String value =
          org.apache.xml.security.utils.Base64.encode(
              credential.getEntityCertificate().getEncoded());
      cert.setValue(value);
      data.getX509Certificates().add(cert);
      keyInfo.getX509Datas().add(data);
      signature.setKeyInfo(keyInfo);
      return signature;
    } catch (CertificateEncodingException e) {
      throw new SSOException("Error getting certificate", e);
    }
  }
  /** Creates the certificate from the KeyInfo element. */
  public static X509Credential loadCredentialFromSignature(Signature signature)
      throws RelyingPartyException {
    X509Credential credential = null;
    KeyInfo kinfo = signature.getKeyInfo();
    List<X509Data> dataList = null;
    List<KeyValue> keyValueList = null;

    if (kinfo == null) {
      return null;
    }

    try {
      dataList = kinfo.getX509Datas();
      keyValueList = kinfo.getKeyValues();

      if (dataList.size() > 0) {

        if (dataList.size() > 1) {
          throw new RelyingPartyException("invalidKeyValueCount");
        }

        X509Data data = dataList.get(0);
        List<X509Certificate> certList = data.getX509Certificates();
        Iterator<X509Certificate> certIterator = certList.iterator();

        while (certIterator.hasNext()) {
          X509Certificate certElem = null;
          String certValue = null;
          byte[] certInBytes = null;
          ByteArrayInputStream inputStream = null;
          CertificateFactory factory = null;
          java.security.cert.X509Certificate x509Cert = null;

          certElem = (X509Certificate) certIterator.next();
          certValue = certElem.getValue();
          certInBytes = Base64.decode(certValue);
          inputStream = new ByteArrayInputStream(certInBytes);
          factory = CertificateFactory.getInstance("X509");
          x509Cert = (java.security.cert.X509Certificate) factory.generateCertificate(inputStream);
          credential = new X509CredentialImpl(x509Cert);
        }
      } else if (keyValueList.size() > 0) {

        if (keyValueList.size() > 1) {
          throw new RelyingPartyException("invalidKeyValueCount");
        }

        KeyValue val = null;
        RSAKeyValue rsaKey = null;
        Element modElem = null;
        Element expElem = null;
        Element elem = null;
        OMElement omElem = null;
        BigInteger mod = null;
        BigInteger exp = null;

        val = (KeyValue) keyValueList.get(0);
        rsaKey = val.getRSAKeyValue();
        elem = rsaKey.getDOM();
        omElem = (OMElement) new OMDOMFactory().getDocument().importNode(elem, true);
        modElem = (Element) omElem.getFirstChildWithName(Modulus.DEFAULT_ELEMENT_NAME);
        expElem = (Element) omElem.getFirstChildWithName(Exponent.DEFAULT_ELEMENT_NAME);
        mod = Base64.decodeBigIntegerFromElement(modElem);

        if (expElem != null) {
          exp = Base64.decodeBigIntegerFromElement(expElem);
        } else {
          exp = DEFAULT_EXPONENET;
        }

        credential = new X509CredentialImpl(mod, exp);
      } else {
        if (log.isDebugEnabled()) {
          log.debug("unknown key info");
        }
      }
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      log.error("Error while loading credentials from signature", e);
      throw new RelyingPartyException("Error while loading credentials from signature", e);
    }

    return credential;
  }