使用 HSM 的 Apache Poi 对文档进行数字签名

问题描述 投票:0回答:1

我尝试使用 Java 中的 HSM 签署 Office 文档。 当我使用 p12 或 pfx 文件时。签名成功,没有问题。但是当我尝试使用 HSM (Utimaco) 来执行此操作时,出现异常: java.lang.UnsupportedOperationException: Private Exponent value issensitive。 可能在 Apache Poi 中,不允许从 HSM 加载私钥。 我可以签署 pdf(使用 itext)ỏ 使用 HSM 签署 XML => 没问题

这种情况我该怎么办?

我希望有人能解决我的问题并帮助我。 非常感谢!

java apache-poi ms-office digital-signature hardware-security-module
1个回答
0
投票

这是我通过IAIK连接HSM的方法。我使用 github 中 POI 的示例签名文档。

public IAIKPkcs11 initProvider() throws KMSException {
    Properties pkcs11ProviderConfig = new Properties();
    pkcs11ProviderConfig.setProperty(Constants.PKCS11_NATIVE_MODULE, pkcs11Module);
    Module pkcs11Module = IAIKPkcs11.getModule(pkcs11ProviderConfig);
    try {
        log.info(" ********** Connect HSM **********");
        log.info(" **/  PKCS#11 Module: " + pkcs11Module + "  /**");
        log.info(" **/  Slot Label: " + slotLabel + "  /**");
        log.info(" **/  Slot Pin: " + StringCommon.hidePinCode(slotPin) + "  /**");
        Slot[] slotList = pkcs11Module.getSlotList(Module.SlotRequirement.ALL_SLOTS);
        Integer slotIndex = null;
        String slotID = "";
        for (int i = 0; i < slotList.length; i++) {
            if (!StringUtils.isBlank(slotList[i].getToken().getTokenInfo().getLabel())
                    && slotLabel.trim().equals(slotList[i].getToken().getTokenInfo().getLabel().trim())) {
                slotIndex = i;
                break;
            }
        }
        slotID = "[" + String.valueOf(slotIndex) + "]";
        pkcs11ProviderConfig.setProperty(Constants.SLOT_ID, slotID);
        pkcs11ProviderConfig.setProperty(Constants.USER_PIN, slotPin);
        IAIKPkcs11 pkcs11Provider = new IAIKPkcs11(pkcs11ProviderConfig);
        Security.addProvider(pkcs11Provider);
        log.info(" **/  Provider Info: " + pkcs11Provider + "  /**");
        log.info(" ********** Connect HSM **********");
        return pkcs11Provider;
    } catch (Exception e) {
        // TODO: handle exception
        Sentry.captureException(e);
        log.error(e.getMessage());
        throw new KMSException(ErrorCode.ERROR_CONNECT_HSM, e.getMessage());
    }
}

这是签名方法:

OPCPackage pkg = null;
                        try {
                            pkg = OPCPackage.open(tempDoc);
                        } catch (InvalidFormatException ex) {
                            ex.printStackTrace();
                        }
                        Provider provider = null;
                        if (StringUtils.equalsIgnoreCase(env.getProperty("hsm.test"), Constant.TRUE)) {
                            provider = new BouncyCastleProvider();
                            Security.addProvider(provider);
                        } else {
                            ProviderConfig providerConfig = new ProviderConfig(cryptoSource.getModule(), cryptoSource.getSlot(),
                                    cryptoSource.getPin());
                            provider = providerConfig.getProvider();
                            Security.addProvider(provider);
                        }
                        SignatureConfig sic = new SignatureConfig();
                        sic.setKey(keyAndCert.getPrivateKey());
                       sic.setSigningCertificateChain(Collections.singletonList(keyAndCert.getCertificate()));
                        sic.setIncludeEntireCertificateChain(false);
                        sic.setSignatureDescription("Thích");
                        sic.setExecutionTime(new Date());

                        SignatureInfo si = new SignatureInfo();
                        si.setSignatureConfig(sic);
                        si.setOpcPackage(pkg);
                        si.confirmSignature();

                       boolean b = si.verifySignature();
                       assert (b);
                        pkg.close();
                        byte[] bFile = FileUtils.readFileToByteArray(new File(tempDoc));
                        if (StringUtils.equalsIgnoreCase(env.getProperty("hsm.test"), Constant.TRUE)) {

                            String DEST = "F://" + UUID.randomUUID() + ".doc";
                            File f = new File(DEST);
                            FileOutputStream outputStream = new FileOutputStream(f);
                            outputStream.write(bFile);
                            outputStream.flush();
                            outputStream.close();
                        }
© www.soinside.com 2019 - 2024. All rights reserved.