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 }