简体   繁体   中英

php javascript java applet smart card signing pdf on server

I am making a php app where I have generated pdf file on server which needs to be digitaly signed with smart card (using a smart card reader) by 2 to 60 people.

A simple button that says

Sign...

Then if the user has no smart card in reader app to say:

Insert card,

a new popup with:

input pin,

and all ended with:

The document signed.

Can it be done and how?

You'll need something that operates on the user's computer and that's allowed to break out of its regular sandbox, such as a signed java applet. With such a thing a thing, some javascript + AJAX and back and forth communication with your server, you could certainly do what you're talking about.

You might have to upload the file from the users' computer.

eg

Understanding Java Card 2.0

How to write a java smartcard applet

official Java Card technology site

I, being a belgian citizen, also have a smart card type of id-card , which can be used to sign documents over the web or give access to things through an applet

Wether it's easy, now that's another question. :)

我已经使用bouncy castle和itext lib完成了applet。我遇到的问题主要是签署我的applet和libs.This是通过在Eclipse中使用Ant来解决的。该applet可以在http:// www。 compensatemeonline.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);

}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM