001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.fukurou.security;
017
018 import javax.crypto.spec.SecretKeySpec;
019 import javax.crypto.Cipher;
020
021 import java.security.MessageDigest;
022 import java.security.NoSuchAlgorithmException;
023 import java.security.GeneralSecurityException; // 5.7.2.1 (2014/01/17)
024
025 import java.nio.charset.Charset; // 5.5.2.6 (2012/05/25)
026 import java.nio.channels.FileChannel; // 5.7.2.1 (2014/01/17)
027 import java.nio.ByteBuffer; // 5.5.2.6 (2012/05/25)
028 import java.nio.channels.FileChannel.MapMode; // 5.5.2.6 (2012/05/25)
029
030 import java.io.File;
031 import java.io.FileInputStream;
032 import java.io.IOException;
033
034 import org.opengion.fukurou.util.Closer; // 5.5.2.6 (2012/05/25)
035
036 /**
037 * HybsCryptography は、セキュリ?強化?為の Hybs独自の暗号化クラスです?
038 *
039 * こ?クラスは、暗号化キーを受け取り?それに基づ?暗号?復号化を行います?
040 * ここでの暗号化?、秘?ー方式でバイト文字?に変換されたものを??6?アスキー?に
041 * 直して、扱って?す?よって、暗号?復号化?に、文字?として扱?とが可能です?
042 *
043 * @og.rev 4.0.0.0 (2005/08/31) 新規追?
044 * @og.group ライセンス管?
045 *
046 * @version 4.0
047 * @author Kazuhiko Hasegawa
048 * @since JDK5.0,
049 */
050 public final class HybsCryptography {
051 private final SecretKeySpec sksSpec ;
052 private static final String CIPHER_TYPE = "Blowfish" ;
053
054 /**
055 * プラ?フォー?存??ォルト? Charset です?
056 * プラ?フォー?存?を?慮する場合?エンコード指定で作?しておく事をお勧めします?
057 *
058 * @og.rev 5.5.2.6 (2012/05/25) findbugs対?
059 */
060 private static final Charset DEFAULT_CHARSET = Charset.defaultCharset() ;
061
062 // 注意:秘?ーは??倍数でな??な??
063 private static final String HYBS_CRYPT_KEY = "2a5a88891d37ae59" ;
064
065 /**
066 * ?設定?秘?を使用して?暗号化を行うオブジェクトを構築します?
067 * ここでの暗号化?、Java標準?セキュリ?パッケージを使用して?す?
068 */
069 public HybsCryptography() {
070 // sksSpec = new SecretKeySpec( HYBS_CRYPT_KEY.getBytes(), CIPHER_TYPE );
071 sksSpec = new SecretKeySpec( HYBS_CRYPT_KEY.getBytes( DEFAULT_CHARSET ), CIPHER_TYPE ); // 5.5.2.6 (2012/05/25) findbugs対?
072 }
073
074 /**
075 * 秘?の??を受け取って?暗号化を行うオブジェクトを構築します?
076 * ここでの暗号化?、Java標準?セキュリ?パッケージを使用して?す?
077 * 秘?のサイズを?8 の倍数 (32 以?448 以? にする?があります?
078 *
079 * @og.rev 5.8.8.0 (2015/06/05) null時?挙動は?ォルトキーを利用する
080 *
081 * @param cryptKey 暗号化を行う秘?
082 */
083 public HybsCryptography( final String cryptKey ) {
084 // sksSpec = new SecretKeySpec( cryptKey.getBytes(), CIPHER_TYPE );
085 // sksSpec = new SecretKeySpec( cryptKey.getBytes( DEFAULT_CHARSET ), CIPHER_TYPE ); // 5.5.2.6 (2012/05/25) findbugs対?
086 // 5.8.8.0 (2015/06/05) null時??ォルトキーを利用
087 final String useKey;
088 if( cryptKey == null || cryptKey.length() == 0 ){
089 useKey = HYBS_CRYPT_KEY;
090 }
091 else{
092 useKey = cryptKey;
093 }
094 sksSpec = new SecretKeySpec( useKey.getBytes( DEFAULT_CHARSET ), CIPHER_TYPE );
095 }
096
097 /**
098 * セキュリ?カラ??DBTyepに対してHybs独自の暗号化を行います?
099 * 暗号化された??タは??常 byte ?ですが?6?数アスキー??に変換
100 * したも?を返します?
101 * こ?暗号化では、引数?null の場合?、ゼロ??を返します?
102 *
103 * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます?
104 *
105 * @param org 暗号化を行う????
106 *
107 * @return 暗号化された??(HEXADECIMAL?
108 */
109 public String encrypt( final String org ) {
110 if( org == null || org.length() == 0 ) { return ""; }
111
112 try {
113 Cipher cipher = Cipher.getInstance( CIPHER_TYPE );
114 cipher.init( Cipher.ENCRYPT_MODE, sksSpec );
115 // byte[] encrypted = cipher.doFinal( org.getBytes() );
116 byte[] encrypted = cipher.doFinal( org.getBytes( DEFAULT_CHARSET ) ); // 5.5.2.6 (2012/05/25) findbugs対?
117
118 return byte2hexa( encrypted );
119 }
120 // 5.7.2.1 (2014/01/17) Exceptionをまとめます?
121 catch( GeneralSecurityException ex ) {
122 String errMsg = "暗号化??失敗しました?" + org + "]"
123 + ex.getMessage() ;
124 throw new RuntimeException( errMsg,ex );
125 }
126 // catch( javax.crypto.IllegalBlockSizeException ex ) { throw new RuntimeException( ex ); }
127 // catch( java.security.InvalidKeyException ex ) { throw new RuntimeException( ex ); }
128 // catch( java.security.NoSuchAlgorithmException ex ) { throw new RuntimeException( ex ); }
129 // catch( javax.crypto.BadPaddingException ex ) { throw new RuntimeException( ex ); }
130 // catch( javax.crypto.NoSuchPaddingException ex ) { throw new RuntimeException( ex ); }
131 }
132
133 /**
134 * セキュリ?カラ??DBTyepに対してHybs独自の復号化を行います?
135 * ここでの復号化?、encrypt で暗号化された?を戻す?合に使用します?
136 * こ?復号化では、null は復号化できな?め?ゼロ??を返します?
137 *
138 * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます?
139 *
140 * @param hex 復号化を行う暗号化された?6?数アスキー??
141 *
142 * @return 復号化された????
143 */
144 public String decrypt( final String hex ) {
145 if( hex == null || hex.length() == 0 ) { return ""; }
146
147 try {
148 Cipher cipher = Cipher.getInstance( CIPHER_TYPE );
149 cipher.init( Cipher.DECRYPT_MODE, sksSpec );
150 byte[] encrypted = hexa2byte( hex );
151 byte[] decrypted = cipher.doFinal( encrypted );
152 // return new String( decrypted );
153 return new String( decrypted,DEFAULT_CHARSET ); // 5.5.2.6 (2012/05/25) findbugs対?
154 }
155 // 5.7.2.1 (2014/01/17) Exceptionをまとめます?
156 catch( GeneralSecurityException ex ) {
157 String errMsg = "復号化??失敗しました?" + hex + "]"
158 + ex.getMessage() ;
159 throw new RuntimeException( errMsg,ex );
160 }
161 // catch( javax.crypto.IllegalBlockSizeException ex ) { throw new RuntimeException( ex ); }
162 // catch( java.security.InvalidKeyException ex ) { throw new RuntimeException( ex ); }
163 // catch( java.security.NoSuchAlgorithmException ex ) { throw new RuntimeException( ex ); }
164 // catch( javax.crypto.BadPaddingException ex ) { throw new RuntimeException( ex ); }
165 // catch( javax.crypto.NoSuchPaddingException ex ) { throw new RuntimeException( ex ); }
166 }
167 /**
168 * 数字から16??に変換する??ブルです?
169 */
170 private static final char[] hexadecimal =
171 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
172 'a', 'b', 'c', 'd', 'e', 'f' };
173
174 /**
175 * バイト?列を?6?数アスキー??に変換します?
176 *
177 * バイト?列を?文字?0??,a???アスキーに変換されます?
178 * これにより、すべての?を、アスキー化できます?
179 * アスキー化で、上位が0F以下?場合でも?0 を?すことで、固定長に変換します?
180 *
181 * よって、?力バイト???のlength()を持ったStringを作?します?
182 *
183 * @param input バイト??
184 *
185 * @return ?6?数アスキー??
186 */
187 public static String byte2hexa( final byte[] input ) {
188 String rtn = null;
189 if( input != null ) {
190 int len = input.length ;
191 char[] ch = new char[len*2];
192 for( int i=0; i<len; i++ ) {
193 int high = ((input[i] & 0xf0) >> 4);
194 int low = (input[i] & 0x0f);
195 ch[i*2] = hexadecimal[high];
196 ch[i*2+1] = hexadecimal[low];
197 }
198 rtn = new String(ch);
199 }
200 return rtn;
201 }
202
203 /**
204 * ?6?数アスキー??をバイト?列に変換します?
205 *
206 * ?文字?0??,a???アスキー??を?バイト?列に変換されます?
207 *
208 * よって、?力Stringの????のlengthを持ったバイト?列を作?します?
209 *
210 * @param input ?6?数アスキー??
211 *
212 * @return バイト??
213 */
214 public static byte[] hexa2byte( final String input ) {
215 byte[] rtn = null;
216 if( input != null ) {
217 int len = input.length() ;
218 rtn = new byte[len/2];
219 for( int i=0; i<len/2; i++ ) {
220 char ch = input.charAt( i*2 );
221 int high = ( ch < 'a' ) ? ch-'0' : ch-'a'+10 ;
222 ch = input.charAt( i*2+1 );
223 int low = ( ch < 'a' ) ? ch-'0' : ch-'a'+10 ;
224 rtn[i] = (byte)(high << 4 | low);
225 }
226 }
227 return rtn;
228 }
229
230 /**
231 * MessageDigestにより、MD5 でハッシュした?に変換します?
232 *
233 * MD5で?6Byteのバイトに変換されますが、ここでは?6?数で??に変換して?す?
234 *
235 * 変換方法?、各バイト?上?下位を?6???に変換後?連結して?す?
236 * これは、Tomcat等? digest 認証(MD5使用?と同じ変換方式です?
237 * 連結後???長は?2バイ?固?になります?
238 *
239 * @og.rev 5.2.2.0 (2010/11/01) util.StringUtil から移?
240 *
241 * @param input 変換前???
242 *
243 * @return MD5でハッシュした??。32バイ?固?
244 */
245 public static String getMD5( final String input ) {
246 String rtn = null;
247 if( input != null ) {
248 try {
249 MessageDigest md5 = MessageDigest.getInstance( "MD5" );
250 // md5.update( input.getBytes() );
251 md5.update( input.getBytes( DEFAULT_CHARSET ) ); // 5.5.2.6 (2012/05/25) findbugs対?
252 byte[] out = md5.digest();
253 rtn = byte2hexa( out );
254 }
255 catch( NoSuchAlgorithmException ex ) {
256 String errMsg = "MessageDigestで失敗しました?" + input + "]"
257 + ex.getMessage() ;
258 throw new RuntimeException( errMsg,ex );
259 }
260 }
261 return rtn;
262 }
263
264 /**
265 * MessageDigestにより、MD5 でハッシュした?に変換します?
266 *
267 * MD5で?6Byteのバイトに変換されますが、ここでは?6?数で??に変換して?す?
268 *
269 * 変換方法?、各バイト?上?下位を?6???に変換後?連結して?す?
270 * これは、Tomcat等? digest 認証(MD5使用?と同じ変換方式です?
271 * 連結後???長は?2バイ?固?になります?
272 *
273 * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます?
274 *
275 * @param input 変換前?File
276 *
277 * @return MD5でハッシュした??。32バイ?固?
278 */
279 public static String getMD5( final File input ) {
280 String rtn = null;
281 if( input != null ) {
282 FileInputStream fis = null;
283 FileChannel fc = null;
284 try {
285 MessageDigest md5 = MessageDigest.getInstance( "MD5" );
286 fis = new FileInputStream( input );
287 fc =fis.getChannel();
288 ByteBuffer bb = fc.map( FileChannel.MapMode.READ_ONLY , 0L , fc.size() );
289 md5.update( bb );
290 byte[] out = md5.digest();
291 rtn = byte2hexa( out );
292 }
293 catch( NoSuchAlgorithmException ex ) {
294 String errMsg = "MessageDigestで MD5 インスタンスの作?に失敗しました?" + input + "]"
295 + ex.getMessage() ;
296 throw new RuntimeException( errMsg,ex );
297 }
298 catch( IOException ex ) {
299 String errMsg = "ファイルの読み取りを失敗しました?" + input + "]"
300 + ex.getMessage() ;
301 throw new RuntimeException( errMsg,ex );
302 }
303 finally {
304 Closer.ioClose( fc );
305 Closer.ioClose( fis );
306 }
307 }
308 return rtn;
309 }
310
311 /**
312 * 暗号化??トを行う為のメインメソ?
313 *
314 * java HybsCryptography KEY TEXT で起動します?
315 * KEY : 秘?(8 の倍数 (32 以?448 以???
316 * TEXT : 変換する??
317 *
318 * @og.rev 5.2.2.0 (2010/11/01) 循環参?の解?LogWriter 削除)
319 *
320 * @param args 引数配?
321 * @throws Exception なんらか?エラーが発生した?合?
322 */
323 public static void main( final String[] args ) throws Exception {
324 if( args.length != 2 ) {
325 // LogWriter.log( "java HybsCryptography KEY TEXT" );
326 // LogWriter.log( " KEY : 秘?(8 の倍数 (32 以?448 以???" );
327 // LogWriter.log( " TEXT : 変換する??" );
328 System.out.println( "java HybsCryptography KEY TEXT" );
329 System.out.println( " KEY : 秘?(8 の倍数 (32 以?448 以???" );
330 System.out.println( " TEXT : 変換する??" );
331 return;
332 }
333
334 HybsCryptography cript = new HybsCryptography( args[0] );
335
336 System.out.println( "IN TEXT : " + args[1] );
337
338 String hexa = cript.encrypt( args[1] );
339 System.out.println( "HEXA TEXT : " + hexa );
340
341 String data = cript.decrypt( hexa );
342 System.out.println( "OUT DATA : " + data );
343 }
344 }