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/CompressedDataOutputStreamDemo.java 10    12.02.25 17:58 Dbratko $
029// $Revision: 10 $
030//
031
032package demo.cms.compressedData;
033
034import iaik.asn1.structures.AlgorithmID;
035import iaik.cms.CMSAlgorithmID;
036import iaik.cms.CMSException;
037import iaik.cms.CompressedDataOutputStream;
038import iaik.cms.CompressedDataStream;
039import iaik.cms.ContentInfoOutputStream;
040import iaik.utils.CryptoUtils;
041import iaik.utils.Util;
042
043import java.io.ByteArrayInputStream;
044import java.io.ByteArrayOutputStream;
045import java.io.IOException;
046import java.io.InputStream;
047import java.security.NoSuchAlgorithmException;
048
049import demo.DemoUtil;
050
051/**
052 * Demonstrates the usage of class {@link iaik.cms.CompressedDataOutputStream} and
053 * {@link iaik.cms.CompressedDataOutputStream} for compressing data using
054 * the CMS type CompressedData.
055 * 
056 * @see iaik.cms.CompressedDataOutputStream
057 * @see iaik.cms.CompressedDataStream
058 */
059public class CompressedDataOutputStreamDemo {
060  
061  /**
062   * Default constructor.
063   */
064  public CompressedDataOutputStreamDemo() {
065    System.out.println();
066    System.out.println("**********************************************************************************");
067    System.out.println("*                        CompressedDataOutputStream demo                         *");
068    System.out.println("*  (shows the usage of the CMS CompressedDataOutputStream type implementation)   *");
069    System.out.println("**********************************************************************************");
070    System.out.println();
071  }
072
073
074  /**
075   * Uses the IAIK-CMS CompressedDataOutputStream class to create a CMS 
076   * <code>CompressedData</code> object for compressing the given message.
077   * <p>
078   * @param message the message to be compressed, as byte representation
079   *
080   * @return the BER encoding of the <code>CompressedData</code> object just created
081   *
082   * @throws CMSException if the <code>CompressedData</code> object cannot
083   *                          be created
084   * @throws IOException if an I/O error occurs
085   */
086  public byte[] createCompressedData(byte[] message) throws CMSException, IOException {
087
088    System.out.println("Create a new CompressedData message.");
089
090    // the stream from which to read the data to be compressed
091    ByteArrayInputStream is = new ByteArrayInputStream(message);
092    
093    // the stream to which to write the CompressedData
094    ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
095    
096    // wrap CompressedData into a ContentInfo 
097    ContentInfoOutputStream contentInfoStream = 
098      new ContentInfoOutputStream(CompressedDataStream.contentType, resultStream);
099    // create a new CompressedDataOutputStream  
100    CompressedDataOutputStream compressedData = 
101      new CompressedDataOutputStream(contentInfoStream,
102                                     (AlgorithmID)CMSAlgorithmID.zlib_compress.clone());
103
104    int blockSize = 8; // in real world we would use a block size like 2048
105    //  write in the data to be compressed
106    byte[] buffer = new byte[blockSize];
107    int bytesRead;
108    while ((bytesRead = is.read(buffer)) != -1) {
109      compressedData.write(buffer, 0, bytesRead);
110    }
111    
112    // closing the stream finishes encoding and closes the underlying stream
113    compressedData.close();
114    return resultStream.toByteArray();
115  }
116
117  /**
118   * Parses a CMS <code>CompressedData</code> object.
119   *
120   * @param encoding  the <code>CompressedData</code> object as BER encoded byte array
121   *
122   * @return the decompressed message as byte array
123   *
124   * @throws CMSException if the CompressedData cannot be parsed
125   * @throws IOException if an I/O error occurs
126   * @throws NoSuchAlgorithmException if the compression algorithm is not supported
127   */
128  public byte[] getCompressedData(byte[] encoding) 
129    throws CMSException, IOException, NoSuchAlgorithmException {
130
131    System.out.println("Parse CompressedData message.");
132    // we are testing the stream interface
133    ByteArrayInputStream is = new ByteArrayInputStream(encoding);
134    // create the CompressedData object
135    CompressedDataStream compressedData = new CompressedDataStream(is);
136 
137    // get an InputStream for reading and decompressing the content
138    InputStream data = compressedData.getInputStream();
139    ByteArrayOutputStream os = new ByteArrayOutputStream();
140    Util.copyStream(data, os, null);
141  
142    return os.toByteArray();
143  }
144
145  
146  /**
147   * Starts the demo.
148   */
149  public void start() {
150     // the test message
151    String m = "ABABABABABABABBABABABABABABABBABABABABABABABBAABABABABABA.";
152    System.out.println("Test message: \""+m+"\"");
153    System.out.println();
154    byte[] message = m.getBytes();
155
156    try {
157      byte[] encoding;
158      byte[] receivedMessage = null;
159   
160      System.out.println("\nCreating compressed message\n");
161      encoding = createCompressedData(message);
162      // transmit data
163      System.out.println("\nParsing compressed data\n");
164      receivedMessage = getCompressedData(encoding);
165      if (CryptoUtils.equalsBlock(message, receivedMessage) == false) {
166        throw new CMSException("Decompression error!");
167      }  
168
169      System.out.print("\nContent: ");
170      System.out.println(new String(receivedMessage));
171      
172        } catch (Exception ex) {
173          ex.printStackTrace();
174          throw new RuntimeException(ex.toString());
175        }
176  }
177
178  /**
179   * Main method.
180   */
181  public static void main(String argv[]) throws Exception {
182
183        DemoUtil.initDemos();
184
185    (new CompressedDataOutputStreamDemo()).start();
186    System.out.println("\nReady!");
187    DemoUtil.waitKey();
188  }
189}