当前位置: 首页 > 面试题库 >

在服务器客户端条件下使用USB驱动程序对PDF进行sigin

姬高扬
2023-03-14
问题内容

我正在做一个项目,我需要使用基于USB的数字签名来签署pdf。我已经在本地尝试了以下代码,并且能够对pdf进行签名。我的问题是天气,以下代码将在基于客户端服务器的senerio中工作。

我的代码是:

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfSignatureAppearance;
import com.lowagie.text.pdf.PdfStamper;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CRL;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import javax.servlet.RequestDispatcher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.security.mscapi.SunMSCAPI;

public class Testing {
    private static boolean resFlag;

    public static void main (String args[])
    {
     try {

        BouncyCastleProvider providerBC = new BouncyCastleProvider();
        Security.addProvider(providerBC);
        SunMSCAPI providerMSCAPI = new SunMSCAPI();
        Security.addProvider(providerMSCAPI);
        KeyStore ks = KeyStore.getInstance("Windows-MY");
        ks.load(null, null);
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey)ks.getKey(alias, null);
        Certificate[] chain = ks.getCertificateChain(alias);


//         //String e = request.getParameter("digiFile");
//         KeyStore ks = KeyStore.getInstance("pkcs12");
//         String f10 = CommonUtil.getRealPath();
//         String str8 = f10 + "/DigiFiles/";
//         //System.out.println("str8-->>>>>>>>" + str8 + e);
//          ks.load(new FileInputStream("F:/DigiFiles/Anurag Goel.pfx"), "123".toCharArray());
//
//
//         System.out.println("The actual path is " + str8);
//         String alias = (String)ks.aliases().nextElement();
//         PrivateKey key = (PrivateKey)ks.getKey(alias, "123".toCharArray());
//         Certificate[] chain = ks.getCertificateChain(alias);
         PdfReader reader = new PdfReader("F:/test.pdf");
         FileOutputStream os = new FileOutputStream("F:/SampleOutPut61.pdf");
         PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0',null,true);
         PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
         appearance.setCrypto(pk, chain, (CRL[])null, PdfSignatureAppearance.VERISIGN_SIGNED);
         appearance.setReason("elicense project");
         appearance.setLocation("Assam");
         appearance.setVisibleSignature("hi");
         stamper.close();
      } catch (KeyStoreException var27) {
         var27.printStackTrace();
         resFlag = false;
      } catch (NoSuchAlgorithmException var28) {
         var28.printStackTrace();
         resFlag = false;
      } catch (CertificateException var29) {
         var29.printStackTrace();
         resFlag = false;
      } catch (FileNotFoundException var30) {
         var30.printStackTrace();
         resFlag = false;
      } catch (IOException var31) {
         var31.printStackTrace();
         resFlag = false;
      } catch (UnrecoverableKeyException var32) {
         var32.printStackTrace();
         resFlag = false;
      } catch (DocumentException var33) {
         var33.printStackTrace();
         resFlag = false;
      } catch (Exception var34) {
         var34.printStackTrace();
         resFlag = false;
      } finally {
         RequestDispatcher rd;


      }

   }
}

请给我建议。谢谢大家


问题答案:
  1. 您使用了错误的iText版本,因此您创建的签名不能为将来使用(请阅读本书以了解代码有什么问题)。
  2. 您取决于操作系统是Windows的事实。您的服务器也是Windows服务器吗?如果它是Linux服务器,则您的代码将不起作用。请与您的托管服务提供商联系,并询问您的托管服务提供商是否允许您在该服务器上拥有USB令牌(如果它不是专用服务器,则他们很可能会拒绝这样做)。
  3. 您正在使用Windows-MY,这意味着您将身份验证委派给操作系统。如果USB需要密码(通常是这样),则Windows将打开一个对话框供您填写该密码。如果将其部署在服务器上:每次有人请求签名时,都会有人坐在该服务器旁边来填写该密码吗?
  4. USB令牌旨在供人们手动签名文档。它们通常具有特定的限制。例如:通常,您每秒不能应用超过1个签名。在网络环境中,这通常是不够的。在Web环境中,您应该使用在服务器上安装硬件安全模块(HSM)。

虽然您的代码理论上可以在服务器上工作,但是我看到很多原因,为什么在客户端/服务器环境中使用在独立计算机上运行的代码不是明智的决定。有太多实际问题(例如身份验证,速度,iText版本错误等)会使您的项目出错。对于您的问题,该代码是否可以在客户端/服务器方案中运行,我将回答“否”。

更新:

在对我的答案的评论中,表明您的服务器是Linux服务器。很明显,在Linux服务器上使用“ Windows-
MY”将永远无效。您必须使用PKCS#11而不是Windows-MY与存储令牌的硬件设备通信。这是一个代码示例,可用于SafeNet的Luna
SA。如您所见,它使用PKCS#11:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import sun.security.pkcs11.SunPKCS11;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.CertificateUtil;
import com.itextpdf.text.pdf.security.CrlClient;
import com.itextpdf.text.pdf.security.CrlClientOnline;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;

public class C4_01_SignWithPKCS11HSM {

    public static final String SRC = "/home/itext/hello.pdf";
    public static final String PROPS = "/home/itext/key.properties";
    public static final String DEST = "/home/itext/hello_hsm.pdf";

