private static String readRSAKey(Connection connection, String pkPath) throws SQLException {
    String res = null;
    byte[] fileBuf = new byte[2048];

    BufferedInputStream fileIn = null;

    try {
      File f = new File(pkPath);
      String canonicalPath = f.getCanonicalPath();
      fileIn = new BufferedInputStream(new FileInputStream(canonicalPath));

      int bytesRead = 0;

      StringBuffer sb = new StringBuffer();
      while ((bytesRead = fileIn.read(fileBuf)) != -1) {
        sb.append(StringUtils.toAsciiString(fileBuf, 0, bytesRead));
      }
      res = sb.toString();

    } catch (IOException ioEx) {

      if (connection.getParanoid()) {
        throw SQLError.createSQLException(
            Messages.getString("Sha256PasswordPlugin.0", new Object[] {""}),
            SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
            connection.getExceptionInterceptor());
      }
      throw SQLError.createSQLException(
          Messages.getString("Sha256PasswordPlugin.0", new Object[] {"'" + pkPath + "'"}),
          SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
          ioEx,
          connection.getExceptionInterceptor());

    } finally {
      if (fileIn != null) {
        try {
          fileIn.close();
        } catch (Exception ex) {
          SQLException sqlEx =
              SQLError.createSQLException(
                  Messages.getString("Sha256PasswordPlugin.1"),
                  SQLError.SQL_STATE_GENERAL_ERROR,
                  ex,
                  connection.getExceptionInterceptor());

          throw sqlEx;
        }
      }
    }

    return res;
  }
  protected synchronized JDBC4ClientInfoProvider getClientInfoProviderImpl() throws SQLException {
    if (this.infoProvider == null) {
      try {
        try {
          this.infoProvider =
              (JDBC4ClientInfoProvider)
                  Util.getInstance(getClientInfoProvider(), new Class[0], new Object[0]);
        } catch (SQLException sqlEx) {
          if (sqlEx.getCause() instanceof ClassCastException) {
            // try with package name prepended
            this.infoProvider =
                (JDBC4ClientInfoProvider)
                    Util.getInstance(
                        "com.mysql.jdbc." + getClientInfoProvider(), new Class[0], new Object[0]);
          }
        }
      } catch (ClassCastException cce) {
        throw SQLError.createSQLException(
            Messages.getString(
                "JDBC4Connection.ClientInfoNotImplemented", new Object[] {getClientInfoProvider()}),
            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
      }

      this.infoProvider.initialize(this, this.props);
    }

    return this.infoProvider;
  }
  public boolean nextAuthenticationStep(Buffer fromServer, List<Buffer> toServer)
      throws SQLException {
    toServer.clear();

    if (this.password == null || this.password.length() == 0 || fromServer == null) {
      // no password or changeUser()
      Buffer bresp = new Buffer(new byte[] {0});
      toServer.add(bresp);

    } else if (((MySQLConnection) connection).getIO().isSSLEstablished()) {
      // allow plain text over SSL
      Buffer bresp = new Buffer(StringUtils.getBytes(this.password));
      bresp.setPosition(bresp.getBufLength());
      int oldBufLength = bresp.getBufLength();
      bresp.writeByte((byte) 0);
      bresp.setBufLength(oldBufLength + 1);
      bresp.setPosition(0);
      toServer.add(bresp);

    } else if (this.connection.getServerRSAPublicKeyFile() != null) {
      // encrypt with given key, don't use "Public Key Retrieval"
      this.seed = fromServer.readString();
      Buffer bresp =
          new Buffer(
              encryptPassword(this.password, this.seed, this.connection, this.publicKeyString));
      toServer.add(bresp);

    } else {
      if (!this.connection.getAllowPublicKeyRetrieval()) {
        throw SQLError.createSQLException(
            Messages.getString("Sha256PasswordPlugin.2"),
            SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE,
            connection.getExceptionInterceptor());
      }

      // We must request the public key from the server to encrypt the password
      if (this.publicKeyRequested) {
        // read key response
        Buffer bresp =
            new Buffer(
                encryptPassword(
                    this.password, this.seed, this.connection, fromServer.readString()));
        toServer.add(bresp);
        this.publicKeyRequested = false;
      } else {
        // build and send Public Key Retrieval packet
        this.seed = fromServer.readString();
        Buffer bresp = new Buffer(new byte[] {1});
        toServer.add(bresp);
        this.publicKeyRequested = true;
      }
    }
    return true;
  }