import java.io.*; import java.nio.file.*; import java.util.*; import java.util.function.*; import java.text.*; import java.security.*; import java.security.cert.*; import java.security.spec.*; import javax.crypto.*; import javax.crypto.spec.*; import javafx.application.*; import javafx.stage.*; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.text.*; import javafx.scene.layout.*; import javafx.scene.input.*; import javafx.beans.property.*; import javafx.event.*; import javafx.geometry.*; import javafx.collections.*; public class MKeyStore extends Application { Stage stage; boolean showChar = false; BooleanProperty binary = new SimpleBooleanProperty(false); BooleanProperty modifyed = new SimpleBooleanProperty(false); ObjectProperty<File> file = new SimpleObjectProperty<>(new File("")); String password = null; TreeTableView<String> treeTableView; KeyStore keyStore; Label label; DateFormat dateFormatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM); FileChooser.ExtensionFilter autodtFl = new FileChooser.ExtensionFilter("Autodetect", "*.*"); FileChooser.ExtensionFilter binaryFl = new FileChooser.ExtensionFilter("Binary", "*.*"); FileChooser.ExtensionFilter base64Fl = new FileChooser.ExtensionFilter("Base-64", "*.*"); ContextMenu contextMenu = new ContextMenu(); String type = "PKCS12"; // PKCS12, JKS @Override public void start(Stage stage) { this.stage = stage; label = new Label(); BorderPane layout = new BorderPane(); stage.setScene(new Scene(layout, 400, 300)); MenuBar menuBar = new MenuBar(); Menu miFile = new Menu("File"); MenuItem miFileNew = new MenuItem("New"); miFileNew.setOnAction(ae -> { newKeyStore(null); }); MenuItem miFileOpen = new MenuItem("Open..."); miFileOpen.setOnAction(ae -> { openKeyStore(); }); MenuItem miFileSave = new MenuItem("Save"); miFileSave.setOnAction(ae -> { saveKeyStore(false); }); miFileSave.setDisable(true); MenuItem miFileSaveAs = new MenuItem("Save as..."); miFileSaveAs.setOnAction(ae -> { saveKeyStore(true); }); MenuItem miFileExit = new MenuItem("Exit"); miFileExit.setOnAction(ae -> { if (confirmSave()) { Platform.exit(); System.exit(0); } }); miFile.getItems().addAll(miFileNew, miFileOpen, new SeparatorMenuItem(), miFileSave, miFileSaveAs, new SeparatorMenuItem(), miFileExit); //Menu miHelp = new Menu("Help"); menuBar.getMenus().addAll(miFile); createTreeTableView(); treeTableView.setRoot(new EntryTreeItem("", null)); treeTableView.getRoot().setExpanded(true); layout.setTop(menuBar); layout.setCenter(treeTableView); layout.setBottom(label); file.addListener((o, v, n) -> { treeTableView.getRoot().setValue((n != null ? n.getName() : "New") + " (" + keyStore.getType() + ")"); }); miFileSave.disableProperty().bind(modifyed.not()); stage.setOnCloseRequest(e -> { if (!confirmSave()) e.consume(); }); stage.show(); Platform.runLater(() -> { List<String> p = getParameters().getRaw(); if (p.isEmpty()) { newKeyStore(null); return; } File pFile = new File(p.get(0)); if (pFile.isFile()) { loadKeyStore(pFile, autodtFl); } else { ButtonType bttp = alert(stage, Alert.AlertType.CONFIRMATION, "File " + pFile.getName() + " not found. Create?", ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); if (bttp == null || bttp == ButtonType.CANCEL) { miFileExit.getOnAction().handle(null); } newKeyStore(bttp == ButtonType.YES ? pFile : null); } }); } void loadKeyStore(File loadFile, FileChooser.ExtensionFilter flt) { try { if (loadFile.length() > 500_000L) sizeException(); byte[] bytes = Files.readAllBytes(loadFile.toPath()); bytes = detect(bytes, flt, binary); keyStore = KeyStore.getInstance(type); try { keyStore.load(new ByteArrayInputStream(bytes), new char[0]); password = ""; } catch (Exception e) { String openPassword = passwordDialog(); if (openPassword == null) { newKeyStore(null); return; } keyStore.load(new ByteArrayInputStream(bytes), openPassword.toCharArray()); password = openPassword; } fillTreeTableView(); file.set(loadFile); modifyed.set(false); } catch (Exception e) { alert(stage, Alert.AlertType.ERROR, e); newKeyStore(null); } } void sizeException() throws IOException { throw new IOException("File is too large"); } void newKeyStore(File fl) { if (!confirmSave()) return; try { keyStore = KeyStore.getInstance(type); keyStore.load(null, null); fillTreeTableView(); file.set(fl); modifyed.set(false); binary.set(true); password = null; } catch (Exception e) { e.printStackTrace(); } } void openKeyStore() { if (!confirmSave()) return; FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().addAll(autodtFl, binaryFl, base64Fl); fileChooser.setInitialFileName("KeyStore"); File openFile = fileChooser.showOpenDialog(stage); if (openFile != null) loadKeyStore(openFile, fileChooser.getSelectedExtensionFilter()); } byte[] detect(byte[] bytes, FileChooser.ExtensionFilter flt, BooleanProperty bin) throws IOException { if (flt == binaryFl) { bin.set(true); return bytes; } boolean chArr = true; for (byte b : bytes) if (b > 0 && b < 32 && b != 9 && b != 10 && b != 13) { chArr = false; break; } if (flt == base64Fl && !chArr) throw new IOException("Non printable character"); if (flt == autodtFl && !chArr) { bin.set(true); return bytes; } bin.set(false); return Base64.getMimeDecoder().decode(norm(new String(bytes))); } String norm(String s) { return s.replaceAll("-----BEGIN [^-]+-----\\s+|-----END [^-]+-----|begin-base64[^\\n]+\\s+|====", ""); } boolean confirmSave() { if (!modifyed.get()) return true; ButtonType bttp = alert(stage, Alert.AlertType.CONFIRMATION, "Save KeyStore?", ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); if (bttp == null || bttp == ButtonType.CANCEL) return false; if (bttp == ButtonType.NO) return true; return saveKeyStore(false); } boolean saveKeyStore(boolean saveAs) { String savePassword = password; File saveFile = file.get(); boolean bin = binary.get(); if (saveAs || file.get() == null) { FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().addAll(binaryFl, base64Fl); fileChooser.setInitialFileName(saveFile != null ? (saveFile.isFile() ? "Copy" : "") + saveFile.getName() : "KeyStore"); saveFile = fileChooser.showSaveDialog(stage); if (saveFile == null) return false; savePassword = passwordDialog(); if (savePassword == null) return false; bin = fileChooser.getSelectedExtensionFilter() == binaryFl; } try (OutputStream os = bin ? Files.newOutputStream(saveFile.toPath()) : Base64.getMimeEncoder().wrap(Files.newOutputStream(saveFile.toPath()))) { keyStore.store(os, savePassword.toCharArray()); } catch (Exception e) { alert(stage, Alert.AlertType.ERROR, e); return false; } password = savePassword; binary.set(bin); file.set(saveFile); modifyed.set(false); return true; } void createTreeTableView() { treeTableView = new TreeTableView<>(); TreeTableColumn<String, String> column = new TreeTableColumn<>(); column.setCellValueFactory( (TreeTableColumn.CellDataFeatures<String, String> cellData) -> new ReadOnlyObjectWrapper<String>(cellData.getValue().getValue()) ); treeTableView.getColumns().add(column); treeTableView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); treeTableView.widthProperty().addListener((v, o, n) -> { Pane header = (Pane)treeTableView.lookup("TableHeaderRow"); if (header != null && header.isVisible()) { header.setMaxHeight(0); header.setMinHeight(0); header.setPrefHeight(0); header.setVisible(false); header.setManaged(false); } }); treeTableView.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> { Date date = null; try { if (((EntryTreeItem)n).getEntryClass() != null) date = keyStore.getCreationDate(n.getValue()); } catch (Exception e) { } label.setText(date != null ? dateFormatter.format(date) : ""); }); MenuItem miInfo = new MenuItem("Info"); miInfo.setOnAction(ae -> { info(); }); MenuItem miView = new MenuItem("View"); miView.setOnAction(ae -> { viewDialog(true, false); }); MenuItem miIns = new MenuItem("New"); miIns.setOnAction(ae -> { viewDialog(false, true); }); MenuItem miClone = new MenuItem("Clone"); miClone.setOnAction(ae -> { viewDialog(true, true); }); MenuItem miDel = new MenuItem("Delete"); miDel.setOnAction(ae -> { delete(); }); treeTableView.setRowFactory(tv -> { TreeTableRow<String> row = new TreeTableRow<>(); row.setOnMouseClicked(me -> { if (contextMenu.isShowing()) contextMenu.hide(); EntryTreeItem tiRoot = (EntryTreeItem)treeTableView.getRoot(); EntryTreeItem eti = (EntryTreeItem)row.getTreeItem(); if (row.isEmpty() || eti == null) { } else if (me.getButton() == MouseButton.PRIMARY && me.getClickCount() == 2) { if (eti == tiRoot) {} else if (eti.getParent() != tiRoot) miView.getOnAction().handle(null); } else if (me.getButton() == MouseButton.SECONDARY && eti != tiRoot) { if (eti.getParent() == tiRoot) contextMenu.getItems().setAll(miIns); else contextMenu.getItems().setAll(miView, miInfo, new SeparatorMenuItem(), miIns, miClone, new SeparatorMenuItem(), miDel); contextMenu.show((Node)me.getSource(), me.getScreenX(), me.getScreenY()); } }); return row; }); treeTableView.setOnKeyPressed(ke -> { EntryTreeItem eti = (EntryTreeItem)treeTableView.getSelectionModel().getSelectedItem(); EntryTreeItem tiRoot = (EntryTreeItem)treeTableView.getRoot(); if (eti != null && eti != tiRoot) { if (ke.getCode() == KeyCode.ENTER && eti.getParent() != tiRoot) miView.getOnAction().handle(null); else if (ke.getCode() == KeyCode.INSERT) miIns.getOnAction().handle(null); else if (ke.getCode() == KeyCode.DELETE && eti.getParent() != tiRoot) miDel.getOnAction().handle(null); } }); } KeyStore.Entry getKeyStoreEntry(EntryTreeItem eti) { String alias = eti.getValue(); KeyStore.Entry kse = null; KeyStore.PasswordProtection ppr = null; if (isProtected(eti.getEntryClass())) { if (eti.getPassword() == null) { try { kse = keyStore.getEntry(alias, new KeyStore.PasswordProtection(new char[0])); eti.setPassword(""); return kse; } catch (Exception e) { } String password = passwordDialog(); if (password == null) return null; eti.setPassword(password); } ppr = new KeyStore.PasswordProtection(eti.getPassword().toCharArray()); } try { kse = keyStore.getEntry(alias, ppr); } catch (Exception e) { alert(stage, Alert.AlertType.ERROR, e); eti.setPassword(null); } return kse; } void info() { EntryTreeItem eti = (EntryTreeItem)treeTableView.getSelectionModel().getSelectedItem(); KeyStore.Entry kse = getKeyStoreEntry(eti); if (kse != null) infoDialog(stage, eti.getValue(), kse.toString()); } void delete() { try { EntryTreeItem eti = (EntryTreeItem)treeTableView.getSelectionModel().getSelectedItem(); String alias = eti.getValue(); if (alert(stage, Alert.AlertType.CONFIRMATION, "Delete " + alias + "?") == ButtonType.OK) { keyStore.deleteEntry(alias); if (!keyStore.containsAlias(alias)) eti.getParent().getChildren().remove(eti); modifyed.set(true); } } catch (Exception e) { e.printStackTrace(); } } void fillTreeTableView() { treeTableView.getRoot().getChildren().clear(); treeTableView.getRoot().getChildren().add(new EntryTreeItem("Private key & Certificate", KeyStore.PrivateKeyEntry.class)); treeTableView.getRoot().getChildren().add(new EntryTreeItem("Secret key", KeyStore.SecretKeyEntry.class)); treeTableView.getRoot().getChildren().add(new EntryTreeItem("Certificate", KeyStore.TrustedCertificateEntry.class)); for (TreeItem<String> eti : treeTableView.getRoot().getChildren()) eti.setExpanded(true); treeTableView.getSelectionModel().selectFirst(); try { Enumeration<String> aliases = keyStore.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); for (TreeItem<String> eti : treeTableView.getRoot().getChildren()) { Class<? extends KeyStore.Entry> clss = ((EntryTreeItem)eti).getEntryClass(); if (keyStore.entryInstanceOf(alias, clss)) { eti.getChildren().add(new EntryTreeItem(alias, clss)); break; } } } } catch (Exception e) { e.printStackTrace(); } } String passwordDialog() { Dialog<ButtonType> dialog = new Dialog<>(); dialog.initOwner(stage); dialog.initStyle(StageStyle.UTILITY); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); CheckBox checkBox = new CheckBox(); checkBox.setSelected(showChar); PasswordField passwordField = new PasswordField(); TextField textField = new TextField(); passwordField.textProperty().bindBidirectional(textField.textProperty()); textField.managedProperty().bind(checkBox.selectedProperty()); textField.visibleProperty().bind(checkBox.selectedProperty()); passwordField.managedProperty().bind(checkBox.selectedProperty().not()); passwordField.visibleProperty().bind(checkBox.selectedProperty().not()); VBox fb = new VBox(); fb.getChildren().addAll(passwordField, textField); HBox cb = new HBox(8); cb.getChildren().addAll(new Label("Show characters:"), checkBox); VBox pb = new VBox(8); pb.getChildren().addAll(new Label("Password:"), fb, cb); dialog.getDialogPane().setContent(pb); Platform.runLater(() -> (showChar ? textField : passwordField).requestFocus()); dpBehavior(dialog.getDialogPane()); Optional<ButtonType> result = dialog.showAndWait(); showChar = checkBox.isSelected(); if (result.isPresent() && result.get() == ButtonType.OK) { return textField.getText(); } return null; } ButtonType alert(Window owner, Alert.AlertType type, Object cont, ButtonType... bt) { Alert alert = new Alert(type, "", bt); alert.initOwner(owner); alert.initStyle(StageStyle.UTILITY); alert.setHeaderText(null); if (cont instanceof String) { alert.setContentText((String)cont); } else if (cont instanceof Throwable) { Throwable t = (Throwable)cont; alert.setContentText(t.getMessage() != null && !t.getMessage().isEmpty() ? t.getMessage() : t.toString()); StringWriter sw = new StringWriter(); ((Throwable)cont).printStackTrace(new PrintWriter(sw)); TextArea ta = new TextArea(sw.toString()); //ta.setStyle("-fx-font-family: monospace; -fx-font-weight: bold;"); ta.setEditable(false); ta.setPadding(new Insets(0)); alert.getDialogPane().setExpandableContent(ta); } dpBehavior(alert.getDialogPane()); Optional<ButtonType> result = alert.showAndWait(); return (result.isPresent() ? result.get() : null); } void viewDialog(boolean cnt, boolean edt) { EntryTreeItem eti = (EntryTreeItem)treeTableView.getSelectionModel().getSelectedItem(); KeyStore.Entry kse = null; if (cnt) { kse = getKeyStoreEntry(eti); if (kse == null) return; } Class<? extends KeyStore.Entry> clss = eti.getEntryClass(); TextField alias = new TextField(cnt ? eti.getValue() : "newAlias"); alias.setEditable(edt); alias.setFocusTraversable(edt); TabPane tabPane = new TabPane(); if (!tabPane.getStyleClass().contains(TabPane.STYLE_CLASS_FLOATING)) { tabPane.getStyleClass().add(TabPane.STYLE_CLASS_FLOATING); } try { if (clss == KeyStore.PrivateKeyEntry.class) { byte[] bytes = (kse != null ? ((KeyStore.PrivateKeyEntry)kse).getPrivateKey().getEncoded() : null); tabPane.getTabs().add(createTab(PrivateKey.class, bytes, "PrivateKey", edt)); if (kse != null) { java.security.cert.Certificate[] serts = ((KeyStore.PrivateKeyEntry)kse).getCertificateChain(); for (java.security.cert.Certificate sert : serts) { tabPane.getTabs().add(createTab(java.security.cert.Certificate.class, sert.getEncoded(), "Certificate", edt)); } } else tabPane.getTabs().add(createTab(java.security.cert.Certificate.class, null, "Certificate", true)); if (edt) tabPane.getTabs().add(createTab(null, null, "+", true)); } else if (clss == KeyStore.SecretKeyEntry.class) { byte[] bytes = (kse != null ? ((KeyStore.SecretKeyEntry)kse).getSecretKey().getEncoded() : null); tabPane.getTabs().add(createTab(SecretKey.class, bytes, "SecretKey", edt)); } else if (clss == KeyStore.TrustedCertificateEntry.class) { byte[] bytes = (kse != null ? ((KeyStore.TrustedCertificateEntry)kse).getTrustedCertificate().getEncoded() : null); tabPane.getTabs().add(createTab(java.security.cert.Certificate.class, bytes, "Certificate", edt)); } } catch (Exception e) { e.printStackTrace(); } Dialog<ButtonType> dialog = new Dialog<>(); Window window = dialog.getDialogPane().getScene().getWindow(); dialog.initOwner(stage); dialog.initStyle(StageStyle.UTILITY); dialog.setTitle(clss.getSimpleName()); dialog.setResizable(true); Button bti = new Button("Info"), bte = new Button((edt ? "Load" : "Save")); bti.setOnAction(e -> { StringBuilder sb = new StringBuilder(); for (Tab tb : tabPane.getTabs()) { if(tb.getUserData() != null && !((TextArea)tb.getContent()).getText().isEmpty()) { Object o = getKSObj(window, tb); if (o == null) return; sb.append(tb.getText()).append(": ").append(getKSObjString(o)).append("\n"); } } infoDialog(window, alias.getText(), sb.toString()); }); bte.setOnAction(e -> { FileChooser fileChooser = new FileChooser(); if (edt) fileChooser.getExtensionFilters().addAll(autodtFl); fileChooser.getExtensionFilters().addAll(binaryFl, base64Fl); Tab tb = tabPane.getSelectionModel().getSelectedItem(); fileChooser.setInitialFileName(tb.getText()); TextArea ta = (TextArea)tb.getContent(); try { if (edt) { File file = fileChooser.showOpenDialog(window); if (file != null) { if (file.length() > 10_000L) sizeException(); byte[] bytes = Files.readAllBytes(file.toPath()); bytes = detect(bytes, fileChooser.getSelectedExtensionFilter(), new SimpleBooleanProperty()); ta.setText(Base64.getMimeEncoder().encodeToString(bytes)); } } else { File file = fileChooser.showSaveDialog(window); if (file != null) { Files.write(file.toPath(), fileChooser.getSelectedExtensionFilter() == binaryFl ? Base64.getMimeDecoder().decode(ta.getText()) : ta.getText().getBytes()); } } } catch (Exception ef) { alert(window, Alert.AlertType.ERROR, ef); } }); tabPane.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> { if (clss == KeyStore.PrivateKeyEntry.class && n.getUserData() == null) { int sz = tabPane.getTabs().size(); Tab pnl = tabPane.getTabs().get(sz - 2); pnl.setClosable(true); Tab pn = tabPane.getTabs().get(sz - 1); tabPane.getTabs().add(createTab(null, null, pn.getText(), true)); pn.setText(pnl.getText()); pn.setUserData(pnl.getUserData()); pn.setClosable(true); } }); tabPane.getTabs().addListener((ListChangeListener.Change<? extends Tab> c) -> { while(c.next()) { if (c.wasRemoved() && tabPane.getTabs().size() == 3) { tabPane.getTabs().get(1).setClosable(false); } } }); HBox hb = new HBox(8); hb.setAlignment(Pos.CENTER_LEFT); hb.getChildren().addAll(new Label("Alias:"), alias, bti, bte); VBox vb = new VBox(8); vb.getChildren().addAll(hb, tabPane); VBox.setVgrow(tabPane, Priority.ALWAYS); dialog.getDialogPane().setContent(vb); dialog.getDialogPane().setPrefSize(640, 480); BiConsumer<Event, Boolean> addEntry = (event, confirm) -> { if (confirm.booleanValue()) { ButtonType bttp = alert(window, Alert.AlertType.CONFIRMATION, "Save entry?", ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); if (bttp == null || bttp == ButtonType.CANCEL) { event.consume(); return; } if (bttp == ButtonType.NO) return; } ArrayList<java.security.cert.Certificate> sertArr = new ArrayList<>(); PrivateKey privateKey = null; SecretKey secretKey = null; String password = null; for (Tab tb : tabPane.getTabs()) { if(tb.getUserData() != null) { Object o = getKSObj(window, tb); if (o == null) { event.consume(); return; } if (o instanceof java.security.cert.Certificate) sertArr.add((java.security.cert.Certificate)o); else if (o instanceof PrivateKey) privateKey = (PrivateKey)o; else if (o instanceof SecretKey) secretKey = (SecretKey)o; } } try { String al = alias.getText().trim().toLowerCase(); if (al.isEmpty()) { alert(window, Alert.AlertType.ERROR, "Alias is empty"); event.consume(); return; } boolean replace = false; if (keyStore.containsAlias(al)) { if (alert(window, Alert.AlertType.CONFIRMATION, "Alias " + al + " already defined. Replace?", ButtonType.YES, ButtonType.NO) != ButtonType.YES) { event.consume(); return; } replace = true; } if (isProtected(clss)) { password = passwordDialog(); if (password == null) { event.consume(); return; } } KeyStore.Entry entry = null; if (clss == KeyStore.PrivateKeyEntry.class) { entry = new KeyStore.PrivateKeyEntry(privateKey, sertArr.toArray(new java.security.cert.Certificate[0])); } else if (clss == KeyStore.SecretKeyEntry.class) { entry = new KeyStore.SecretKeyEntry(secretKey); } else if (clss == KeyStore.TrustedCertificateEntry.class) { entry = new KeyStore.TrustedCertificateEntry(sertArr.get(0)); } if (replace) { EntryTreeItem ti = getEntryTreeItem(al); keyStore.deleteEntry(al); if (!keyStore.containsAlias(al)) ti.getParent().getChildren().remove(ti); } keyStore.setEntry(al, entry, (password != null ? new KeyStore.PasswordProtection(password.toCharArray()) : null)); EntryTreeItem newEti = new EntryTreeItem(al, clss); newEti.setPassword(password); getEntryTreeItem(clss).getChildren().add(newEti); treeTableView.getSelectionModel().select(treeTableView.getRow(newEti)); modifyed.set(true); } catch (Exception ef) { alert(window, Alert.AlertType.ERROR, ef); event.consume(); } }; dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK); if (edt) { dialog.getDialogPane().getButtonTypes().addAll(ButtonType.CANCEL); Button btOk = (Button)dialog.getDialogPane().lookupButton(ButtonType.OK); btOk.addEventFilter(ActionEvent.ACTION, e -> { addEntry.accept(e, Boolean.FALSE); }); window.setOnCloseRequest(e -> { addEntry.accept(e, Boolean.TRUE); }); dialog.getDialogPane().getScene().setOnKeyPressed(e -> { if (e.getCode() == KeyCode.ESCAPE) addEntry.accept(e, Boolean.TRUE); }); dpBehavior(dialog.getDialogPane()); } dialog.showAndWait(); } Tab createTab(Class<?> clss, byte[] bytes, String name, boolean edt) { String s = (bytes != null ? Base64.getMimeEncoder().encodeToString(bytes) : ""); TextArea ta = new TextArea(s); ta.setEditable(edt); ta.setFont(Font.font("Monospaced")); Tab tab = new Tab(name, ta); tab.setUserData(clss); tab.setClosable(false); return tab; } Object getKSObj(Window window, Tab tab) { try { Class<?> clss = (Class<?>)tab.getUserData(); String s = ((TextArea)tab.getContent()).getText(); byte[] bytes = Base64.getMimeDecoder().decode(norm(s)); if (clss == java.security.cert.Certificate.class) { return /*(java.security.cert.Certificate)*/ CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(bytes)); } else if (clss == PrivateKey.class) { return /*(PrivateKey)*/ KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(bytes)); } else if (clss == SecretKey.class) { return (SecretKey)(new SecretKeySpec(bytes, "AES")); } } catch (Exception e) { tab.getTabPane().getSelectionModel().select(tab); alert(window, Alert.AlertType.ERROR, e); } return null; } String getKSObjString(Object obj) { if (obj instanceof Key) return (obj instanceof SecretKey ? "Size " + (((Key)obj).getEncoded().length * 8) + " bits, " : "") + "Algorithm " + ((Key)obj).getAlgorithm() + ", Format " + ((Key)obj).getFormat(); return obj.toString(); } boolean isProtected(Class<? extends KeyStore.Entry> clss) { return (clss == KeyStore.PrivateKeyEntry.class || clss == KeyStore.SecretKeyEntry.class); } EntryTreeItem getEntryTreeItem(Class<? extends KeyStore.Entry> clss) { for (TreeItem<String> eti : treeTableView.getRoot().getChildren()) if (((EntryTreeItem)eti).getEntryClass() == clss) return (EntryTreeItem)eti; return null; } EntryTreeItem getEntryTreeItem(String alias) { for (TreeItem<String> etir : treeTableView.getRoot().getChildren()) for (TreeItem<String> eti : etir.getChildren()) if (alias.equals(eti.getValue())) return (EntryTreeItem)eti; return null; } void infoDialog(Window owner, String title, String text) { TextArea ta = new TextArea(text); ta.setEditable(false); ta.setFont(Font.font("Monospaced")); ta.setPadding(new Insets(0)); Dialog<ButtonType> dialog = new Dialog<>(); dialog.initOwner(owner); dialog.initStyle(StageStyle.UTILITY); dialog.setResizable(true); dialog.setTitle(title); dialog.getDialogPane().setContent(ta); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK); dialog.getDialogPane().setPrefSize(480, 320); dpBehavior(dialog.getDialogPane()); dialog.showAndWait(); } void dpBehavior(DialogPane dialogPane) { for (ButtonType bt : dialogPane.getButtonTypes()) { Button b = (Button)dialogPane.lookupButton(bt); b.setDefaultButton(false); b.addEventHandler(KeyEvent.KEY_PRESSED, ke -> { if (ke.getCode() == KeyCode.ENTER) { ((Button)ke.getTarget()).fire(); ke.consume(); } }); } } class EntryTreeItem extends TreeItem<String> { Class<? extends KeyStore.Entry> entryClass; String password = null; EntryTreeItem(String alias, Class<? extends KeyStore.Entry> entryClass) { super(alias, (Node)null); this.entryClass = entryClass; } String getPassword() { return password; } void setPassword(String password) { this.password = password; } Class<? extends KeyStore.Entry> getEntryClass() { return entryClass; } } // end class EntryTreeItem } // end class MKeyStore