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