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/DigestedDataOutputStreamDemo.java 15 12.02.25 17:58 Dbratko $ 029// $Revision: 15 $ 030// 031 032package demo.cms.digestedData; 033 034import iaik.asn1.ObjectID; 035import iaik.asn1.structures.AlgorithmID; 036import iaik.cms.CMSException; 037import iaik.cms.ContentInfoOutputStream; 038import iaik.cms.DigestedDataOutputStream; 039import iaik.cms.DigestedDataStream; 040import iaik.utils.Util; 041 042import java.io.ByteArrayInputStream; 043import java.io.ByteArrayOutputStream; 044import java.io.IOException; 045import java.io.InputStream; 046 047import demo.DemoUtil; 048 049/** 050 * Demonstrates the usage of class {@link iaik.cms.DigestedDataOutputStream} and 051 * {@link iaik.cms.DigestedData} for digesting data using the CMS type 052 * DigestedData. 053 */ 054public class DigestedDataOutputStreamDemo { 055 056 /** 057 * Default constructor. 058 */ 059 public DigestedDataOutputStreamDemo() throws IOException { 060 System.out.println(); 061 System.out.println("**********************************************************************************"); 062 System.out.println("* DigestedDataOutputStream demo *"); 063 System.out.println("* (shows the usage of the DigestedDataOutputStream implementation) *"); 064 System.out.println("**********************************************************************************"); 065 System.out.println(); 066 } 067 068 069 /** 070 * Uses the IAIK-CMS DigestedDataOutputStream class to create a CMS <code>DigestedData</code> 071 * object for digesting the given message. 072 * 073 * @param message the message to be digested, as byte representation 074 * @param mode IMPLICIT (include message) or EXPLICIT (do not include message) 075 * 076 * @return the BER encoding of the <code>DigestedData</code> object just created, 077 * wrapped in a ContentInfo 078 * 079 * @throws CMSException if the <code>DigestedData</code> object cannot 080 * be created 081 * @throws IOException if an I/O error occurs 082 */ 083 public byte[] createDigestedData(byte[] message, int mode) throws CMSException, IOException { 084 085 System.out.println("Create a new message to be digested:"); 086 087 // the stream from which to read the data to be digested 088 ByteArrayInputStream is = new ByteArrayInputStream(message); 089 090 // the stream to which to write the DigestedData 091 ByteArrayOutputStream resultStream = new ByteArrayOutputStream(); 092 093 // wrap DigestedData into a ContentInfo 094 ContentInfoOutputStream contentInfoStream = 095 new ContentInfoOutputStream(ObjectID.cms_digestedData, resultStream); 096 // create a new DigestedData object 097 DigestedDataOutputStream digestedData = 098 new DigestedDataOutputStream(contentInfoStream, 099 (AlgorithmID)AlgorithmID.sha256.clone(), 100 mode); 101 102 103 int blockSize = 8; // in real world we would use a block size like 2048 104 // write in the data to be digested 105 byte[] buffer = new byte[blockSize]; 106 int bytesRead; 107 while ((bytesRead = is.read(buffer)) != -1) { 108 digestedData.write(buffer, 0, bytesRead); 109 } 110 111 // closing the stream finishes digest calculation and closes the underlying stream 112 digestedData.close(); 113 return resultStream.toByteArray(); 114 } 115 116 /** 117 * Parses a CMS <code>DigestedData</code> object and verifies the hash. 118 * 119 * @param digestedData <code>DigestedData</code> object as BER encoded byte array 120 * @param message the message which may have been transmitted out-of-band 121 * 122 * @return the inherent message as byte array 123 * 124 * @throws CMSException if some parsing error occurs or the hash verification fails 125 * @throws IOException if an I/O error occurs 126 */ 127 public byte[] getDigestedData(byte[] digestedData, byte[] message) throws CMSException, IOException { 128 129 // we are testing the stream interface 130 ByteArrayInputStream is = new ByteArrayInputStream(digestedData); 131 // create the DigestedData object 132 DigestedDataStream digested_data = new DigestedDataStream(is); 133 134 if (message != null) { 135 // explicit mode: set content received by other means 136 digested_data.setInputStream(new ByteArrayInputStream(message)); 137 } 138 139 // get an InputStream for reading the content 140 InputStream data = digested_data.getInputStream(); 141 ByteArrayOutputStream os = new ByteArrayOutputStream(); 142 Util.copyStream(data, os, null); 143 144 145 if (digested_data.verify()) { 146 System.out.println("Hash ok!"); 147 } else { 148 throw new CMSException("Hash verification failed!"); 149 } 150 151 return os.toByteArray(); 152 } 153 154 155 156 /** 157 * Starts the tests. 158 */ 159 public void start() { 160 // the test message 161 String m = "This is the test message."; 162 System.out.println("Test message: \""+m+"\""); 163 System.out.println(); 164 byte[] message = m.getBytes(); 165 166 try { 167 byte[] encoding; 168 byte[] received_message = null; 169 170 // 171 // test CMS Implicit DigestedDataOutputStream 172 // 173 System.out.println("\nImplicit DigestedDataOutputStream demo [create]:\n"); 174 encoding = createDigestedData(message, DigestedDataOutputStream.IMPLICIT); 175 // transmit data 176 System.out.println("\nImplicit DigestedDataOutputStream demo [parse]:\n"); 177 received_message = getDigestedData(encoding, null); 178 System.out.print("\nContent: "); 179 System.out.println(new String(received_message)); 180 181 // 182 // test CMS Explicit DigestedDataOutputStream 183 // 184 System.out.println("\nExplicit DigestedDataOutputStream demo [create]:\n"); 185 encoding = createDigestedData(message, DigestedDataOutputStream.EXPLICIT); 186 // transmit data 187 System.out.println("\nExplicit DigestedDataOutputStream demo [parse]:\n"); 188 received_message = getDigestedData(encoding, message); 189 System.out.print("\nContent: "); 190 System.out.println(new String(received_message)); 191 192 193 } catch (Exception ex) { 194 ex.printStackTrace(); 195 throw new RuntimeException(ex.toString()); 196 } 197 } 198 199 /** 200 * Main method. 201 */ 202 public static void main(String argv[]) throws Exception { 203 204 DemoUtil.initDemos(); 205 206 (new DigestedDataOutputStreamDemo()).start(); 207 System.out.println("\nReady!"); 208 DemoUtil.waitKey(); 209 } 210}