/**
   * Create user identity token based on an issued token
   *
   * @param ep
   * @param senderNonce
   * @param issuedIdentityToken
   * @return user identity token
   * @throws ServiceResultException if endpoint or the stack doesn't support UserName token policy
   */
  public static UserIdentityToken createIssuedIdentityToken(
      EndpointDescription ep, byte[] senderNonce, byte[] issuedIdentityToken)
      throws ServiceResultException {
    UserTokenPolicy policy = ep.findUserTokenPolicy(UserTokenType.IssuedToken);
    if (policy == null)
      throw new ServiceResultException(
          StatusCodes.Bad_IdentityTokenRejected, "IssuedToken not supported");
    String securityPolicyUri = policy.getSecurityPolicyUri();
    if (securityPolicyUri == null) securityPolicyUri = ep.getSecurityPolicyUri();
    SecurityPolicy securityPolicy = SecurityPolicy.getSecurityPolicy(securityPolicyUri);
    if (securityPolicy == null) securityPolicy = SecurityPolicy.NONE;
    IssuedIdentityToken token = new IssuedIdentityToken();
    token.setTokenData(issuedIdentityToken);

    // Encrypt the token
    SecurityAlgorithm algorithmUri = securityPolicy.getAsymmetricEncryptionAlgorithm();
    if (algorithmUri == null) algorithmUri = SecurityAlgorithm.RsaOaep;
    try {
      Cipher cipher = Cipher.getInstance(algorithmUri.getStandardName());
      Cert serverCert = new Cert(ep.getServerCertificate());
      cipher.init(Cipher.ENCRYPT_MODE, serverCert.getCertificate());
      byte[] tokenData = issuedIdentityToken;
      if (senderNonce != null)
        tokenData =
            ByteBufferUtils.concatenate(
                toArray(issuedIdentityToken.length + senderNonce.length),
                issuedIdentityToken,
                senderNonce);
      token.setTokenData(cipher.doFinal(tokenData));
      token.setEncryptionAlgorithm(algorithmUri.getUri());

    } catch (InvalidKeyException e) {
      // Server certificate does not have encrypt usage
      throw new ServiceResultException(
          StatusCodes.Bad_CertificateInvalid,
          "Server certificate in endpoint is invalid: " + e.getMessage());
    } catch (IllegalBlockSizeException e) {
      throw new ServiceResultException(
          StatusCodes.Bad_SecurityPolicyRejected, e.getClass().getName() + ":" + e.getMessage());
    } catch (BadPaddingException e) {
      throw new ServiceResultException(
          StatusCodes.Bad_CertificateInvalid,
          "Server certificate in endpoint is invalid: " + e.getMessage());
    } catch (NoSuchAlgorithmException e) {
      throw new ServiceResultException(StatusCodes.Bad_InternalError, e);
    } catch (NoSuchPaddingException e) {
      throw new ServiceResultException(StatusCodes.Bad_InternalError, e);
    }

    return token;
  }
  /**
   * Create user identity token based on username and password
   *
   * @param ep
   * @param username
   * @param password
   * @return user identity token
   * @throws ServiceResultException if endpoint or the stack doesn't support UserName token policy
   */
  public static UserIdentityToken createUserNameIdentityToken(
      EndpointDescription ep, byte[] senderNonce, String username, String password)
      throws ServiceResultException {
    UserTokenPolicy policy = ep.findUserTokenPolicy(UserTokenType.UserName);
    if (policy == null)
      throw new ServiceResultException(
          StatusCodes.Bad_IdentityTokenRejected, "UserName not supported");
    String securityPolicyUri = policy.getSecurityPolicyUri();
    if (securityPolicyUri == null) securityPolicyUri = ep.getSecurityPolicyUri();
    SecurityPolicy securityPolicy = SecurityPolicy.getSecurityPolicy(securityPolicyUri);
    if (securityPolicy == null) securityPolicy = SecurityPolicy.NONE;
    UserNameIdentityToken token = new UserNameIdentityToken();

    token.setUserName(username);
    token.setPolicyId(policy.getPolicyId());

    // Encrypt the password, unless no security is defined
    SecurityAlgorithm algorithm = securityPolicy.getAsymmetricEncryptionAlgorithm();
    byte[] pw = password.getBytes(BinaryEncoder.UTF8);
    if (algorithm == null) token.setPassword(pw);
    else
      try {
        Cert serverCert = new Cert(ep.getServerCertificate());
        if (senderNonce != null)
          pw =
              ByteBufferUtils.concatenate(toArray(pw.length + senderNonce.length), pw, senderNonce);
        else pw = ByteBufferUtils.concatenate(toArray(pw.length), pw);
        pw = CryptoUtil.asymmEncrypt(pw, serverCert.getCertificate().getPublicKey(), algorithm);
        token.setPassword(pw);

      } catch (InvalidKeyException e) {
        // Server certificate does not have encrypt usage
        throw new ServiceResultException(
            StatusCodes.Bad_CertificateInvalid,
            "Server certificate in endpoint is invalid: " + e.getMessage());
      } catch (IllegalBlockSizeException e) {
        throw new ServiceResultException(
            StatusCodes.Bad_SecurityPolicyRejected, e.getClass().getName() + ":" + e.getMessage());
      } catch (BadPaddingException e) {
        throw new ServiceResultException(
            StatusCodes.Bad_CertificateInvalid,
            "Server certificate in endpoint is invalid: " + e.getMessage());
      } catch (NoSuchAlgorithmException e) {
        throw new ServiceResultException(StatusCodes.Bad_InternalError, e);
      } catch (NoSuchPaddingException e) {
        throw new ServiceResultException(StatusCodes.Bad_InternalError, e);
      }
    token.setEncryptionAlgorithm(algorithm.getUri());

    return token;
  }
  public static X509IdentityToken createX509IdentityToken(
      EndpointDescription ep,
      byte[] serverNonce,
      Cert certificate,
      PrivateKey key,
      SignatureData signatureData)
      throws ServiceResultException {
    if (signatureData == null)
      throw new NullPointerException("signatureData must be defined (will be filled in)");
    UserTokenPolicy policy = ep.findUserTokenPolicy(UserTokenType.Certificate);
    if (policy == null)
      throw new ServiceResultException(
          StatusCodes.Bad_IdentityTokenRejected, "Certificate UserTokenType is not supported");

    X509IdentityToken token = new X509IdentityToken(policy.getPolicyId(), certificate.getEncoded());

    String securityPolicyUri = policy.getSecurityPolicyUri();
    if (securityPolicyUri == null) securityPolicyUri = ep.getSecurityPolicyUri();
    SecurityPolicy securityPolicy = SecurityPolicy.getSecurityPolicy(securityPolicyUri);
    Cert serverCert = new Cert(ep.getServerCertificate());
    if ((securityPolicy != null) && (serverCert != null))
      try {
        // Create a Signature object and initialize it with the private
        // key
        Signature signature =
            Signature.getInstance(
                securityPolicy.getAsymmetricSignatureAlgorithm().getTransformation());
        signature.initSign(key);

        signature.update(serverCert.getEncoded());
        signature.update(serverNonce);

        signatureData.setSignature(signature.sign());
        signatureData.setAlgorithm(securityPolicy.getAsymmetricSignatureAlgorithm().getUri());

      } catch (NoSuchAlgorithmException e) {
        throw new ServiceResultException(
            StatusCodes.Bad_SecurityChecksFailed, "Signature generation failed: " + e.getMessage());
      } catch (InvalidKeyException e) {
        // Server certificate does not have encrypt usage
        throw new ServiceResultException(
            StatusCodes.Bad_CertificateInvalid,
            "Server certificate in endpoint is invalid: " + e.getMessage());
      } catch (SignatureException e) {
        throw new ServiceResultException(
            StatusCodes.Bad_SecurityChecksFailed, "Signature generation failed: " + e.getMessage());
      }
    return token;
  }
 public static EndpointDescription[] select(
     EndpointDescription[] searchSet, int minKeySize, int maxKeySize) {
   List<EndpointDescription> result = new ArrayList<EndpointDescription>();
   for (EndpointDescription d : searchSet) {
     try {
       Cert cert = new Cert(d.getServerCertificate());
       int keySize = cert.getKeySize();
       if (keySize < minKeySize || keySize > maxKeySize) continue;
       result.add(d);
     } catch (ServiceResultException e) {
       continue;
     }
   }
   return result.toArray(new EndpointDescription[result.size()]);
 }
 /**
  * Load file certificate and private key from applicationName.der & .pfx - or create ones if they
  * do not exist
  *
  * @return the KeyPair composed of the certificate and private key
  * @throws ServiceResultException
  */
 private static KeyPair getOPCCert(String applicationName) throws ServiceResultException {
   File certFile = new File(applicationName + ".der");
   File privKeyFile = new File(applicationName + ".pem");
   try {
     Cert myServerCertificate = Cert.load(certFile);
     PrivKey myServerPrivateKey = PrivKey.load(privKeyFile, PRIVKEY_PASSWORD);
     return new KeyPair(myServerCertificate, myServerPrivateKey);
   } catch (CertificateException e) {
     throw new ServiceResultException(e);
   } catch (IOException e) {
     try {
       String hostName = InetAddress.getLocalHost().getHostName();
       String applicationUri = "urn:" + hostName + ":" + applicationName;
       KeyPair keys =
           CertificateUtils.createApplicationInstanceCertificate(
               applicationName, null, applicationUri, 3650, hostName);
       keys.getCertificate().save(certFile);
       PrivKey privKeySecure = keys.getPrivateKey();
       privKeySecure.save(privKeyFile, PRIVKEY_PASSWORD);
       return keys;
     } catch (Exception e1) {
       throw new ServiceResultException(e1);
     }
   } catch (NoSuchAlgorithmException e) {
     throw new ServiceResultException(e);
   } catch (Exception e) {
     throw new ServiceResultException(e);
   }
 }