如何使用 Java 以编程方式签署二进制 MS Office 文档? [英] How to programmatically sign a binary MS office document with Java?

查看:58
本文介绍了如何使用 Java 以编程方式签署二进制 MS Office 文档?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们如何在 Apache POI 或任何其他开源库中对遗留的二进制 MS-Office 文档(doc、xls、ppt)进行数字签名?

How can we digitally sign a legacy binary MS-Office document (doc, xls, ppt) in Apache POI, or any other open source library?

介绍了 Open XML 格式如何使用 Java 以编程方式签署 MS Office XML 文档?

推荐答案

我可以通过创建分离的 xml 签名来签署 .doc 文件,然后使用 PIOFSFileSystem 将其添加到根目录下,示例如下:

I was able to sign .doc file by creating detached xml signature, then adding it under root directory using POIFSFileSystem, example is below :

public class OfficeDocumentSigner2 {


    public static void main(String[] args) {
        signClassicOfficeDocuments();
    }

    private static String sign() {

        // First, create a DOM XMLSignatureFactory that will be used to
        // generate the XMLSignature and marshal it to DOM.
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
        OutputStream os = null;
        String signedDoc = "C:\\Users\\Desktop\\digitalSign\\signdoc_signed.xml";
        try {
            // Create a Reference to an external URI that will be digested
            // using the SHA1 digest algorithm

            Reference ref = fac.newReference(officeFilePath, fac.newDigestMethod(DigestMethod.SHA1, null));
            // Create the SignedInfo
            SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                    Collections.singletonList(ref));

            // Create the Document that will hold the resulting XMLSignature --> detached
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true); // must be set
            Document doc = dbf.newDocumentBuilder().newDocument();

            // certificate info
            File file = new File("C:\\Users\\Desktop\\digitalSign\\test101\\KeyStore.jks");
            // extracting private key and certificate
            String alias = "certAlias";
            X509Certificate x509 = null;
            // loading the keystore
            KeyStore keystore = KeyStore.getInstance("JKS");
            FileInputStream fis = new FileInputStream(file);
            keystore.load(fis, password);
            fis.close();
            x509 = (X509Certificate) keystore.getCertificate(alias);
            KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) keystore.getEntry(alias, new KeyStore.PasswordProtection(password));

            // Create the KeyInfo containing the X509Data.
            // ref : http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html
            KeyInfoFactory kif = fac.getKeyInfoFactory();
            List x509Content = new ArrayList();
            x509Content.add(x509.getSubjectX500Principal().getName());
            x509Content.add(x509);
            X509Data xd = kif.newX509Data(x509Content);
            KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

            // Create a DOMSignContext and specify the DSA PrivateKey and
            // location of the resulting XMLSignature's parent element
            DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc);
            dsc.setBaseURI(baseURI);
            // Create the XMLSignature (but don't sign it yet)
            XMLSignature signature = fac.newXMLSignature(si, ki);

            // Marshal, generate (and sign) the enveloped signature
            signature.sign(dsc);

            // Output the resulting document.

            os = new FileOutputStream(signedDoc);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(doc), new StreamResult(os));


        } catch (Exception e) {
            e.printStackTrace();
        }
        return signedDoc;
    }

    public static void signClassicOfficeDocuments() {

        InputStream is;
        try {
            //sign document
            String signaturePath = sign();
            InputStream signatureAsIS = new FileInputStream(signaturePath);

            is = new FileInputStream(fileName);
            POIFSFileSystem poifs = new POIFSFileSystem(is);
            DirectoryEntry dirEntry =  poifs.createDirectory("_xmlsignatures"); // create a new DirectoryEntry in the root directory
            dirEntry.createDocument("9149", signatureAsIS);

            String destPath = "C://Users//Desktop//digitalSign//test_11_24_signedByMe.doc";
            OutputStream os = new FileOutputStream(destPath);
            poifs.writeFilesystem(os);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}

这篇关于如何使用 Java 以编程方式签署二进制 MS Office 文档?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