    public void sign(String src, String dest,
            Certificate[] chain, PrivateKey pk,
            String digestAlgorithm, String provider, CryptoStandard subfilter,
            String reason, String location,
            Collection<CrlClient> crlList,
            OcspClient ocspClient,
            TSAClient tsaClient,
            int estimatedSize)
                    throws GeneralSecurityException, IOException, DocumentException {
        // Creating the reader and the stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        // Creating the appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason(reason);
        appearance.setLocation(location);
        appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
        // Creating the signature
        ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
    }

    public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {

        LoggerFactory.getInstance().setLogger(new SysoLogger());

        Properties properties = new Properties();
        properties.load(new FileInputStream(PROPS));
        char[] pass = properties.getProperty("PASSWORD").toCharArray();
        String pkcs11cfg = properties.getProperty("PKCS11CFG");

        BouncyCastleProvider providerBC = new BouncyCastleProvider();
        Security.addProvider(providerBC);
        FileInputStream fis = new FileInputStream(pkcs11cfg);
        Provider providerPKCS11 = new SunPKCS11(fis);
        Security.addProvider(providerPKCS11);

        KeyStore ks = KeyStore.getInstance("PKCS11");
        ks.load(null, pass);
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey)ks.getKey(alias, pass);
        Certificate[] chain = ks.getCertificateChain(alias);
        OcspClient ocspClient = new OcspClientBouncyCastle();
        TSAClient tsaClient = null;
        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = (X509Certificate)chain[i];
            String tsaUrl = CertificateUtil.getTSAURL(cert);
            if (tsaUrl != null) {
                tsaClient = new TSAClientBouncyCastle(tsaUrl);
                break;
            }
        }
        List<CrlClient> crlList = new ArrayList<CrlClient>();
        crlList.add(new CrlClientOnline(chain));
        C4_01_SignWithPKCS11HSM app = new C4_01_SignWithPKCS11HSM();
        app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(), CryptoStandard.CMS,
                "HSM test", "Ghent", crlList, ocspClient, tsaClient, 0);
    }
}

使用的配置文件的内容如下所示:

Name = Luna
library = /usr/lunasa/lib/libCryptoki2_64.so
slot = 1

请注意,根据so您的情况,可能在另一个目录中,并且您的证书可能在另一个插槽中。我还使用属性文件来存储证书的密码。显然,我不会共享密码;-)

此示例已在GlobalSign拥有的服务器上使用GlobalSign证书进行了测试。



 类似资料:
  • 当在客户机模式下使用spark时(例如,yarn-client),运行驱动程序的本地机器是否直接与运行远程执行器的集群工作节点通信? 如果是,是否意味着如果集群的配置方式是工作节点在集群之外不可见,那么客户机模式将无法工作,并且必须使用集群模式? 谢了!

  • 我正在开发一个通讯系统: A、B是NAT下的计算机,A是服务器B是客户端S是STUN服务器 %S正在Internet上可访问的计算机上运行 麻烦就从这里开始,STUN服务器完成了它的工作,因为两端都接收到关于另一端的正确信息。 但是我从来没有接收到另一端的消息,所以两端都在监听,没有接收到握手操作码或其他任何东西。 我检查了NAT的行为,似乎它是这样的 我运行的测试看到两端(A,B)托管在同一台机

  • 问题内容: 每当将任何USB闪存驱动器(不仅是特定的USB闪存驱动器)插入系统时,我都试图运行一个脚本,并且我已经断断续续地花了大约2周的时间来尝试找出问题。有谁能够帮助我?(如果有帮助,请运行Ubuntu)。 我需要至少传递驱动器序列号和devpath(/ dev / sd **)。 问题答案: 首先,您需要使用规则来检测USB存储设备 /etc/udev/rules.d/10-usbmount

  • 我正在使用TCP / IP流编写客户端服务器Java程序,我的服务器连接到oracle数据库。当客户端请求一些信息时,服务器处理查询,即返回一个包含一些行的列(例如 5)。我想将整列发送回客户端,我能够发送和接收单行数据,但不能发送和接收多行(因为表包含许多行 i,e 行)....任何帮助都是可取的

  • 问题内容: 我正在尝试使用我一直在努力的客户端/服务器程序实现多线程。我需要允许多个客户端同时连接到服务器。我目前有4类:客户端,服务器,协议和用于处理线程的工作器。以下代码是我对这些类的拥有的代码: SocketServer类: SocketClient类别: 协议类别: ClientWorker类: 当我运行服务器和客户端时,一切正常。然后,当我尝试运行另一个客户端时,它只是挂在那儿,没有提示

  • 问题内容: 我做一个简单的, 没有线程 客户端 - 服务器 进行GUI有两个一个按钮程序 服务器 和 客户 端。当 客户端 按下按钮时,它将按钮上的文本更改为 “ C” 并发送到 服务器 “ C” 字符串,因此 服务器 端的按钮将文本更改为 “ C” 。 服务器的 工作方式与 客户端 相似,但是发送的是 “ S” 而不是 “ C” 。他们轮流工作:轮到 客户时 , 服务器 客户端 始终首先启动。