001 /* Copyright (c) 2002 Graz University of Technology. All rights reserved.
002 *
003 * Redistribution and use in source and binary forms, with or without
004 * modification, are permitted provided that the following conditions are met:
005 *
006 * 1. Redistributions of source code must retain the above copyright notice,
007 * this list of conditions and the following disclaimer.
008 *
009 * 2. Redistributions in binary form must reproduce the above copyright notice,
010 * this list of conditions and the following disclaimer in the documentation
011 * and/or other materials provided with the distribution.
012 *
013 * 3. The end-user documentation included with the redistribution, if any, must
014 * include the following acknowledgment:
015 *
016 * "This product includes software developed by IAIK of Graz University of
017 * Technology."
018 *
019 * Alternately, this acknowledgment may appear in the software itself, if
020 * and wherever such third-party acknowledgments normally appear.
021 *
022 * 4. The names "Graz University of Technology" and "IAIK of Graz University of
023 * Technology" must not be used to endorse or promote products derived from
024 * this software without prior written permission.
025 *
026 * 5. Products derived from this software may not be called
027 * "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
028 * written permission of Graz University of Technology.
029 *
030 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
031 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
032 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
033 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
034 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
035 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
036 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
037 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
038 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
039 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
040 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
041 * POSSIBILITY OF SUCH DAMAGE.
042 */
043
044 package demo.pkcs.pkcs11;
045
046 import java.io.FileInputStream;
047 import java.io.InputStream;
048 import java.math.BigInteger;
049 import java.security.MessageDigest;
050 import java.util.Arrays;
051
052 import iaik.pkcs.pkcs11.Mechanism;
053 import iaik.pkcs.pkcs11.Module;
054 import iaik.pkcs.pkcs11.Session;
055 import iaik.pkcs.pkcs11.Slot;
056 import iaik.pkcs.pkcs11.Token;
057
058
059
060 /**
061 * This demo program connects to two different modules and calculates hash
062 * values with both of them. This program uses SHA-1. It demonstrates that it is
063 * possible to work with two independent module at the same time. By now, I did
064 * not conduct any real multi-threaded tests.
065 *
066 * @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a>
067 * @version 0.1
068 * @invariants
069 */
070 public class ConcurrentHash {
071
072 public static void main(String[] args) {
073 if (args.length == 3){
074 try {
075 System.out.println("################################################################################");
076 System.out.println("load and initialize module: " + args[0]);
077 Module pkcs11Module1 = Module.getInstance(args[0]);
078 pkcs11Module1.initialize(null);
079 System.out.println("load and initialize module: " + args[1]);
080 Module pkcs11Module2 = Module.getInstance(args[1]);
081 pkcs11Module2.initialize(null);
082 System.out.println("################################################################################");
083
084
085 System.out.println("################################################################################");
086 System.out.println("getting tokens");
087
088 Slot[] slotsWithToken1 = pkcs11Module1.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
089 if (slotsWithToken1.length < 1) {
090 System.err.println("No token present for module: " + pkcs11Module1.getInfo());
091 System.exit(1);
092 }
093 Token token1 = slotsWithToken1[0].getToken();
094 System.out.println("________________________________________________________________________________");
095 System.out.println("token #1:");
096 System.out.println(token1.getTokenInfo());
097 System.out.println("________________________________________________________________________________");
098
099 Slot[] slotsWithToken2 = pkcs11Module2.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
100 if (slotsWithToken2.length < 1) {
101 System.err.println("No token present for module: " + pkcs11Module2.getInfo());
102 System.exit(1);
103 }
104 Token token2 = slotsWithToken2[0].getToken();
105 System.out.println("________________________________________________________________________________");
106 System.out.println("token #2:");
107 System.out.println(token2.getTokenInfo());
108 System.out.println("________________________________________________________________________________");
109 System.out.println("################################################################################");
110
111
112 System.out.println("################################################################################");
113 System.out.println("opening sessions");
114 Session session1 = token1.
115 openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RO_SESSION, null, null);
116 Session session2 = token2.
117 openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RO_SESSION, null, null);
118
119 System.out.println("opening data file: " + args[2]);
120 InputStream dataInputStream = new FileInputStream(args[2]);
121
122 //be sure that your token can process the specified mechanism
123 Mechanism digestMechanism = Mechanism.SHA_1;
124 // initialize for digesting
125 System.out.println("initializing sessions for hashing");
126 session1.digestInit(digestMechanism);
127 session2.digestInit(digestMechanism);
128
129 byte[] dataBuffer = new byte[1024];
130 byte[] helpBuffer;
131 int bytesRead;
132
133 // feed in all data from the input stream
134 while ((bytesRead = dataInputStream.read(dataBuffer)) >= 0) {
135 helpBuffer = new byte[bytesRead]; // we need a buffer that only holds what to send for digesting
136 System.arraycopy(dataBuffer, 0, helpBuffer, 0, bytesRead);
137 session1.digestUpdate(helpBuffer);
138 session2.digestUpdate(helpBuffer);
139 Arrays.fill(helpBuffer, (byte) 0); // ensure that no data is left in the memory
140 }
141 Arrays.fill(dataBuffer, (byte) 0); // ensure that no data is left in the memory
142
143 byte[] digestValue1 = session1.digestFinal();
144 byte[] digestValue2 = session2.digestFinal();
145
146 System.out.println("The SHA-1 hash value #1 is: " + new BigInteger(1, digestValue1).toString(16));
147 System.out.println("The SHA-1 hash value #2 is: " + new BigInteger(1, digestValue2).toString(16));
148
149 if (Arrays.equals(digestValue1, digestValue2)) {
150 System.out.println("The hash values are equal.");
151 } else {
152 System.out.println("The hash values are different. Test failed");
153 }
154
155 System.out.println("closing sessions");
156 session1.closeSession();
157 session2.closeSession();
158 System.out.println("################################################################################");
159
160
161 System.out.println("################################################################################");
162 System.out.println("verifying hash with software digest");
163
164 MessageDigest softwareDigestEngine = MessageDigest.getInstance("SHA-1");
165
166 dataInputStream = new FileInputStream(args[2]);
167
168 // feed in all data from the input stream
169 while ((bytesRead = dataInputStream.read(dataBuffer)) >= 0) {
170 softwareDigestEngine.update(dataBuffer, 0, bytesRead);
171 }
172 dataInputStream.close();
173 byte[] softwareDigestValue = softwareDigestEngine.digest();
174
175 Arrays.fill(dataBuffer, (byte) 0); // ensure that no data is left in the memory
176
177 System.out.println("The software digest value is: " + new BigInteger(1, softwareDigestValue).toString(16));
178
179 if (Arrays.equals(digestValue1, softwareDigestValue) && Arrays.equals(digestValue2, softwareDigestValue)) {
180 System.out.println("All SHA-1 hash values are equal. Test passed successfully.");
181 } else {
182 System.out.println("Verification of hash value FAILED!");
183 }
184
185 System.out.println("################################################################################");
186
187 } catch (Throwable ex) {
188 ex.printStackTrace();
189 }
190 } else {
191 printUsage();
192 }
193 System.gc(); // to finalize and disconnect the modules
194 }
195
196 protected static void printUsage() {
197 System.out.println("ConcurrentHash <PKCS#11 module name #1> <PKCS#11 module name #2> <data>");
198 System.out.println("e.g.: ConcurrentHash pk2priv.dll softtoken.dll data.dat");
199 System.out.println("Both modules must support hashing without the user being logged in.");
200 }
201
202 }