/**
   * Test that first signs, then encrypts a WS-Security envelope.
   *
   * <p>
   *
   * @throws Exception Thrown when there is any problem in signing, encryption, decryption, or
   *     verification
   */
  public void testEncryptedKeySignature() throws Exception {

    SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
    LOG.info("Before Sign/Encryption....");
    Document doc = unsignedEnvelope.getAsDocument();

    WSSecHeader secHeader = new WSSecHeader();
    secHeader.insertSecurityHeader(doc);

    WSSecEncryptedKey encrKey = new WSSecEncryptedKey();
    encrKey.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
    encrKey.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
    encrKey.setKeySize(192);
    encrKey.prepare(doc, crypto);

    WSSecEncrypt encrypt = new WSSecEncrypt();
    encrypt.setEncKeyId(encrKey.getId());
    encrypt.setEphemeralKey(encrKey.getEphemeralKey());
    encrypt.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
    encrypt.setEncryptSymmKey(false);
    encrypt.setEncryptedKeyElement(encrKey.getEncryptedKeyElement());

    WSSecSignature sign = new WSSecSignature();
    sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
    sign.setCustomTokenId(encrKey.getId());
    sign.setSecretKey(encrKey.getEphemeralKey());
    sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);

    Document signedDoc = sign.build(doc, crypto, secHeader);
    Document encryptedSignedDoc = encrypt.build(signedDoc, crypto, secHeader);

    if (LOG.isDebugEnabled()) {
      LOG.debug("Signed and encrypted message with IssuerSerial key identifier (both), 3DES:");
      String outputString =
          org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedSignedDoc);
      LOG.debug(outputString);
    }

    LOG.info("After Sign/Encryption....");
    verify(encryptedSignedDoc);
  }
  private byte[] doSignature(
      List<WSEncryptionPart> sigs,
      TokenWrapper policyTokenWrapper,
      Token policyToken,
      SecurityToken tok,
      boolean included)
      throws WSSecurityException {
    if (policyToken.isDerivedKeys()) {
      return doSignatureDK(sigs, policyTokenWrapper, policyToken, tok, included);
    } else {
      WSSecSignature sig = new WSSecSignature(wssConfig);
      sig.setWsConfig(wssConfig);
      // If a EncryptedKeyToken is used, set the correct value type to
      // be used in the wsse:Reference in ds:KeyInfo
      int type =
          included ? WSConstants.CUSTOM_SYMM_SIGNING : WSConstants.CUSTOM_SYMM_SIGNING_DIRECT;
      if (policyToken instanceof X509Token) {
        if (isRequestor()) {
          sig.setCustomTokenValueType(
              WSConstants.SOAPMESSAGE_NS11 + "#" + WSConstants.ENC_KEY_VALUE_TYPE);
          sig.setKeyIdentifierType(type);
        } else {
          // the tok has to be an EncryptedKey token
          sig.setEncrKeySha1value(tok.getSHA1());
          sig.setKeyIdentifierType(WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER);
        }
      } else if (policyToken instanceof UsernameToken) {
        sig.setCustomTokenValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
        sig.setKeyIdentifierType(type);
      } else {
        // Setting the AttachedReference or the UnattachedReference according to the flag
        Element ref;
        if (included) {
          ref = tok.getAttachedReference();
        } else {
          ref = tok.getUnattachedReference();
        }

        if (ref != null) {
          SecurityTokenReference secRef = new SecurityTokenReference(cloneElement(ref), false);
          sig.setSecurityTokenReference(secRef);
          sig.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
        } else {
          String tokenType = tok.getTokenType();
          if (WSConstants.WSS_SAML_TOKEN_TYPE.equals(tokenType)
              || WSConstants.SAML_NS.equals(tokenType)) {
            sig.setCustomTokenValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
            sig.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
          } else if (WSConstants.WSS_SAML2_TOKEN_TYPE.equals(tokenType)
              || WSConstants.SAML2_NS.equals(tokenType)) {
            sig.setCustomTokenValueType(WSConstants.WSS_SAML2_KI_VALUE_TYPE);
            sig.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
          } else {
            sig.setCustomTokenValueType(tokenType);
            sig.setKeyIdentifierType(type);
          }
        }
      }

      String sigTokId;
      if (included) {
        sigTokId = tok.getWsuId();
        if (sigTokId == null) {
          if (policyToken instanceof SecureConversationToken
              || policyToken instanceof SecurityContextToken) {
            sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING_DIRECT);
          }
          sigTokId = tok.getId();
        }
        if (sigTokId.startsWith("#")) {
          sigTokId = sigTokId.substring(1);
        }
      } else {
        sigTokId = tok.getId();
      }

      if (included && sbinding.isTokenProtection()) {
        sigs.add(new WSEncryptionPart(sigTokId));
      }

      sig.setCustomTokenId(sigTokId);
      sig.setSecretKey(tok.getSecret());
      sig.setSignatureAlgorithm(sbinding.getAlgorithmSuite().getSymmetricSignature());
      Crypto crypto = null;
      if (sbinding.getProtectionToken() != null) {
        crypto = getEncryptionCrypto(sbinding.getProtectionToken());
      } else {
        crypto = getSignatureCrypto(policyTokenWrapper);
      }
      this.message.getExchange().put(SecurityConstants.SIGNATURE_CRYPTO, crypto);
      sig.prepare(saaj.getSOAPPart(), crypto, secHeader);
      sig.setParts(sigs);
      List<Reference> referenceList = sig.addReferencesToSign(sigs, secHeader);

      // Do signature
      if (bottomUpElement == null) {
        sig.computeSignature(referenceList, false, null);
      } else {
        sig.computeSignature(referenceList, true, bottomUpElement);
      }
      bottomUpElement = sig.getSignatureElement();

      this.mainSigId = sig.getId();
      return sig.getSignatureValue();
    }
  }