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/DigestedDataDemo.java 19 12.02.25 17:58 Dbratko $
059 // $Revision: 19 $
060 //
061
062 package demo.cms.digestedData;
063
064 import iaik.asn1.structures.AlgorithmID;
065 import iaik.cms.CMSException;
066 import iaik.cms.DigestedData;
067 import iaik.cms.DigestedDataStream;
068 import iaik.security.random.SecRandom;
069 import iaik.utils.Util;
070
071 import java.io.ByteArrayInputStream;
072 import java.io.ByteArrayOutputStream;
073 import java.io.IOException;
074 import java.io.InputStream;
075 import java.security.NoSuchAlgorithmException;
076 import java.security.SecureRandom;
077
078 import demo.DemoUtil;
079
080 /**
081 * Demonstrates the usage of class {@link iaik.cms.DigestedDataStream} and
082 * {@link iaik.cms.DigestedData} for digesting data using the CMS type
083 * DigestedData.
084 */
085 public class DigestedDataDemo {
086
087 // secure random number generator
088 SecureRandom random;
089
090 /**
091 * Default constructor.
092 */
093 public DigestedDataDemo() throws IOException {
094 System.out.println();
095 System.out.println("**********************************************************************************");
096 System.out.println("* CMSDigestedData demo *");
097 System.out.println("* (shows the usage of the CMS DigestedData type implementation) *");
098 System.out.println("**********************************************************************************");
099 System.out.println();
100
101 random = SecRandom.getDefault();
102 }
103
104
105 /**
106 * Creates a CMS <code>DigestedData</code> object.
107 * <p>
108 * @param message the message to be digested, as byte representation
109 * @param mode IMPLICIT (include message) or EXPLICIT (do not include message)
110 * @return the DER encoding of the <code>DigestedData</code> object just created
111 * @throws CMSException if the <code>DigestedData</code> object cannot
112 * be created
113 * @throws IOException if an I/O error occurs
114 */
115 public byte[] createDigestedDataStream(byte[] message, int mode) throws CMSException, IOException {
116
117 System.out.println("Create a new message to be digested:");
118
119 // we are testing the stream interface
120 ByteArrayInputStream is = new ByteArrayInputStream(message);
121
122 // create a new DigestedData object which includes the data
123 DigestedDataStream digested_data = null;
124
125 digested_data = new DigestedDataStream(is, (AlgorithmID)AlgorithmID.sha256.clone(), mode);
126
127
128 // write the data through DigestedData to any out-of-band place
129 if (mode == DigestedDataStream.EXPLICIT) {
130 InputStream data_is = digested_data.getInputStream();
131 byte[] buf = new byte[1024];
132 int r;
133 while ((r = data_is.read(buf)) > 0) {
134 ; // skip data
135 }
136 }
137
138 // return the DigestedData as DER encoded byte array with block size 2048
139 ByteArrayOutputStream os = new ByteArrayOutputStream();
140 digested_data.writeTo(os, 2048);
141 return os.toByteArray();
142 }
143
144 /**
145 * Parses a CMS <code>DigestedData</code> object and verifies the hash.
146 *
147 * @param digestedData <code>DigestedData</code> object as DER encoded byte array
148 * @param message the the message which was transmitted out-of-band
149 *
150 * @return the inherent message as byte array
151 * @throws CMSException if some parsing error occurs or the hash verification fails
152 * @throws IOException if an I/O error occurs
153 */
154 public byte[] getDigestedDataStream(byte[] digestedData, byte[] message) throws CMSException, IOException {
155
156 // we are testing the stream interface
157 ByteArrayInputStream is = new ByteArrayInputStream(digestedData);
158 // create the DigestedData object
159 DigestedDataStream digested_data = null;
160 if (message == null) {
161 // implicitly; read the DER encoded object
162 digested_data = new DigestedDataStream(is);
163 } else {
164 // explicitly; set the data stream for digesting the message
165 digested_data = new DigestedDataStream(new ByteArrayInputStream(message), (AlgorithmID)AlgorithmID.sha256.clone());
166 }
167
168 // get an InputStream for reading the content
169 InputStream data = digested_data.getInputStream();
170 ByteArrayOutputStream os = new ByteArrayOutputStream();
171 Util.copyStream(data, os, null);
172
173 if (message != null) {
174 // explicit mode: decode the DigestedData now
175 digested_data.decode(is);
176 }
177
178 if (digested_data.verify()) {
179 System.out.println("Hash ok!");
180 } else {
181 throw new CMSException("Hash verification failed!");
182 }
183
184 return os.toByteArray();
185 }
186
187
188 /**
189 * Creates a CMS <code>DigestedData</code> object.
190 * <p>
191 *
192 * @param message the message to be digested, as byte representation
193 * @param mode IMPLICIT (include message) or EXPLICIT (do not include message)
194 * @return the DER encoded <code>DigestedData</code>
195 * @throws CMSException if the <code>DigestedData</code> object cannot
196 * be created
197 * @throws IOException if an I/O error occurs
198 */
199 public byte[] createDigestedData(byte[] message, int mode) throws CMSException, IOException {
200
201 System.out.println("Create a new digested message:");
202
203 // create a new DigestedData object which includes the data
204 DigestedData digested_data = new DigestedData(message, (AlgorithmID)AlgorithmID.sha256.clone(), mode);
205
206 return digested_data.getEncoded();
207 }
208
209 /**
210 * Parses a CMS <code>DigestedData</code> object and verifies the hash value.
211 *
212 * @param encoding the DER encoded <code>DigestedData</code> object
213 * @param message the the message which was transmitted out-of-band (explicit digested)
214 *
215 * @return the message
216 * @throws CMSException if some parsing error occurs or the hash verification fails
217 * @throws IOException if an I/O error occurs
218 */
219 public byte[] getDigestedData(byte[] encoding, byte[] message) throws CMSException, IOException {
220
221 ByteArrayInputStream encodedStream = new ByteArrayInputStream(encoding);
222 // create the DigestedData object
223 DigestedData digested_data = null;
224 if (message == null) {
225 // implicitly digested; read the ASN.1 object
226 digested_data = new DigestedData(encodedStream);
227 }
228 else {
229 // explicitly digested; set the data for digesting the message
230 try {
231 digested_data = new DigestedData(message, (AlgorithmID)AlgorithmID.sha256.clone());
232 // if explicitly digested now the DER encoded object
233 digested_data.decode(encodedStream);
234
235 } catch (NoSuchAlgorithmException ex) {
236 throw new CMSException(ex.getMessage());
237 }
238 }
239
240 // now verify the digest
241 if (digested_data.verify()) {
242 System.out.println("Hash ok!");
243 } else {
244 throw new CMSException("Hash verification failed!");
245 }
246
247 return digested_data.getContent();
248 }
249
250 /**
251 * Starts the tests.
252 */
253 public void start() {
254 // the test message
255 String m = "This is the test message.";
256 System.out.println("Test message: \""+m+"\"");
257 System.out.println();
258 byte[] message = m.getBytes();
259
260 try {
261 byte[] encoding;
262 byte[] received_message = null;
263 System.out.println("Stream implementation demos");
264 System.out.println("===========================");
265
266 // the stream implementation
267
268 //
269 // test CMS Implicit DigestedDataStream
270 //
271 System.out.println("\nImplicit DigestedDataStream demo [create]:\n");
272 encoding = createDigestedDataStream(message, DigestedDataStream.IMPLICIT);
273 // transmit data
274 System.out.println("\nImplicit DigestedDataStream demo [parse]:\n");
275 received_message = getDigestedDataStream(encoding, null);
276 System.out.print("\nContent: ");
277 System.out.println(new String(received_message));
278
279 //
280 // test CMS Explicit DigestedDataStream
281 //
282 System.out.println("\nExplicit DigestedDataStream demo [create]:\n");
283 encoding = createDigestedDataStream(message, DigestedDataStream.EXPLICIT);
284 // transmit data
285 System.out.println("\nExplicit DigestedDataStream demo [parse]:\n");
286 received_message = getDigestedDataStream(encoding, message);
287 System.out.print("\nContent: ");
288 System.out.println(new String(received_message));
289
290 // the non-stream implementation
291 System.out.println("\nNon-stream implementation demos");
292 System.out.println("===============================");
293
294 //
295 // test CMS Implicit DigestedData
296 //
297 System.out.println("\nImplicit DigestedData demo [create]:\n");
298 encoding = createDigestedData(message, DigestedData.IMPLICIT);
299 // transmit data
300 System.out.println("\nImplicit DigestedData demo [parse]:\n");
301 received_message = getDigestedData(encoding, null);
302 System.out.print("\nContent: ");
303 System.out.println(new String(received_message));
304
305 //
306 // test CMS Explicit DigestedData
307 //
308 System.out.println("\nExplicit DigestedData demo [create]:\n");
309 encoding = createDigestedData(message, DigestedData.EXPLICIT);
310 // transmit data
311 System.out.println("\nExplicit DigestedData demo [parse]:\n");
312 received_message = getDigestedData(encoding, message);
313 System.out.print("\nContent: ");
314 System.out.println(new String(received_message));
315
316 } catch (Exception ex) {
317 ex.printStackTrace();
318 throw new RuntimeException(ex.toString());
319 }
320 }
321
322 /**
323 * Main method.
324 */
325 public static void main(String argv[]) throws Exception {
326
327 DemoUtil.initDemos();
328
329 (new DigestedDataDemo()).start();
330 System.out.println("\nReady!");
331 DemoUtil.waitKey();
332 }
333 }