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 }