• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ebourg / jsign / #370

25 Apr 2025 04:41PM UTC coverage: 83.31% (+0.008%) from 83.302%
#370

push

ebourg
Changelog update

4862 of 5836 relevant lines covered (83.31%)

0.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.84
/jsign-core/src/main/java/net/jsign/cat/CatalogFile.java
1
/*
2
 * Copyright 2022 Emmanuel Bourg and contributors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package net.jsign.cat;
18

19
import java.io.File;
20
import java.io.IOException;
21
import java.nio.ByteBuffer;
22
import java.nio.channels.Channels;
23
import java.nio.channels.SeekableByteChannel;
24
import java.nio.file.Files;
25
import java.nio.file.StandardOpenOption;
26
import java.util.Collections;
27
import java.util.List;
28

29
import org.bouncycastle.asn1.ASN1Object;
30
import org.bouncycastle.cms.CMSException;
31
import org.bouncycastle.cms.CMSSignedData;
32
import org.bouncycastle.cms.CMSTypedData;
33
import org.bouncycastle.cms.SignerInformationStore;
34
import org.bouncycastle.util.CollectionStore;
35

36
import net.jsign.DigestAlgorithm;
37
import net.jsign.Signable;
38
import net.jsign.SignatureUtils;
39

40
/**
41
 * Windows Catalog file.
42
 *
43
 * @see <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/install/catalog-files">Windows Drivers - Catalog Files and Digital Signatures</a>
44
 * @since 4.2
45
 */
46
public class CatalogFile implements Signable {
47

48
    private final SeekableByteChannel channel;
49

50
    private CMSSignedData signedData;
51

52
    /**
53
     * Tells if the specified file is a Windows catalog file.
54
     *
55
     * @param file the file to check
56
     * @return <code>true</code> if the file is a Windows catalog, <code>false</code> otherwise
57
     */
58
    public static boolean isCatalogFile(File file) {
59
        if (!file.exists() || !file.isFile()) {
1✔
60
            return false;
×
61
        }
62

63
        try {
64
            CatalogFile catFile = new CatalogFile(file);
1✔
65
            catFile.close();
1✔
66
            return true;
1✔
67
        } catch (IOException e) {
1✔
68
            return false;
1✔
69
        }
70
    }
71

72
    /**
73
     * Create a Windows catalog from the specified file.
74
     *
75
     * @param file the file to open
76
     * @throws IOException if an I/O error occurs
77
     */
78
    public CatalogFile(File file) throws IOException {
79
        this(Files.newByteChannel(file.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE));
1✔
80
    }
1✔
81

82
    /**
83
     * Create a Windows catalog from the specified channel.
84
     *
85
     * @param channel the channel to read the file from
86
     * @throws IOException if an I/O error occurs
87
     */
88
    public CatalogFile(SeekableByteChannel channel) throws IOException {
1✔
89
        this.channel = channel;
1✔
90

91
        channel.position(0);
1✔
92

93
        try {
94
            signedData = new CMSSignedData(Channels.newInputStream(channel));
1✔
95
        } catch (CMSException e) {
1✔
96
            throw new IOException("Catalog file format error", e);
1✔
97
        }
1✔
98
    }
1✔
99

100
    @Override
101
    public void close() throws IOException {
102
        channel.close();
1✔
103
    }
1✔
104

105
    @Override
106
    public CMSTypedData createSignedContent(DigestAlgorithm digestAlgorithm) {
107
        return signedData.getSignedContent();
1✔
108
    }
109

110
    @Override
111
    public byte[] computeDigest(DigestAlgorithm digest) {
112
        throw new UnsupportedOperationException();
×
113
    }
114

115
    @Override
116
    public ASN1Object createIndirectData(DigestAlgorithm digestAlgorithm) {
117
        throw new UnsupportedOperationException();
×
118
    }
119

120
    @Override
121
    public List<CMSSignedData> getSignatures() throws IOException {
122
        if (signedData.getSignerInfos().size() > 0) {
1✔
123
            return SignatureUtils.getSignatures(signedData);
1✔
124
        } else {
125
            return Collections.emptyList();
1✔
126
        }
127
    }
128

129
    @Override
130
    public void setSignature(CMSSignedData signature) {
131
        if (signature != null) {
1✔
132
            signedData = signature;
1✔
133
        } else {
134
            // remove the signatures and the certificates
135
            try {
136
                signedData = CMSSignedData.replaceSigners(signedData, new SignerInformationStore(Collections.emptyList()));
1✔
137
                CollectionStore<?> emptyStore = new CollectionStore<>(Collections.emptyList());
1✔
138
                signedData = CMSSignedData.replaceCertificatesAndCRLs(signedData, emptyStore, emptyStore, emptyStore);
1✔
139
            } catch (CMSException e) {
×
140
                throw new RuntimeException(e);
×
141
            }
1✔
142
        }
143
    }
1✔
144

145
    @Override
146
    public void save() throws IOException {
147
        channel.position(0);
1✔
148
        channel.truncate(0);
1✔
149
        channel.write(ByteBuffer.wrap(signedData.getEncoded("DER")));
1✔
150
    }
1✔
151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc