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 }