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 }