Source code: com/traxel/crypto/DHUtil.java
1 /* $Id: DHUtil.java,v 1.4 2001/04/01 05:38:42 cvsbob Exp $ */
2
3 /*
4 * DHUtil.java, tool to handle DH keypairs.
5 * Copyright (C) 2001 Robert Bushman.
6 *
7 * I reserve the right to release this program under seperate license.
8 * If you require a special license grant contact Robert Bushman.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 * 02111-1307, USA.
24 */
25
26 package com.traxel.crypto;
27
28 import java.io.InputStream;
29 import java.io.IOException;
30 import java.math.BigInteger;
31 import java.security.AlgorithmParameterGenerator;
32 import java.security.AlgorithmParameters;
33 import java.security.KeyFactory;
34 import java.security.NoSuchAlgorithmException;
35 import java.security.Security;
36 import java.security.spec.InvalidKeySpecException;
37 import java.security.spec.InvalidParameterSpecException;
38 import java.security.spec.X509EncodedKeySpec;
39 import java.security.spec.PKCS8EncodedKeySpec;
40 import javax.crypto.spec.DHParameterSpec;
41 import javax.crypto.interfaces.DHPublicKey;
42 import javax.crypto.interfaces.DHPrivateKey;
43
44 /**
45 * This class has been coded to solve my specific problems.
46 * It is not general purpose. <b>Use at your own risk.</b>
47 */
48 public class DHUtil {
49
50 // -------------------------------------------------------------
51 // CONSTANTS
52 // -------------------------------------------------------------
53
54 public static final String DH = "DH";
55
56 // ------------------------------------------------------------
57
58 public static DHParameterSpec generateDhParams( int bitSize ) {
59 DHParameterSpec parameterSpec;
60 AlgorithmParameterGenerator parameterGenerator;
61 AlgorithmParameters parameters;
62
63 System.out.print( "Secure Params Can Take A Long Time..." );
64 System.out.flush();
65
66 try {
67 parameterGenerator =
68 AlgorithmParameterGenerator.getInstance( DH );
69 parameterGenerator.init( bitSize );
70 parameters = parameterGenerator.generateParameters();
71 parameterSpec = (DHParameterSpec)
72 parameters.getParameterSpec( DHParameterSpec.class );
73
74 System.out.println( "Secure Params Generated" );
75
76 return( parameterSpec );
77 } catch( NoSuchAlgorithmException e ) {
78 e.printStackTrace();
79 System.exit( 1 );
80 } catch( InvalidParameterSpecException e ) {
81 e.printStackTrace();
82 System.exit( 1 );
83 }
84
85 return( null );
86 }
87
88 /**
89 * <b>WARNING:</b> This is quite happy to extract the base 16 bytes
90 * from a non-base 16 document. EG: if you read from "document"
91 * it would return "dce".
92 * <br>
93 * <b>NOTE:</b> This method depends on the termination of the
94 * input stream (IE: it returns -1 in response to a read() ).
95 */
96 public static DHPrivateKey privKeyFromBase16( InputStream in )
97 throws InvalidKeySpecException, IOException {
98
99 PKCS8EncodedKeySpec pkcs8 = pkcs8FromBase16( in );
100 return( privKeyFromPkcs8( pkcs8 ) );
101 }
102
103 /**
104 * <b>WARNING:</b> This is quite happy to extract the base 16 bytes
105 * from a non-base 16 document. EG: if you read from "document"
106 * it would return "dce".
107 * <br>
108 * <b>NOTE:</b> This method depends on the termination of the
109 * input stream (IE: it returns -1 in response to a read() ).
110 */
111 public static DHPublicKey pubKeyFromBase16( InputStream in )
112 throws InvalidKeySpecException, IOException {
113
114 X509EncodedKeySpec x509 = x509FromBase16( in );
115 return( pubKeyFromX509( x509 ) );
116 }
117
118 public static DHPublicKey pubKeyFromX509( X509EncodedKeySpec x509 )
119 throws InvalidKeySpecException {
120
121 KeyFactory keyFac;
122 DHPublicKey pubKey = null;
123
124 try {
125 keyFac = KeyFactory.getInstance( DH );
126 pubKey = (DHPublicKey)keyFac.generatePublic( x509 );
127 } catch( NoSuchAlgorithmException e ) {
128 e.printStackTrace();
129 System.out.println( "This should never happen" );
130 System.exit( 1 );
131 }
132
133 return( pubKey );
134 }
135
136 public static DHPrivateKey privKeyFromPkcs8( PKCS8EncodedKeySpec pkcs8 )
137 throws InvalidKeySpecException {
138
139 KeyFactory keyFac;
140 DHPrivateKey privKey = null;
141
142 try {
143 keyFac = KeyFactory.getInstance( DH );
144 privKey = (DHPrivateKey)keyFac.generatePrivate( pkcs8 );
145 } catch( NoSuchAlgorithmException e ) {
146 e.printStackTrace();
147 System.out.println( "This should never happen" );
148 System.exit( 1 );
149 }
150
151 return( privKey );
152 }
153
154 public static PKCS8EncodedKeySpec pkcs8FromBase16( InputStream in )
155 throws IOException {
156
157 String base16;
158 BigInteger bigInt;
159 byte[] keyBytes;
160 PKCS8EncodedKeySpec pkcs8;
161
162 base16 = readBase16( in );
163 bigInt = new BigInteger( base16, 16 );
164 keyBytes = bigInt.toByteArray();
165 pkcs8 = new PKCS8EncodedKeySpec( keyBytes );
166
167 return( pkcs8 );
168 }
169
170 public static X509EncodedKeySpec x509FromBase16( InputStream in )
171 throws IOException {
172
173 String base16;
174 BigInteger bigInt;
175 byte[] keyBytes;
176 X509EncodedKeySpec x509;
177
178 base16 = readBase16( in );
179 bigInt = new BigInteger( base16, 16 );
180 keyBytes = bigInt.toByteArray();
181 x509 = new X509EncodedKeySpec( keyBytes );
182
183 return( x509 );
184 }
185
186 public static String readBase16( InputStream in )
187 throws IOException {
188
189 int byteRead;
190 StringBuffer pubBase16Buffer = new StringBuffer();
191
192 while( ( byteRead = in.read() ) > -1 ) {
193 if( isBase16( (char)byteRead ) ) {
194 pubBase16Buffer.append( (char)byteRead );
195 }
196 }
197
198 return( pubBase16Buffer.toString() );
199 }
200
201 public static boolean isBase16( char character ) {
202 return( ( character >= '0' && character <= '9' )
203 ||
204 ( character >= 'A' && character <= 'F' )
205 ||
206 ( character >= 'a' && character <= 'f' ) );
207 }
208
209 // ----------------------------------------------------
210 // RUNTIME
211 // ---------------------------------------------------
212
213 public static void main( String[] args ) {
214 // BUG: Removed this because I didn't want to take the
215 // time to do the Class.forName stuff, and am using
216 // bouncy castle now.
217 // SunJCE provider = new SunJCE();
218 // Security.addProvider( provider );
219 DHParameterSpec params = generateDhParams( 1024 );
220 System.out.println( "P: " + params.getP().toString( 16 ) );
221 System.out.println( "G: " + params.getG().toString( 16 ) );
222 }
223 }