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