/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* Copyright (c) 2013, MPL CodeInside http://codeinside.ru
*/
package ru.codeinside.sign;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import java.io.IOException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.BoxLayout;
final class CertSelector implements Runnable {
final Panel ui;
final java.util.List<Cert> certs;
final CertConsumer consumer;
final String fio;
Cert selectedCert;
CertSelector(Panel ui, ArrayList<Cert> certs, CertConsumer consumer, String fio) {
this.ui = ui;
this.certs = certs;
this.consumer = consumer;
this.fio = fio;
}
CertSelector(Panel ui, ArrayList<Cert> certs, CertConsumer consumer) {
this.ui = ui;
this.certs = certs;
this.consumer = consumer;
this.fio = null;
}
@Override
public void run() {
ui.removeAll();
final Label comp1 = new Label(consumer.getSelectionLabel());
final Label comp2 = new Label("подпись, соответствующую данной учетной записи.");
final Label comp3 = new Label("Использовать данную ЭП в СИУ невозможно.");
Panel p = new Panel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.add(comp1);
p.add(comp2);
p.add(comp3);
Font f = new Font("Arial", Font.PLAIN, 12);
comp1.setFont(f);
comp2.setFont(f);
comp3.setFont(f);
comp2.setVisible(false);
comp3.setVisible(false);
comp2.setBackground(Color.RED);
comp3.setBackground(Color.RED);
ui.add(p, BorderLayout.PAGE_START);
List list = new List();
for (Cert cert : certs) {
list.add(cert.name);
}
ui.add(list, BorderLayout.CENTER);
final Button next = new Button(" Ввести пароль ");
next.setEnabled(false);
Panel panel = new Panel(new BorderLayout());
panel.add(next, BorderLayout.LINE_END);
ui.add(panel, BorderLayout.PAGE_END);
list.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
boolean selected = ItemEvent.SELECTED == e.getStateChange();
if (selected) {
selectedCert = certs.get((Integer) e.getItem());
if (consumer instanceof Binder || consumer instanceof Rebinder) {
String certificateFIO = selectedCert.extract(selectedCert.certificate.getSubjectDN().getName(), "CN=");
String surName = selectedCert.extract(selectedCert.certificate.getSubjectDN().getName(), "SURNAME=");
String givenName = selectedCert.extract(selectedCert.certificate.getSubjectDN().getName(), "GIVENNAME=");
if ((surName != null && givenName != null && fio.equals(surName + " " + givenName)) || fio.equals(certificateFIO)) {
comp1.setText("Выбранная электронная подпись соответствует данной учетной записи.");
comp2.setVisible(false);
comp1.setBackground(null);
next.setEnabled(true);
} else {
comp1.setText("Неверно выбрана электронная подпись. Выберите электронную");
comp1.setBackground(Color.RED);
comp2.setVisible(true);
next.setEnabled(false);
}
} else if (consumer instanceof Signer) {
comp2.setText("Обратитесь в Удостоверяющий центр для получения новой ЭП.");
long certificateTime = selectedCert.certificate.getNotAfter().getTime();
long currentTime = System.currentTimeMillis();
long privateKeyTime = getPrivateKeyTime(selectedCert.certificate);
if (currentTime <= certificateTime && (privateKeyTime == 0L || currentTime <= privateKeyTime)) {
next.setEnabled(true);
comp1.setText("Вы можете использовать выбранную подпись.");
comp1.setBackground(null);
comp2.setVisible(false);
comp3.setVisible(false);
} else {
next.setEnabled(false);
comp1.setText("Срок действия закрытого ключа ЭП истек в " +
new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(privateKeyTime))
);
comp1.setBackground(Color.RED);
comp2.setVisible(true);
comp3.setVisible(true);
}
}
}
refresh();
}
});
refresh();
ActionListener certSelector = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ui.removeAll();
ui.add(new Label(selectedCert.name), BorderLayout.PAGE_START);
final TextField pass = new TextField();
pass.setEchoChar('*');
Panel panel3 = new Panel(new GridBagLayout());
final Label hint = new Label("Введите пароль:");
panel3.add(hint, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.LAST_LINE_START,
GridBagConstraints.HORIZONTAL, new Insets(2, 2, 0, 2), 0, 0));
panel3.add(pass, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.FIRST_LINE_START,
GridBagConstraints.HORIZONTAL, new Insets(0, 2, 2, 2), 0, 0));
ui.add(panel3, BorderLayout.CENTER);
final Button prev = new Button("Выбрать сертификат");
prev.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(new CertLoading(consumer));
}
});
final Button next = new Button(consumer.getActionText());
Panel panel = new Panel(new BorderLayout(2, 2));
panel.add(prev, BorderLayout.LINE_START);
panel.add(next, BorderLayout.LINE_END);
ui.add(panel, BorderLayout.PAGE_END);
consumer.refresh();
pass.addTextListener(new TextListener() {
@Override
public void textValueChanged(TextEvent e) {
next.setEnabled(true);
hint.setText("Пароль:");
}
});
ActionListener withPass = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
prev.setEnabled(false);
next.setEnabled(false);
pass.setEnabled(false);
hint.setText("Проверка пароля...");
refresh();
try {
KeyStore keyStore = KeyStore.getInstance(selectedCert.type + "Store", "JCP");
keyStore.load(null, null);
char[] password = pass.getText().toCharArray().length > 0 ? pass.getText().toCharArray() : null;
PrivateKey privateKey = (PrivateKey) keyStore.getKey(selectedCert.alias, password);
if (privateKey != null) {
consumer.ready(selectedCert.name, privateKey, selectedCert.certificate);
} else {
hint.setText("Сертификат не поддерживается");
prev.setEnabled(true);
refresh();
}
} catch (Exception ex) {
if ("Password is not valid.".equals(ex.getMessage())) {
hint.setText("Ошибка, введите правильный пароль!");
} else {
hint.setText(ex.getMessage());
}
prev.setEnabled(true);
pass.setEnabled(true);
pass.requestFocus();
refresh();
}
}
};
pass.addActionListener(withPass);
next.addActionListener(withPass);
pass.requestFocus();
refresh();
}
};
next.addActionListener(certSelector);
list.requestFocus();
refresh();
}
private void refresh() {
ui.validate();
ui.repaint();
}
long getPrivateKeyTime(X509Certificate certificate) {
long time = 0L;
try {
byte[] value = certificate.getExtensionValue("2.5.29.16");
if (value != null) {
DerInputStream der = new DerInputStream(value);
der = new DerInputStream(der.getOctetString());
DerValue[] sequence = der.getSequence(2);
time = new SimpleDateFormat("yyyyMMddHHmmss'Z'").parse(new String(sequence[1].getDataBytes())).getTime();
}
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return time;
}
}