/**
  * Loescht den permanenten Store mit den PINs.
  *
  * @param passport der Passport, dessen PIN geloescht werden soll. Optional. Wird er weggelassen,
  *     werden alle PINs geloescht.
  */
 public static void clearPINStore(HBCIPassport passport) {
   try {
     if (passport != null) {
       // Wir loeschen nur das Passwort vom angegebenen Passport
       String key = getCacheKey(passport);
       if (key != null && Settings.getWallet().get(key) != null) {
         // Nur loeschen, wenn es den Key auch wirklich gibt. Das spart
         // den Schreibzugriff, wenn er nicht vorhanden ist
         Settings.getWallet().delete(key);
       }
       // Wenn kein Key existiert, haben wir auch nichts zu loeschen,
       // weil dann gar kein Passwort im Store existieren kann
     } else {
       // Alles Keys beginnen mit "hibiscus.pin."
       Settings.getWallet().deleteAll("hibiscus.pin.");
     }
   } catch (Exception e) {
     // Wenn das fehlschlaegt, sollte man eigentlich mehr Alarm schlagen
     // Allerdings wuesste ich jetzt auch nicht, was der User dann machen
     // kann, ausser dem Loeschen der Wallet-Datei. Was aber dazu fuehren
     // wuerde, dass saemtliche DDV- und PinTan-Passport-Files nicht mehr
     // gelesen werden koennen, weil fuer die ja Random-Passworte verwendet
     // werden, die ebenfalls im Wallet gespeichert sind
     Logger.error("unable to clear pin cache", e);
   }
 }
  /**
   * 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));
    }
  }
  /**
   * 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;
  }