Я создаю приложение php, где у меня есть файл pdf на сервере, который должен быть подписан на цифровом устройстве с помощью смарт-карты (с использованием устройства чтения смарт-карт) на 2-60 человек.
Простая кнопка, которая гласит:
Знак…
Тогда, если у пользователя нет смарт-карты в приложении для чтения, чтобы сказать:
Вставьте карту,
новое всплывающее окно:
входной штырь,
и все закончилось:
Документ подписан.
Можно ли это сделать и как?
Вам понадобится что-то, что работает на компьютере пользователя, и это позволяет вырваться из его обычной песочницы, например, подписанного java-апплета. С такой штукой вещи, некоторые javascript + AJAX и обратно и вперед связь с вашим сервером, вы, безусловно, могли бы сделать то, о чем вы говорите.
Возможно, вам придется загрузить файл с компьютера пользователя.
например
Понимание Java Card 2.0
Как написать апплет смарт-карты java
официальный сайт технологии Java Card
Я, будучи бельгийским гражданином, также имею идентификационную карту смарт -карты , которую можно использовать для подписи документов через Интернет или доступа к вещам через апплет
Уэтер это легко, теперь это другой вопрос. 🙂
Я закончил апплет, используя bouncy castle и itext libs.У меня были проблемы с подписью моего апплета и libs.This была решена с помощью Ant в Eclipse. Апплет можно увидеть по адресу http: // www. correatemeonline.com/applet/japplet.html .
package compensatemeonline8; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.*; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.security.*; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import java.io.File; import java.lang.reflect.Method; public class CompensateMeOnlineApplet extends java.applet.Applet { private static final long serialVersionUID = -5290769300644275624L; String alias = new String(); @Override public void init() { try { try { java.awt.EventQueue.invokeAndWait(new Runnable() { @Override public void run() { initComponents(); } }); } catch (Exception ex) { ex.printStackTrace(); } File file = new File(".."); System.out.println("where the pdf you should :" + file.getAbsolutePath()); KeyStore keyStore = null; Provider pjacapi = Security.getProvider("CAPI"); final Provider pmscapi = Security.getProvider("SunMSCAPI"); System.out.println("pmscapi:" + pmscapi); if (pmscapi != null) { AccessController .doPrivileged(new PrivilegedExceptionAction<Boolean>() { @Override public Boolean run() throws Exception { pmscapi.setProperty("Signature.SHA1withRSA", "sun.security.mscapi.RSASignature$SHA1"); return true; } }); keyStore = KeyStore.getInstance("Windows-MY", pmscapi); System.out.println("keystore: " + keyStore); } else if (pjacapi != null) { keyStore = KeyStore.getInstance("CAPI"); } if (keyStore != null) { keyStore.load(null, null); Enumeration<String> enums = keyStore.aliases(); while (enums.hasMoreElements()) { this.jComboBox1.addItem((String) enums.nextElement()); } } } catch (IOException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (CertificateException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (KeyStoreException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (Exception ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } } /** * This method is called from within the init() method to initialize the * form. WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { jComboBox1 = new javax.swing.JComboBox(); jButton1 = new javax.swing.JButton(); jButton2 = new javax.swing.JButton(); setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); jComboBox1.setModel(new javax.swing.DefaultComboBoxModel( new String[] { "Choose signature to sign with" })); jButton1.setText("Sign"); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); jButton2.setText("Exit"); jButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton2ActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addContainerGap() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addComponent( jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent( jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 89, Short.MAX_VALUE)) .addGroup( javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent( jButton2))) .addContainerGap())); layout.setVerticalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addContainerGap() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent( jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jButton1)) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED, 23, Short.MAX_VALUE) .addComponent(jButton2).addContainerGap())); }// </editor-fold> private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { alias = (String) jComboBox1.getSelectedItem(); if (alias.equals("Choose signature to sign with")) { JOptionPane.showMessageDialog(jComboBox1, "Must select a signature to sign with!"); // System.exit(1); return; } // JOptionPane.showMessageDialog(jComboBox1, alias); try { potpisi(); JOptionPane.showMessageDialog(jComboBox1, "Document signed"); // TODO add your handling code here: } catch (KeyStoreException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (CertificateException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (UnrecoverableKeyException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (DocumentException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (InvalidKeyException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (SignatureException ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } catch (Exception ex) { Logger.getLogger(CompensateMeOnlineApplet.class.getName()).log( Level.SEVERE, null, ex); } } private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { System.exit(1); // TODO add your handling code here: } // Variables declaration - do not modify private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; private javax.swing.JComboBox jComboBox1; // End of variables declaration @Override public void start() { } public void potpisi() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, DocumentException, InvalidKeyException, SignatureException, Exception { KeyStore ks = null; Provider pjacapi = Security.getProvider("CAPI"); final Provider pmscapi = Security.getProvider("SunMSCAPI"); if (pmscapi != null) { AccessController .doPrivileged(new PrivilegedExceptionAction<Boolean>() { @Override public Boolean run() throws Exception { pmscapi.setProperty("Signature.SHA1withRSA", "sun.security.mscapi.RSASignature$SHA1"); return true; } }); ks = KeyStore.getInstance("Windows-MY", pmscapi); } else if (pjacapi != null) { ks = KeyStore.getInstance("CAPI"); } if (ks != null) { ks.load(null, null); } ks.load(null, null); // ovo smo ubacili Enumeration en = ks.aliases(); PrivateKey key = (PrivateKey) ks .getKey(alias, "password".toCharArray()); java.security.cert.Certificate[] chain = ks.getCertificateChain(alias); PdfReader reader = new PdfReader( "Compensate.pdf"); FileOutputStream fout = new FileOutputStream("signed.pdf"); PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', null, true); PdfSignatureAppearance appearance = stp.getSignatureAppearance(); appearance.setCrypto(null, chain, null, PdfSignatureAppearance.SELF_SIGNED); appearance.setReason("Potpis kompenzacije"); appearance.setLocation("Foobar"); appearance.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, "jedan"); appearance.setExternalDigest(new byte[128], null, "RSA"); appearance.preClose(); Signature signature = Signature.getInstance("SHA1withRSA"); signature.initSign(key); byte buf[] = new byte[8192]; int n; InputStream inp = appearance.getRangeStream(); while ((n = inp.read(buf)) > 0) { signature.update(buf, 0, n); } PdfPKCS7 sig = appearance.getSigStandard().getSigner(); sig.setExternalDigest(signature.sign(), null, "RSA"); PdfDictionary dic = new PdfDictionary(); dic.put(PdfName.CONTENTS, new PdfString(sig.getEncodedPKCS1()).setHexWriting(true)); appearance.close(dic); } }