001 // Copyright (C) 2002 IAIK
002 // https://jce.iaik.tugraz.at
003 //
004 // Copyright (C) 2003 - 2025 Stiftung Secure Information and
005 // Communication Technologies SIC
006 // https://sic.tech
007 //
008 // All rights reserved.
009 //
010 // Redistribution and use in source and binary forms, with or without
011 // modification, are permitted provided that the following conditions
012 // are met:
013 // 1. Redistributions of source code must retain the above copyright
014 // notice, this list of conditions and the following disclaimer.
015 // 2. Redistributions in binary form must reproduce the above copyright
016 // notice, this list of conditions and the following disclaimer in the
017 // documentation and/or other materials provided with the distribution.
018 //
019 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
020 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
023 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
024 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
025 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
027 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
028 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
029 // SUCH DAMAGE.
030
031 // Copyright (C) 2002 IAIK
032 // https://sic.tech/
033 //
034 // Copyright (C) 2003 - 2025 Stiftung Secure Information and
035 // Communication Technologies SIC
036 // https://sic.tech/
037 //
038 // All rights reserved.
039 //
040 // This source is provided for inspection purposes and recompilation only,
041 // unless specified differently in a contract with IAIK. This source has to
042 // be kept in strict confidence and must not be disclosed to any third party
043 // under any circumstances. Redistribution in source and binary forms, with
044 // or without modification, are <not> permitted in any case!
045 //
046 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
047 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
048 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
049 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
050 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
051 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
052 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
053 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
054 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
055 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
056 // SUCH DAMAGE.
057 //
058 // $Header: /IAIK-CMS/current/src/demo/cms/compressedData/CompressedDataDemo.java 13 12.02.25 17:58 Dbratko $
059 // $Revision: 13 $
060 //
061
062 package demo.cms.compressedData;
063
064 import iaik.asn1.structures.AlgorithmID;
065 import iaik.cms.CMSAlgorithmID;
066 import iaik.cms.CMSException;
067 import iaik.cms.CompressedData;
068 import iaik.cms.CompressedDataStream;
069 import iaik.cms.ContentInfo;
070 import iaik.cms.ContentInfoStream;
071 import iaik.cms.Utils;
072 import iaik.utils.CryptoUtils;
073 import iaik.utils.Util;
074
075 import java.io.ByteArrayInputStream;
076 import java.io.ByteArrayOutputStream;
077 import java.io.IOException;
078 import java.io.InputStream;
079 import java.security.NoSuchAlgorithmException;
080
081 import demo.DemoUtil;
082
083
084
085 /**
086 * Demonstrates the usage of class {@link iaik.cms.CompressedDataStream} and
087 * {@link iaik.cms.CompressedData} for compressing/decompressing data using
088 * the CMS type CompressedData.
089 */
090 public class CompressedDataDemo {
091
092 /**
093 * In explcit mode the compressed content data has to be transmitted by other means.
094 */
095 byte[] compressedContent_;
096
097 /**
098 * Default constructor.
099 */
100 public CompressedDataDemo() {
101 System.out.println();
102 System.out.println("**********************************************************************************");
103 System.out.println("* CompressedDataDemo *");
104 System.out.println("* (shows the usage of the CMS CompressedData type implementation) *");
105 System.out.println("**********************************************************************************");
106 System.out.println();
107 }
108
109
110 /**
111 * Creates a CMS <code>CompressedData</code> object.
112 * <p>
113 * @param message the message to be compressed, as byte representation
114 * @param mode IMPLICIT (include compressed content) or
115 * EXPLICIT (do not include compressed content)
116 *
117 * @return the BER encoding of the <code>CompressedData</code> object just created
118 *
119 * @throws CMSException if the <code>CompressedData</code> object cannot
120 * be created
121 * @throws IOException if an I/O error occurs
122 * @throws NoSuchAlgorithmException if the compression algorithm is not supported
123 */
124 public byte[] createCompressedDataStream(byte[] message, int mode)
125 throws CMSException, IOException, NoSuchAlgorithmException {
126
127 System.out.println("Create a new CompressedData message.");
128
129 // we are testing the stream interface
130 ByteArrayInputStream is = new ByteArrayInputStream(message);
131
132 // create a new CompressedData object
133 CompressedDataStream compressedData = new CompressedDataStream(is,
134 (AlgorithmID)CMSAlgorithmID.zlib_compress.clone(),
135 mode);
136
137
138 // in explicit mode transmit compressed content out-of-band
139 if (mode == CompressedDataStream.EXPLICIT) {
140 InputStream dataIs = compressedData.getInputStream();
141 ByteArrayOutputStream baos = new ByteArrayOutputStream();
142 Utils.copyStream(dataIs, baos, null);
143 compressedContent_ = baos.toByteArray();
144 }
145
146 // for testing return the CompressedData as BER encoded byte array with block size of 4
147 ByteArrayOutputStream os = new ByteArrayOutputStream();
148 compressedData.setBlockSize(4);
149 ContentInfoStream cis = new ContentInfoStream(compressedData);
150 cis.writeTo(os);
151 return os.toByteArray();
152 }
153
154 /**
155 * Parses a CMS <code>CompressedData</code> object.
156 *
157 * @param encoding the <code>CompressedData</code> object as BER encoded byte array
158 * @param compressedContent the compressed content which was transmitted out-of-band
159 *
160 * @return the decompressed message as byte array
161 *
162 * @throws CMSException if the CompressedData cannot be parsed
163 * @throws IOException if an I/O error occurs
164 * @throws NoSuchAlgorithmException if the compression algorithm is not supported
165 */
166 public byte[] getCompressedDataStream(byte[] encoding, byte[] compressedContent)
167 throws CMSException, IOException, NoSuchAlgorithmException {
168
169 System.out.println("Parse CompressedData message.");
170 // we are testing the stream interface
171 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
172 // create the CompressedData object
173 CompressedDataStream compressedData = new CompressedDataStream(is);
174
175 if (compressedData.getMode() == CompressedDataStream.EXPLICIT) {
176 // in explicit mode now provide the content received by other means
177 compressedData.setInputStream(new ByteArrayInputStream(compressedContent));
178 }
179
180 // get an InputStream for reading and decompressing the content
181 InputStream data = compressedData.getInputStream();
182 ByteArrayOutputStream os = new ByteArrayOutputStream();
183 Util.copyStream(data, os, null);
184
185 return os.toByteArray();
186 }
187
188
189 /**
190 * Creates a CMS <code>CompressedData</code> object.
191 * <p>
192 *
193 * @param message the message to be compressed, as byte representation
194 * @param mode IMPLICIT (include the compressed content) or
195 * EXPLICIT (do not include the compressed content)
196 *
197 * @return the DER encoded <code>CompressedData</code>
198 *
199 * @throws CMSException if the <code>CompressedData</code> object cannot
200 * be created
201 * @throws IOException if an I/O error occurs
202 * @throws NoSuchAlgorithmException if the compression algorithm is not supported
203 */
204 public byte[] createCompressedData(byte[] message, int mode)
205 throws CMSException, IOException, NoSuchAlgorithmException {
206
207 System.out.println("Create a new CompressedData message.");
208
209 // create a new CompressedData object
210 CompressedData compressedData = new CompressedData(message,
211 (AlgorithmID)CMSAlgorithmID.zlib_compress.clone(),
212 mode);
213 // in explicit mode get the compressed content to transmit it by other means
214 if (mode == CompressedData.EXPLICIT) {
215 compressedContent_ = compressedData.getContent();
216 }
217 ContentInfo ci = new ContentInfo(compressedData);
218 return ci.getEncoded();
219 }
220
221 /**
222 * Parses a CMS <code>CompressedData</code> object.
223 *
224 * @param encoding the DER encoded <code>CompressedData</code> object
225 * @param compressedContent the compressed content which was transmitted out-of-band
226 *
227 * @return the decompressed message as byte array
228 *
229 * @throws CMSException if the CompressedData cannot be parsed
230 * @throws IOException if an I/O error occurs
231 * @throws NoSuchAlgorithmException if the compression algorithm is not supported
232 */
233 public byte[] getCompressedData(byte[] encoding, byte[] compressedContent)
234 throws CMSException, IOException, NoSuchAlgorithmException {
235
236 System.out.println("Parse CompressedData message.");
237 ByteArrayInputStream encodedStream = new ByteArrayInputStream(encoding);
238 // create the CompressedData object
239 CompressedData compressedData = new CompressedData(encodedStream);
240
241 if (compressedData.getMode() == CompressedData.EXPLICIT) {
242 // in explicit mode provide the compressed content received by other means
243 compressedData.setContent(compressedContent);
244 }
245 // decompress
246 return compressedData.getContent();
247 }
248
249 /**
250 * Starts the demo.
251 */
252 public void start() {
253 // the test message
254 String m = "ABABABABABABABBABABABABABABABBABABABABABABABBAABABABABABA.";
255 System.out.println("Test message: \""+m+"\"");
256 System.out.println();
257 byte[] message = m.getBytes();
258
259 try {
260 byte[] encoding;
261 byte[] receivedMessage = null;
262 System.out.println("Stream implementation demos");
263 System.out.println("===========================");
264
265 // the stream implementation
266
267 //
268 // test CMS Implicit CompressedDataStream
269 //
270 System.out.println("\nImplicit CompressedDataStream demo [create]\n");
271 encoding = createCompressedDataStream(message, CompressedDataStream.IMPLICIT);
272 // transmit data
273 System.out.println("\nImplicit CompressedDataStream demo [parse]\n");
274 receivedMessage = getCompressedDataStream(encoding, null);
275 if (CryptoUtils.equalsBlock(message, receivedMessage) == false) {
276 throw new CMSException("Decompression error!");
277 }
278 System.out.print("\nContent: ");
279 System.out.println(new String(receivedMessage));
280
281 //
282 // test CMS Explicit CompressedDataStream
283 //
284 System.out.println("\nExplicit CompressedDataStream demo [create]\n");
285 encoding = createCompressedDataStream(message, CompressedDataStream.EXPLICIT);
286 // transmit data
287 System.out.println("\nExplicit CompressedDataStream demo [parse]\n");
288 receivedMessage = getCompressedDataStream(encoding, compressedContent_);
289 if (CryptoUtils.equalsBlock(message, receivedMessage) == false) {
290 throw new CMSException("Decompression error!");
291 }
292 System.out.print("\nContent: ");
293 System.out.println(new String(receivedMessage));
294
295 // the non-stream implementation
296 System.out.println("\nNon-stream implementation demos");
297 System.out.println("===============================");
298
299 //
300 // test CMS Implicit CompressedData
301 //
302 System.out.println("\nImplicit CompressedData demo [create]\n");
303 encoding = createCompressedData(message, CompressedData.IMPLICIT);
304 // transmit data
305 System.out.println("\nImplicit CompressedData demo [parse]\n");
306 receivedMessage = getCompressedData(encoding, null);
307 if (CryptoUtils.equalsBlock(message, receivedMessage) == false) {
308 throw new CMSException("Decompression error!");
309 }
310 System.out.print("\nContent: ");
311 System.out.println(new String(receivedMessage));
312
313 //
314 // test CMS Explicit CompressedData
315 //
316 System.out.println("\nExplicit CompressedData demo [create]\n");
317 encoding = createCompressedData(message, CompressedData.EXPLICIT);
318 // transmit data
319 System.out.println("\nExplicit CompressedData demo [parse]\n");
320 receivedMessage = getCompressedData(encoding, compressedContent_);
321 if (CryptoUtils.equalsBlock(message, receivedMessage) == false) {
322 throw new CMSException("Decompression error!");
323 }
324 System.out.print("\nContent: ");
325 System.out.println(new String(receivedMessage));
326
327 } catch (Exception ex) {
328 ex.printStackTrace();
329 throw new RuntimeException(ex.toString());
330 }
331 }
332
333 /**
334 * Main method.
335 */
336 public static void main(String argv[]) throws Exception {
337
338 DemoUtil.initDemos();
339
340 (new CompressedDataDemo()).start();
341 System.out.println("\nReady!");
342 DemoUtil.waitKey();
343 }
344 }