有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

数字签名如何从签名文件p7m/Enveloped和p7s/Enveloped中提取使用java Bouncycastle签名的原始文件

我需要从一个带有信封模式(p7m)或信封模式(p7s)的签名文件中提取它被签名的原始文件

我很难弄明白如何使用bouncycastle库来实现这一点

我使用了BouncyCastle 1.5和BouncyCastle 1.4

private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(GetOriginalContentFromFileSigned.class);

protected static CMSSignedData extractContent(InputStream buffer) throws IOException, CMSException {        
    CMSSignedData cms = null;
    CMSSignedData signature = new CMSSignedData(buffer);        
    Store cs = signature.getCertificates();
    SignerInformationStore signers = signature.getSignerInfos();
    Collection c = signers.getSigners();
    Iterator it = c.iterator();

    //the following array will contain the content of xml document
    byte[] data = null;

    while (it.hasNext()) {
        SignerInformation signer = (SignerInformation) it.next();
        Collection certCollection = cs.getMatches(signer.getSID());
        Iterator certIt = certCollection.iterator();
        X509CertificateHolder cert = (X509CertificateHolder) certIt.next();

        CMSProcessable sc = signature.getSignedContent();
        data = (byte[]) sc.getContent();
        cms = signature;
    }
    return cms;
}   

protected static byte[] getOriginalDocumentBinaries(InputStream signedDocument) {
    try (InputStream is = getOriginalDocumentStream(signedDocument)) {
        return IOUtils.toByteArray(is);
    } catch (Exception e) {
        logger.warn("Unable to retrieve original document binaries", e);
        return null;
    }
}

protected static InputStream getOriginalDocumentStream(InputStream signedDocument) throws Exception {
    final CMSSignedData cmsSignedData = getCmsSignedData(signedDocument);
    CMSTypedData signedContent = null;
    try{
        signedContent = (CMSTypedData) cmsSignedData.getSignedContent();
    }catch(Throwable t){        
        Object content = cmsSignedData.getSignedContent().getContent();
        if(content!=null){
            return new ByteArrayInputStream((byte[]) content);
        }
    }
    if (signedContent != null) {
        return new ByteArrayInputStream(getSignedContent(signedContent));
    }else{
        throw new Exception("Only enveloping and detached signatures are supported");
    }
}

protected static CMSSignedData getCmsSignedData(final InputStream dssDocument) throws CMSException, IOException {
    CMSSignedData cmsSignedData = null;
    if (isASN1SequenceTag(readFirstByte(dssDocument))) {
        try {
            cmsSignedData = new CMSSignedData(Base64.encodeBase64(IOUtils.toByteArray(dssDocument)));
        } catch (CMSException e) {
            logger.error("Can't get the CmisSigneData from P7M",e);
        }
    }else{
        logger.warn("Can't get the CmisSigneData from P7M with standard way");
        try {
            cmsSignedData = new CMSSignedData(Base64.encodeBase64(IOUtils.toByteArray(dssDocument)));
        } catch (CMSException e) {
            logger.error("Can't get the CmisSigneData from P7M with no standard way",e);                    
        }
    }           
    return cmsSignedData;
}

protected static boolean isASN1SequenceTag(byte tagByte) {
    // BERTags.SEQUENCE | BERTags.CONSTRUCTED = 0x30
    return (BERTags.SEQUENCE | BERTags.CONSTRUCTED) == tagByte;
}

protected static byte readFirstByte(final InputStream dssDocument) throws IOException{
    byte[] result = new byte[1];
    try (InputStream inputStream = dssDocument) {
        inputStream.read(result, 0, 1);
    } catch (IOException e) {
        throw new IOException(e);
    }
    return result[0];
}

protected static byte[] getSignedContent(final CMSTypedData cmsTypedData) throws Exception {
    if (cmsTypedData == null) {
        throw new Exception("CMSTypedData is null (should be a detached signature)");
    }
    try (ByteArrayOutputStream originalDocumentData = new ByteArrayOutputStream()) {
        cmsTypedData.write(originalDocumentData);
        return originalDocumentData.toByteArray();
    } catch (CMSException | IOException e) {
        throw new Exception(e);
    }
}

private interface BERTags
{
    public static final int BOOLEAN             = 0x01;
    public static final int INTEGER             = 0x02;
    public static final int BIT_STRING          = 0x03;
    public static final int OCTET_STRING        = 0x04;
    public static final int NULL                = 0x05;
    public static final int OBJECT_IDENTIFIER   = 0x06;
    public static final int EXTERNAL            = 0x08;
    public static final int ENUMERATED          = 0x0a; // decimal 10
    public static final int SEQUENCE            = 0x10; // decimal 16
    public static final int SEQUENCE_OF         = 0x10; // for completeness - used to model a SEQUENCE of the same type.
    public static final int SET                 = 0x11; // decimal 17
    public static final int SET_OF              = 0x11; // for completeness - used to model a SET of the same type.


    public static final int NUMERIC_STRING      = 0x12; // decimal 18
    public static final int PRINTABLE_STRING    = 0x13; // decimal 19
    public static final int T61_STRING          = 0x14; // decimal 20
    public static final int VIDEOTEX_STRING     = 0x15; // decimal 21
    public static final int IA5_STRING          = 0x16; // decimal 22
    public static final int UTC_TIME            = 0x17; // decimal 23
    public static final int GENERALIZED_TIME    = 0x18; // decimal 24
    public static final int GRAPHIC_STRING      = 0x19; // decimal 25
    public static final int VISIBLE_STRING      = 0x1a; // decimal 26
    public static final int GENERAL_STRING      = 0x1b; // decimal 27
    public static final int UNIVERSAL_STRING    = 0x1c; // decimal 28
    public static final int BMP_STRING          = 0x1e; // decimal 30
    public static final int UTF8_STRING         = 0x0c; // decimal 12

    public static final int CONSTRUCTED         = 0x20; // decimal 32
    public static final int APPLICATION         = 0x40; // decimal 64
    public static final int TAGGED              = 0x80; // decimal 128
}

部分代码取自https://github.com/esig/dss项目

“getOriginalDocumentBinaries”方法让工作变得有效,我缺少了什么? 我觉得没问题,但我不擅长弹跳

你好


共 (1) 个答案

  1. # 1 楼答案

    我只是遇到了同样的问题,我实现了这个。我相信这会对其他人有所帮助

    /**
    *Extract from .p7m file and write into new file  
    */
    
    public void extractTxtFileFromP7M() throws Exception {
        File file = new File(".p7m FilePath");
        String fileName = FilenameUtils.removeExtension(file.getName());
        byte[] p7mFileByteArray = fromFileToByteArray(file);
        byte[] extractedFileByteArray = getData(p7mFileByteArray);
        File extractedFile = new File("..../fileName");
        FileUtils.writeByteArrayToFile(extractedFile, extractedFileByteArray);
    }
    private byte[] fromFileToByteArray(File file) {
        try {
            return FileUtils.readFileToByteArray(file);
        } catch (IOException e) {
            log.error("Error while reading .p7m file!", e);
        }
        return new byte[0];
    }
    private byte[] getData(final byte[] p7bytes) {
        CMSSignedData cms = null;
        try {
            cms = new CMSSignedData(p7bytes);
        } catch (CMSException e) {
            log.error("Error while converting bytes to CMSSignedData : " + e.getMessage(), e);
        }
        if( cms == null || cms.getSignedContent() == null) {
            return new byte[0];
        }
        return (byte[]) cms.getSignedContent().getContent();
    }