private void doIssuanceProtocol(
      IssuerAbcEngine issuerEngine,
      UserAbcEngine userEngine,
      IssuancePolicy ip,
      List<Attribute> issuerAtts)
      throws Exception {

    // Initialize ABC4Trust Issuance Protocol Issuer side
    // Returns an IssuancePolicy from CryptoEngineIssuer to be passed to CryptoEngineUser
    // initialization
    IssuanceMessageAndBoolean issuerIm = issuerEngine.initIssuanceProtocol(ip, issuerAtts);
    assertFalse(issuerIm.isLastMessage());

    // Initialize ABC4Trust Issuance Protocol Prover side
    // FIXME: userEngine indirectly calls CryptoEngineUser.createIssuanceToken() with the
    // IssuancePolicy from the Issuer and returns an IssuanceToken
    // contained in the IssuanceMessage. This IssuanceToken is simply NOT used for now in the next
    // step of the UProve Credential Issuance protocol.
    // However, this seems to be the only proper way for now to initialise CryptoEngineUser to a
    // working state, despite the createIssuanceToken() step being
    // an optional step for the advanced Issuance setting not supported by UProve for now.
    IssuMsgOrCredDesc userIm = userEngine.issuanceProtocolStep(issuerIm.getIssuanceMessage());

    // Execute the UProve issuance protocol:

    // Prover side asks issuer for first message
    issuerIm = issuerEngine.issuanceProtocolStep(userIm.im);
    assertFalse(issuerIm.isLastMessage());

    // Prover side generates second message based on the first message
    userIm = userEngine.issuanceProtocolStep(issuerIm.getIssuanceMessage());

    // Prover side asks issuer for third message based on the second message
    assertNotNull(userIm.im);
    issuerIm = issuerEngine.issuanceProtocolStep(userIm.im);
    assertNotNull(issuerIm.getIssuanceMessage());

    // Prover side generates UProve Tokens based on the third message
    userIm = userEngine.issuanceProtocolStep(issuerIm.getIssuanceMessage());
    boolean userLastMessage = (userIm.cd != null);
    assertTrue(issuerIm.isLastMessage() == userLastMessage);

    assertNull(userIm.im);
    assertNotNull(userIm.cd);

    // CredentialDescription actualCredDesc = userIm.cd;
    // ObjectFactory of = new ObjectFactory();
    // String actualCredentialDesc =
    // XmlUtils.toNormalizedXML(of.createCredentialDescription(actualCredDesc));

    // System.out.println(actualCredentialDesc);
  }