001// Copyright (C) 2002 IAIK 002// https://sic.tech/ 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// This source is provided for inspection purposes and recompilation only, 011// unless specified differently in a contract with IAIK. This source has to 012// be kept in strict confidence and must not be disclosed to any third party 013// under any circumstances. Redistribution in source and binary forms, with 014// or without modification, are <not> permitted in any case! 015// 016// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 017// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 020// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 021// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 022// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 023// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 024// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 025// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 026// SUCH DAMAGE. 027// 028// $Header: /IAIK-CMS/current/src/demo/cms/digestedData/DigestedDataDemo.java 19 12.02.25 17:58 Dbratko $ 029// $Revision: 19 $ 030// 031 032package demo.cms.digestedData; 033 034import iaik.asn1.structures.AlgorithmID; 035import iaik.cms.CMSException; 036import iaik.cms.DigestedData; 037import iaik.cms.DigestedDataStream; 038import iaik.security.random.SecRandom; 039import iaik.utils.Util; 040 041import java.io.ByteArrayInputStream; 042import java.io.ByteArrayOutputStream; 043import java.io.IOException; 044import java.io.InputStream; 045import java.security.NoSuchAlgorithmException; 046import java.security.SecureRandom; 047 048import demo.DemoUtil; 049 050/** 051 * Demonstrates the usage of class {@link iaik.cms.DigestedDataStream} and 052 * {@link iaik.cms.DigestedData} for digesting data using the CMS type 053 * DigestedData. 054 */ 055public class DigestedDataDemo { 056 057 // secure random number generator 058 SecureRandom random; 059 060 /** 061 * Default constructor. 062 */ 063 public DigestedDataDemo() throws IOException { 064 System.out.println(); 065 System.out.println("**********************************************************************************"); 066 System.out.println("* CMSDigestedData demo *"); 067 System.out.println("* (shows the usage of the CMS DigestedData type implementation) *"); 068 System.out.println("**********************************************************************************"); 069 System.out.println(); 070 071 random = SecRandom.getDefault(); 072 } 073 074 075 /** 076 * Creates a CMS <code>DigestedData</code> object. 077 * <p> 078 * @param message the message to be digested, as byte representation 079 * @param mode IMPLICIT (include message) or EXPLICIT (do not include message) 080 * @return the DER encoding of the <code>DigestedData</code> object just created 081 * @throws CMSException if the <code>DigestedData</code> object cannot 082 * be created 083 * @throws IOException if an I/O error occurs 084 */ 085 public byte[] createDigestedDataStream(byte[] message, int mode) throws CMSException, IOException { 086 087 System.out.println("Create a new message to be digested:"); 088 089 // we are testing the stream interface 090 ByteArrayInputStream is = new ByteArrayInputStream(message); 091 092 // create a new DigestedData object which includes the data 093 DigestedDataStream digested_data = null; 094 095 digested_data = new DigestedDataStream(is, (AlgorithmID)AlgorithmID.sha256.clone(), mode); 096 097 098 // write the data through DigestedData to any out-of-band place 099 if (mode == DigestedDataStream.EXPLICIT) { 100 InputStream data_is = digested_data.getInputStream(); 101 byte[] buf = new byte[1024]; 102 int r; 103 while ((r = data_is.read(buf)) > 0) { 104 ; // skip data 105 } 106 } 107 108 // return the DigestedData as DER encoded byte array with block size 2048 109 ByteArrayOutputStream os = new ByteArrayOutputStream(); 110 digested_data.writeTo(os, 2048); 111 return os.toByteArray(); 112 } 113 114 /** 115 * Parses a CMS <code>DigestedData</code> object and verifies the hash. 116 * 117 * @param digestedData <code>DigestedData</code> object as DER encoded byte array 118 * @param message the the message which was transmitted out-of-band 119 * 120 * @return the inherent message as byte array 121 * @throws CMSException if some parsing error occurs or the hash verification fails 122 * @throws IOException if an I/O error occurs 123 */ 124 public byte[] getDigestedDataStream(byte[] digestedData, byte[] message) throws CMSException, IOException { 125 126 // we are testing the stream interface 127 ByteArrayInputStream is = new ByteArrayInputStream(digestedData); 128 // create the DigestedData object 129 DigestedDataStream digested_data = null; 130 if (message == null) { 131 // implicitly; read the DER encoded object 132 digested_data = new DigestedDataStream(is); 133 } else { 134 // explicitly; set the data stream for digesting the message 135 digested_data = new DigestedDataStream(new ByteArrayInputStream(message), (AlgorithmID)AlgorithmID.sha256.clone()); 136 } 137 138 // get an InputStream for reading the content 139 InputStream data = digested_data.getInputStream(); 140 ByteArrayOutputStream os = new ByteArrayOutputStream(); 141 Util.copyStream(data, os, null); 142 143 if (message != null) { 144 // explicit mode: decode the DigestedData now 145 digested_data.decode(is); 146 } 147 148 if (digested_data.verify()) { 149 System.out.println("Hash ok!"); 150 } else { 151 throw new CMSException("Hash verification failed!"); 152 } 153 154 return os.toByteArray(); 155 } 156 157 158 /** 159 * Creates a CMS <code>DigestedData</code> object. 160 * <p> 161 * 162 * @param message the message to be digested, as byte representation 163 * @param mode IMPLICIT (include message) or EXPLICIT (do not include message) 164 * @return the DER encoded <code>DigestedData</code> 165 * @throws CMSException if the <code>DigestedData</code> object cannot 166 * be created 167 * @throws IOException if an I/O error occurs 168 */ 169 public byte[] createDigestedData(byte[] message, int mode) throws CMSException, IOException { 170 171 System.out.println("Create a new digested message:"); 172 173 // create a new DigestedData object which includes the data 174 DigestedData digested_data = new DigestedData(message, (AlgorithmID)AlgorithmID.sha256.clone(), mode); 175 176 return digested_data.getEncoded(); 177 } 178 179 /** 180 * Parses a CMS <code>DigestedData</code> object and verifies the hash value. 181 * 182 * @param encoding the DER encoded <code>DigestedData</code> object 183 * @param message the the message which was transmitted out-of-band (explicit digested) 184 * 185 * @return the message 186 * @throws CMSException if some parsing error occurs or the hash verification fails 187 * @throws IOException if an I/O error occurs 188 */ 189 public byte[] getDigestedData(byte[] encoding, byte[] message) throws CMSException, IOException { 190 191 ByteArrayInputStream encodedStream = new ByteArrayInputStream(encoding); 192 // create the DigestedData object 193 DigestedData digested_data = null; 194 if (message == null) { 195 // implicitly digested; read the ASN.1 object 196 digested_data = new DigestedData(encodedStream); 197 } 198 else { 199 // explicitly digested; set the data for digesting the message 200 try { 201 digested_data = new DigestedData(message, (AlgorithmID)AlgorithmID.sha256.clone()); 202 // if explicitly digested now the DER encoded object 203 digested_data.decode(encodedStream); 204 205 } catch (NoSuchAlgorithmException ex) { 206 throw new CMSException(ex.getMessage()); 207 } 208 } 209 210 // now verify the digest 211 if (digested_data.verify()) { 212 System.out.println("Hash ok!"); 213 } else { 214 throw new CMSException("Hash verification failed!"); 215 } 216 217 return digested_data.getContent(); 218 } 219 220 /** 221 * Starts the tests. 222 */ 223 public void start() { 224 // the test message 225 String m = "This is the test message."; 226 System.out.println("Test message: \""+m+"\""); 227 System.out.println(); 228 byte[] message = m.getBytes(); 229 230 try { 231 byte[] encoding; 232 byte[] received_message = null; 233 System.out.println("Stream implementation demos"); 234 System.out.println("==========================="); 235 236 // the stream implementation 237 238 // 239 // test CMS Implicit DigestedDataStream 240 // 241 System.out.println("\nImplicit DigestedDataStream demo [create]:\n"); 242 encoding = createDigestedDataStream(message, DigestedDataStream.IMPLICIT); 243 // transmit data 244 System.out.println("\nImplicit DigestedDataStream demo [parse]:\n"); 245 received_message = getDigestedDataStream(encoding, null); 246 System.out.print("\nContent: "); 247 System.out.println(new String(received_message)); 248 249 // 250 // test CMS Explicit DigestedDataStream 251 // 252 System.out.println("\nExplicit DigestedDataStream demo [create]:\n"); 253 encoding = createDigestedDataStream(message, DigestedDataStream.EXPLICIT); 254 // transmit data 255 System.out.println("\nExplicit DigestedDataStream demo [parse]:\n"); 256 received_message = getDigestedDataStream(encoding, message); 257 System.out.print("\nContent: "); 258 System.out.println(new String(received_message)); 259 260 // the non-stream implementation 261 System.out.println("\nNon-stream implementation demos"); 262 System.out.println("==============================="); 263 264 // 265 // test CMS Implicit DigestedData 266 // 267 System.out.println("\nImplicit DigestedData demo [create]:\n"); 268 encoding = createDigestedData(message, DigestedData.IMPLICIT); 269 // transmit data 270 System.out.println("\nImplicit DigestedData demo [parse]:\n"); 271 received_message = getDigestedData(encoding, null); 272 System.out.print("\nContent: "); 273 System.out.println(new String(received_message)); 274 275 // 276 // test CMS Explicit DigestedData 277 // 278 System.out.println("\nExplicit DigestedData demo [create]:\n"); 279 encoding = createDigestedData(message, DigestedData.EXPLICIT); 280 // transmit data 281 System.out.println("\nExplicit DigestedData demo [parse]:\n"); 282 received_message = getDigestedData(encoding, message); 283 System.out.print("\nContent: "); 284 System.out.println(new String(received_message)); 285 286 } catch (Exception ex) { 287 ex.printStackTrace(); 288 throw new RuntimeException(ex.toString()); 289 } 290 } 291 292 /** 293 * Main method. 294 */ 295 public static void main(String argv[]) throws Exception { 296 297 DemoUtil.initDemos(); 298 299 (new DigestedDataDemo()).start(); 300 System.out.println("\nReady!"); 301 DemoUtil.waitKey(); 302 } 303}