1 /* |
1 /* |
2 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
50 * are created. |
50 * are created. |
51 */ |
51 */ |
52 |
52 |
53 public class DHKeyAgreement2 { |
53 public class DHKeyAgreement2 { |
54 |
54 |
|
55 private static final String SUNJCE = "SunJCE"; |
55 private DHKeyAgreement2() {} |
56 private DHKeyAgreement2() {} |
56 |
57 |
57 public static void main(String argv[]) throws Exception { |
58 public static void main(String argv[]) throws Exception { |
58 String mode = "USE_SKIP_DH_PARAMS"; |
59 String mode = "USE_SKIP_DH_PARAMS"; |
59 |
|
60 // Add JCE to the list of providers |
|
61 SunJCE jce = new SunJCE(); |
|
62 Security.addProvider(jce); |
|
63 |
60 |
64 DHKeyAgreement2 keyAgree = new DHKeyAgreement2(); |
61 DHKeyAgreement2 keyAgree = new DHKeyAgreement2(); |
65 |
62 |
66 if (argv.length > 1) { |
63 if (argv.length > 1) { |
67 keyAgree.usage(); |
64 keyAgree.usage(); |
84 |
81 |
85 if (mode.equals("GENERATE_DH_PARAMS")) { |
82 if (mode.equals("GENERATE_DH_PARAMS")) { |
86 // Some central authority creates new DH parameters |
83 // Some central authority creates new DH parameters |
87 System.err.println("Creating Diffie-Hellman parameters ..."); |
84 System.err.println("Creating Diffie-Hellman parameters ..."); |
88 AlgorithmParameterGenerator paramGen |
85 AlgorithmParameterGenerator paramGen |
89 = AlgorithmParameterGenerator.getInstance("DH"); |
86 = AlgorithmParameterGenerator.getInstance("DH", SUNJCE); |
90 paramGen.init(512); |
87 paramGen.init(512); |
91 AlgorithmParameters params = paramGen.generateParameters(); |
88 AlgorithmParameters params = paramGen.generateParameters(); |
92 dhSkipParamSpec = (DHParameterSpec)params.getParameterSpec |
89 dhSkipParamSpec = (DHParameterSpec)params.getParameterSpec |
93 (DHParameterSpec.class); |
90 (DHParameterSpec.class); |
94 } else { |
91 } else { |
101 /* |
98 /* |
102 * Alice creates her own DH key pair, using the DH parameters from |
99 * Alice creates her own DH key pair, using the DH parameters from |
103 * above |
100 * above |
104 */ |
101 */ |
105 System.err.println("ALICE: Generate DH keypair ..."); |
102 System.err.println("ALICE: Generate DH keypair ..."); |
106 KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH"); |
103 KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH", SUNJCE); |
107 aliceKpairGen.initialize(dhSkipParamSpec); |
104 aliceKpairGen.initialize(dhSkipParamSpec); |
108 KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); |
105 KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); |
109 System.out.println("Alice DH public key:\n" + |
106 System.out.println("Alice DH public key:\n" + |
110 aliceKpair.getPublic().toString()); |
107 aliceKpair.getPublic().toString()); |
111 System.out.println("Alice DH private key:\n" + |
108 System.out.println("Alice DH private key:\n" + |
112 aliceKpair.getPrivate().toString()); |
109 aliceKpair.getPrivate().toString()); |
113 DHParameterSpec dhParamSpec = |
110 DHParameterSpec dhParamSpec = |
114 ((DHPublicKey)aliceKpair.getPublic()).getParams(); |
111 ((DHPublicKey)aliceKpair.getPublic()).getParams(); |
115 AlgorithmParameters algParams = AlgorithmParameters.getInstance("DH"); |
112 AlgorithmParameters algParams = AlgorithmParameters.getInstance("DH", SUNJCE); |
116 algParams.init(dhParamSpec); |
113 algParams.init(dhParamSpec); |
117 System.out.println("Alice DH parameters:\n" |
114 System.out.println("Alice DH parameters:\n" |
118 + algParams.toString()); |
115 + algParams.toString()); |
119 |
116 |
120 // Alice executes Phase1 of her version of the DH protocol |
117 // Alice executes Phase1 of her version of the DH protocol |
121 System.err.println("ALICE: Execute PHASE1 ..."); |
118 System.err.println("ALICE: Execute PHASE1 ..."); |
122 KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH"); |
119 KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH", SUNJCE); |
123 aliceKeyAgree.init(aliceKpair.getPrivate()); |
120 aliceKeyAgree.init(aliceKpair.getPrivate()); |
124 |
121 |
125 // Alice encodes her public key, and sends it over to Bob. |
122 // Alice encodes her public key, and sends it over to Bob. |
126 byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded(); |
123 byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded(); |
127 |
124 |
128 /* |
125 /* |
129 * Let's turn over to Bob. Bob has received Alice's public key |
126 * Let's turn over to Bob. Bob has received Alice's public key |
130 * in encoded format. |
127 * in encoded format. |
131 * He instantiates a DH public key from the encoded key material. |
128 * He instantiates a DH public key from the encoded key material. |
132 */ |
129 */ |
133 KeyFactory bobKeyFac = KeyFactory.getInstance("DH"); |
130 KeyFactory bobKeyFac = KeyFactory.getInstance("DH", SUNJCE); |
134 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec |
131 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec |
135 (alicePubKeyEnc); |
132 (alicePubKeyEnc); |
136 PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec); |
133 PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec); |
137 |
134 |
138 /* |
135 /* |
142 */ |
139 */ |
143 dhParamSpec = ((DHPublicKey)alicePubKey).getParams(); |
140 dhParamSpec = ((DHPublicKey)alicePubKey).getParams(); |
144 |
141 |
145 // Bob creates his own DH key pair |
142 // Bob creates his own DH key pair |
146 System.err.println("BOB: Generate DH keypair ..."); |
143 System.err.println("BOB: Generate DH keypair ..."); |
147 KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH"); |
144 KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH", SUNJCE); |
148 bobKpairGen.initialize(dhParamSpec); |
145 bobKpairGen.initialize(dhParamSpec); |
149 KeyPair bobKpair = bobKpairGen.generateKeyPair(); |
146 KeyPair bobKpair = bobKpairGen.generateKeyPair(); |
150 System.out.println("Bob DH public key:\n" + |
147 System.out.println("Bob DH public key:\n" + |
151 bobKpair.getPublic().toString()); |
148 bobKpair.getPublic().toString()); |
152 System.out.println("Bob DH private key:\n" + |
149 System.out.println("Bob DH private key:\n" + |
153 bobKpair.getPrivate().toString()); |
150 bobKpair.getPrivate().toString()); |
154 |
151 |
155 // Bob executes Phase1 of his version of the DH protocol |
152 // Bob executes Phase1 of his version of the DH protocol |
156 System.err.println("BOB: Execute PHASE1 ..."); |
153 System.err.println("BOB: Execute PHASE1 ..."); |
157 KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH"); |
154 KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH", SUNJCE); |
158 bobKeyAgree.init(bobKpair.getPrivate()); |
155 bobKeyAgree.init(bobKpair.getPrivate()); |
159 |
156 |
160 // Bob encodes his public key, and sends it over to Alice. |
157 // Bob encodes his public key, and sends it over to Alice. |
161 byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded(); |
158 byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded(); |
162 |
159 |
164 * Alice uses Bob's public key for Phase2 of her version of the DH |
161 * Alice uses Bob's public key for Phase2 of her version of the DH |
165 * protocol. |
162 * protocol. |
166 * Before she can do so, she has to instanticate a DH public key |
163 * Before she can do so, she has to instanticate a DH public key |
167 * from Bob's encoded key material. |
164 * from Bob's encoded key material. |
168 */ |
165 */ |
169 KeyFactory aliceKeyFac = KeyFactory.getInstance("DH"); |
166 KeyFactory aliceKeyFac = KeyFactory.getInstance("DH", SUNJCE); |
170 x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc); |
167 x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc); |
171 PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec); |
168 PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec); |
172 System.err.println("ALICE: Execute PHASE2 ..."); |
169 System.err.println("ALICE: Execute PHASE2 ..."); |
173 aliceKeyAgree.doPhase(bobPubKey, true); |
170 aliceKeyAgree.doPhase(bobPubKey, true); |
174 |
171 |
184 * agreement protocol. |
181 * agreement protocol. |
185 * Each generates the (same) shared secret. |
182 * Each generates the (same) shared secret. |
186 */ |
183 */ |
187 byte[] aliceSharedSecret = aliceKeyAgree.generateSecret(); |
184 byte[] aliceSharedSecret = aliceKeyAgree.generateSecret(); |
188 int aliceLen = aliceSharedSecret.length; |
185 int aliceLen = aliceSharedSecret.length; |
|
186 |
|
187 // check if alice's key agreement has been reset afterwards |
|
188 try { |
|
189 aliceKeyAgree.generateSecret(); |
|
190 throw new Exception("Error: alice's KeyAgreement not reset"); |
|
191 } catch (IllegalStateException e) { |
|
192 System.out.println("EXPECTED: " + e.getMessage()); |
|
193 } |
189 |
194 |
190 byte[] bobSharedSecret = new byte[aliceLen]; |
195 byte[] bobSharedSecret = new byte[aliceLen]; |
191 int bobLen; |
196 int bobLen; |
192 try { |
197 try { |
193 // provide output buffer that is too short |
198 // provide output buffer that is too short |
194 bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 1); |
199 bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 1); |
195 |
|
196 /* |
|
197 * Gatekeeper's note: |
|
198 * We should not be getting here, but every so often, we |
|
199 * get a failure, either a "ShortBufferException" or |
|
200 * "Key agreement has not been completed yet" in the |
|
201 * generateSecret(bobSharedSecret, 0) below. |
|
202 * |
|
203 * This will help to figure out why we're dropping through |
|
204 * and not failing. |
|
205 */ |
|
206 System.out.println("NIGHTLY: Should *NOT* be here!!!\n" + |
|
207 "aliceLen = " + aliceLen + "\n" + |
|
208 "Alice's shared secret"); |
|
209 |
|
210 try { |
|
211 HexDumpEncoder hd = new HexDumpEncoder(); |
|
212 |
|
213 hd.encodeBuffer( |
|
214 new ByteArrayInputStream(aliceSharedSecret), System.out); |
|
215 } catch (IOException e) { } |
|
216 |
|
217 System.out.println("bobLen = " + bobLen); |
|
218 |
|
219 try { |
|
220 HexDumpEncoder hd = new HexDumpEncoder(); |
|
221 |
|
222 hd.encodeBuffer( |
|
223 new ByteArrayInputStream(bobSharedSecret), System.out); |
|
224 } catch (IOException e) { } |
|
225 |
|
226 throw new Exception("Shouldn't be succeeding."); |
|
227 } catch (ShortBufferException e) { |
200 } catch (ShortBufferException e) { |
228 System.out.println("EXPECTED: " + e.getMessage()); |
201 System.out.println("EXPECTED: " + e.getMessage()); |
229 } |
202 } |
230 |
203 // retry w/ output buffer of required size |
231 // provide output buffer of required size |
|
232 bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 0); |
204 bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 0); |
|
205 |
|
206 // check if bob's key agreement has been reset afterwards |
|
207 try { |
|
208 bobKeyAgree.generateSecret(bobSharedSecret, 0); |
|
209 throw new Exception("Error: bob's KeyAgreement not reset"); |
|
210 } catch (IllegalStateException e) { |
|
211 System.out.println("EXPECTED: " + e.getMessage()); |
|
212 } |
233 |
213 |
234 System.out.println("Alice secret: " + toHexString(aliceSharedSecret)); |
214 System.out.println("Alice secret: " + toHexString(aliceSharedSecret)); |
235 System.out.println("Bob secret: " + toHexString(bobSharedSecret)); |
215 System.out.println("Bob secret: " + toHexString(bobSharedSecret)); |
236 |
216 |
237 if (aliceLen != bobLen) { |
217 if (aliceLen != bobLen) { |