/**
   * Speichert die PIN temporaer fuer diese Session.
   *
   * @param passport der Passport.
   * @param pin die PIN.
   * @throws Exception
   */
  private static void setCachedPIN(HBCIPassport passport, String pin) throws Exception {
    String key = getCacheKey(passport);

    // Kein Key, dann muessen wir nicht cachen
    if (key == null) return;

    ByteArrayInputStream bis = new ByteArrayInputStream(pin.getBytes());
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    Application.getSSLFactory().encrypt(bis, bos);
    byte[] crypted = bos.toByteArray();

    if (Settings.getCachePin()) {
      pinCache.put(key, crypted);
    }

    // Permanentes Speichern der PIN gibts nur bei PIN/TAN, da dort ueber
    // die TAN eine weitere Autorisierung bei der Ausfuehrung von Geschaeftsvorfaellen
    // mit Geldfluss stattfindet. Bei DDV/RDH koennte man sonst beliebig Geld
    // transferieren, ohne jemals wieder nach einem Passwort gefragt zu werden.
    if (Settings.getStorePin() && (passport instanceof HBCIPassportPinTan)) {
      // Nicht direkt das Byte-Array speichern sondern einen Base64-String.
      // Grund: Bei einem Byte-Array wuerde der XML-Serializer fuer jedes
      // Byte ein einzelnes XML-Element anlegen und damit das Wallet aufblasen
      Settings.getWallet().set(key, Base64.encode(crypted));
    }
  }
  /**
   * Hilfsfunktion zum Ermitteln des Keys, zu dem die PIN gespeichert ist.
   *
   * @param passport
   * @return die PIN oder null.
   */
  private static String getCacheKey(HBCIPassport passport) {
    // Entweder das Cachen ist abgeschaltet oder wir haben keinen Passport
    if (!Settings.getCachePin() || passport == null) {
      Logger.debug("pin caching disabled or no passport set");
      return null;
    }

    String key = null;
    // PIN/TAN
    if (passport instanceof HBCIPassportPinTan) key = ((HBCIPassportPinTan) passport).getFileName();

    // Schluesseldiskette
    else if (passport instanceof AbstractRDHSWFileBasedPassport)
      key = ((AbstractRDHSWFileBasedPassport) passport).getFilename();

    // DDV
    else if (passport instanceof HBCIPassportDDV) key = ((HBCIPassportDDV) passport).getFileName();

    if (key != null) {
      key = "hibiscus.pin." + key;
      Logger.debug("using cache key: " + key);
      return key;
    }

    Logger.warn(
        "unknown passport type ["
            + passport.getClass().getName()
            + "], don't know, how to cache pin");
    return null;
  }
  /**
   * Prueft, ob eine gespeicherte PIN fuer diesen Passport vorliegt.
   *
   * @param passport der Passport.
   * @return die PIN oder null, wenn keine gefunden wurde.
   * @throws Exception
   */
  private static String getCachedPIN(HBCIPassport passport) throws Exception {
    String key = getCacheKey(passport);

    // Kein Key - dann brauchen wir auch nicht im Cache schauen
    if (key == null) return null;

    byte[] data = null;

    // Cache checken
    if (Settings.getCachePin()) {
      data = pinCache.get(key);
    }

    // Wenn wir noch nichts im Cache haben, schauen wir im Wallet - wenn das erlaubt ist
    if (data == null && Settings.getStorePin() && (passport instanceof HBCIPassportPinTan)) {
      String s = (String) Settings.getWallet().get(key);
      if (s != null) {
        data = Base64.decode(s);

        // Wenn diese Meldung im Log erscheint, gibts keinen Support mehr von mir.
        // Wer die PIN permament speichert, tut das auf eigenes Risiko
        Logger.info("pin loaded from wallet");
        // Uebernehmen wir gleich in den Cache, damit wir beim
        // naechsten Mal direkt im Cache schauen koennen und nicht
        // mehr im Wallet
        pinCache.put(key, data);
      }
    }

    // Haben wir Daten?
    if (data != null) {
      ByteArrayInputStream bis = new ByteArrayInputStream(data);
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      Application.getSSLFactory().decrypt(bis, bos);
      String s = bos.toString();
      if (s != null && s.length() > 0) return s;
    }

    return null;
  }