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/digestedData/DigestedDataOutputStreamDemo.java 15    12.02.25 17:58 Dbratko $
059    // $Revision: 15 $
060    //
061    
062    package demo.cms.digestedData;
063    
064    import iaik.asn1.ObjectID;
065    import iaik.asn1.structures.AlgorithmID;
066    import iaik.cms.CMSException;
067    import iaik.cms.ContentInfoOutputStream;
068    import iaik.cms.DigestedDataOutputStream;
069    import iaik.cms.DigestedDataStream;
070    import iaik.utils.Util;
071    
072    import java.io.ByteArrayInputStream;
073    import java.io.ByteArrayOutputStream;
074    import java.io.IOException;
075    import java.io.InputStream;
076    
077    import demo.DemoUtil;
078    
079    /**
080     * Demonstrates the usage of class {@link iaik.cms.DigestedDataOutputStream} and
081     * {@link iaik.cms.DigestedData} for digesting data using the CMS type
082     * DigestedData.
083     */
084    public class DigestedDataOutputStreamDemo {
085    
086      /**
087       * Default constructor.
088       */
089      public DigestedDataOutputStreamDemo() throws IOException {
090        System.out.println();
091        System.out.println("**********************************************************************************");
092        System.out.println("*                  DigestedDataOutputStream demo                                 *");
093        System.out.println("*        (shows the usage of the DigestedDataOutputStream implementation)        *");
094        System.out.println("**********************************************************************************");
095        System.out.println();
096      }
097    
098    
099      /**
100       * Uses the IAIK-CMS DigestedDataOutputStream class to create a CMS <code>DigestedData</code> 
101       * object for digesting the given message.
102       * 
103       * @param message the message to be digested, as byte representation
104       * @param mode IMPLICIT (include message) or EXPLICIT (do not include message)
105       * 
106       * @return the BER encoding of the <code>DigestedData</code> object just created,
107       *         wrapped in a ContentInfo
108       * 
109       * @throws CMSException if the <code>DigestedData</code> object cannot
110       *                          be created
111       * @throws IOException if an I/O error occurs
112       */
113      public byte[] createDigestedData(byte[] message, int mode) throws CMSException, IOException  {
114    
115        System.out.println("Create a new message to be digested:");
116    
117        // the stream from which to read the data to be digested
118        ByteArrayInputStream is = new ByteArrayInputStream(message);
119    
120        // the stream to which to write the DigestedData
121        ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
122        
123        // wrap DigestedData into a ContentInfo 
124        ContentInfoOutputStream contentInfoStream = 
125          new ContentInfoOutputStream(ObjectID.cms_digestedData, resultStream);
126        // create a new DigestedData object 
127        DigestedDataOutputStream digestedData = 
128          new DigestedDataOutputStream(contentInfoStream,
129                                       (AlgorithmID)AlgorithmID.sha256.clone(),
130                                       mode);
131    
132    
133        int blockSize = 8; // in real world we would use a block size like 2048
134        //  write in the data to be digested
135        byte[] buffer = new byte[blockSize];
136        int bytesRead;
137        while ((bytesRead = is.read(buffer)) != -1) {
138          digestedData.write(buffer, 0, bytesRead);
139        }
140        
141        // closing the stream finishes digest calculation and closes the underlying stream
142        digestedData.close();
143        return resultStream.toByteArray();
144      }
145    
146      /**
147       * Parses a CMS <code>DigestedData</code> object and verifies the hash.
148       *
149       * @param digestedData <code>DigestedData</code> object as BER encoded byte array
150       * @param message the message which may have been transmitted out-of-band
151       *
152       * @return the inherent message as byte array
153       * 
154       * @throws CMSException if some parsing error occurs or the hash verification fails
155       * @throws IOException if an I/O error occurs
156       */
157      public byte[] getDigestedData(byte[] digestedData, byte[] message) throws CMSException, IOException {
158    
159        // we are testing the stream interface
160        ByteArrayInputStream is = new ByteArrayInputStream(digestedData);
161        // create the DigestedData object
162        DigestedDataStream digested_data = new DigestedDataStream(is);
163        
164        if (message != null) {
165          // explicit mode: set content received by other means
166          digested_data.setInputStream(new ByteArrayInputStream(message));
167        }
168    
169        // get an InputStream for reading the content
170        InputStream data = digested_data.getInputStream();
171        ByteArrayOutputStream os = new ByteArrayOutputStream();
172        Util.copyStream(data, os, null);
173    
174    
175        if (digested_data.verify()) {
176           System.out.println("Hash ok!");
177        } else {
178           throw new CMSException("Hash verification failed!");
179        }
180    
181        return os.toByteArray();
182      }
183    
184    
185      
186      /**
187       * Starts the tests.
188       */
189      public void start() {
190         // the test message
191        String m = "This is the test message.";
192        System.out.println("Test message: \""+m+"\"");
193        System.out.println();
194        byte[] message = m.getBytes();
195    
196        try {
197          byte[] encoding;
198          byte[] received_message = null;
199          
200          //
201          // test CMS Implicit DigestedDataOutputStream
202          //
203          System.out.println("\nImplicit DigestedDataOutputStream demo [create]:\n");
204          encoding = createDigestedData(message, DigestedDataOutputStream.IMPLICIT);
205          // transmit data
206          System.out.println("\nImplicit DigestedDataOutputStream demo [parse]:\n");
207          received_message = getDigestedData(encoding, null);
208          System.out.print("\nContent: ");
209          System.out.println(new String(received_message));
210    
211          //
212          // test CMS Explicit DigestedDataOutputStream
213          //
214          System.out.println("\nExplicit DigestedDataOutputStream demo [create]:\n");
215          encoding = createDigestedData(message, DigestedDataOutputStream.EXPLICIT);
216          // transmit data
217          System.out.println("\nExplicit DigestedDataOutputStream demo [parse]:\n");
218          received_message = getDigestedData(encoding, message);
219          System.out.print("\nContent: ");
220          System.out.println(new String(received_message));
221          
222          
223            } catch (Exception ex) {
224              ex.printStackTrace();
225              throw new RuntimeException(ex.toString());
226            }
227      }
228    
229      /**
230       * Main method.
231       */
232      public static void main(String argv[]) throws Exception {
233    
234            DemoUtil.initDemos();
235    
236        (new DigestedDataOutputStreamDemo()).start();
237        System.out.println("\nReady!");
238        DemoUtil.waitKey();
239      }
240    }