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 * @param cryptKey 暗号化を行う秘? 080 */ 081 public HybsCryptography( final String cryptKey ) { 082 // sksSpec = new SecretKeySpec( cryptKey.getBytes(), CIPHER_TYPE ); 083 sksSpec = new SecretKeySpec( cryptKey.getBytes( DEFAULT_CHARSET ), CIPHER_TYPE ); // 5.5.2.6 (2012/05/25) findbugs対? 084 } 085 086 /** 087 * セキュリ?カラ??DBTyepに対してHybs独自の暗号化を行います? 088 * 暗号化された??タは??常 byte ?ですが?6?数アスキー??に変換 089 * したも?を返します? 090 * こ?暗号化では、引数?null の場合?、ゼロ??を返します? 091 * 092 * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます? 093 * 094 * @param org 暗号化を行う???? 095 * 096 * @return 暗号化された??(HEXADECIMAL? 097 */ 098 public String encrypt( final String org ) { 099 if( org == null || org.length() == 0 ) { return ""; } 100 101 try { 102 Cipher cipher = Cipher.getInstance( CIPHER_TYPE ); 103 cipher.init( Cipher.ENCRYPT_MODE, sksSpec ); 104 // byte[] encrypted = cipher.doFinal( org.getBytes() ); 105 byte[] encrypted = cipher.doFinal( org.getBytes( DEFAULT_CHARSET ) ); // 5.5.2.6 (2012/05/25) findbugs対? 106 107 return byte2hexa( encrypted ); 108 } 109 // 5.7.2.1 (2014/01/17) Exceptionをまとめます? 110 catch( GeneralSecurityException ex ) { 111 String errMsg = "暗号化??失敗しました?" + org + "]" 112 + ex.getMessage() ; 113 throw new RuntimeException( errMsg,ex ); 114 } 115 // catch( javax.crypto.IllegalBlockSizeException ex ) { throw new RuntimeException( ex ); } 116 // catch( java.security.InvalidKeyException ex ) { throw new RuntimeException( ex ); } 117 // catch( java.security.NoSuchAlgorithmException ex ) { throw new RuntimeException( ex ); } 118 // catch( javax.crypto.BadPaddingException ex ) { throw new RuntimeException( ex ); } 119 // catch( javax.crypto.NoSuchPaddingException ex ) { throw new RuntimeException( ex ); } 120 } 121 122 /** 123 * セキュリ?カラ??DBTyepに対してHybs独自の復号化を行います? 124 * ここでの復号化?、encrypt で暗号化された?を戻す?合に使用します? 125 * こ?復号化では、null は復号化できな?め?ゼロ??を返します? 126 * 127 * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます? 128 * 129 * @param hex 復号化を行う暗号化された?6?数アスキー?? 130 * 131 * @return 復号化された???? 132 */ 133 public String decrypt( final String hex ) { 134 if( hex == null || hex.length() == 0 ) { return ""; } 135 136 try { 137 Cipher cipher = Cipher.getInstance( CIPHER_TYPE ); 138 cipher.init( Cipher.DECRYPT_MODE, sksSpec ); 139 byte[] encrypted = hexa2byte( hex ); 140 byte[] decrypted = cipher.doFinal( encrypted ); 141 // return new String( decrypted ); 142 return new String( decrypted,DEFAULT_CHARSET ); // 5.5.2.6 (2012/05/25) findbugs対? 143 } 144 // 5.7.2.1 (2014/01/17) Exceptionをまとめます? 145 catch( GeneralSecurityException ex ) { 146 String errMsg = "復号化??失敗しました?" + hex + "]" 147 + ex.getMessage() ; 148 throw new RuntimeException( errMsg,ex ); 149 } 150 // catch( javax.crypto.IllegalBlockSizeException ex ) { throw new RuntimeException( ex ); } 151 // catch( java.security.InvalidKeyException ex ) { throw new RuntimeException( ex ); } 152 // catch( java.security.NoSuchAlgorithmException ex ) { throw new RuntimeException( ex ); } 153 // catch( javax.crypto.BadPaddingException ex ) { throw new RuntimeException( ex ); } 154 // catch( javax.crypto.NoSuchPaddingException ex ) { throw new RuntimeException( ex ); } 155 } 156 /** 157 * 数字から16??に変換する??ブルです? 158 */ 159 private static final char[] hexadecimal = 160 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 161 'a', 'b', 'c', 'd', 'e', 'f' }; 162 163 /** 164 * バイト?列を?6?数アスキー??に変換します? 165 * 166 * バイト?列を?文字?0??,a???アスキーに変換されます? 167 * これにより、すべての?を、アスキー化できます? 168 * アスキー化で、上位が0F以下?場合でも?0 を?すことで、固定長に変換します? 169 * 170 * よって、?力バイト???のlength()を持ったStringを作?します? 171 * 172 * @param input バイト?? 173 * 174 * @return ?6?数アスキー?? 175 */ 176 public static String byte2hexa( final byte[] input ) { 177 String rtn = null; 178 if( input != null ) { 179 int len = input.length ; 180 char[] ch = new char[len*2]; 181 for( int i=0; i<len; i++ ) { 182 int high = ((input[i] & 0xf0) >> 4); 183 int low = (input[i] & 0x0f); 184 ch[i*2] = hexadecimal[high]; 185 ch[i*2+1] = hexadecimal[low]; 186 } 187 rtn = new String(ch); 188 } 189 return rtn; 190 } 191 192 /** 193 * ?6?数アスキー??をバイト?列に変換します? 194 * 195 * ?文字?0??,a???アスキー??を?バイト?列に変換されます? 196 * 197 * よって、?力Stringの????のlengthを持ったバイト?列を作?します? 198 * 199 * @param input ?6?数アスキー?? 200 * 201 * @return バイト?? 202 */ 203 public static byte[] hexa2byte( final String input ) { 204 byte[] rtn = null; 205 if( input != null ) { 206 int len = input.length() ; 207 rtn = new byte[len/2]; 208 for( int i=0; i<len/2; i++ ) { 209 char ch = input.charAt( i*2 ); 210 int high = ( ch < 'a' ) ? ch-'0' : ch-'a'+10 ; 211 ch = input.charAt( i*2+1 ); 212 int low = ( ch < 'a' ) ? ch-'0' : ch-'a'+10 ; 213 rtn[i] = (byte)(high << 4 | low); 214 } 215 } 216 return rtn; 217 } 218 219 /** 220 * MessageDigestにより、MD5 でハッシュした?に変換します? 221 * 222 * MD5で?6Byteのバイトに変換されますが、ここでは?del>マイナス時には, 223 * 符号を反転させて?/del>?6?数で??に変換して?す? 224 * <del>よって、このメソ?で変換した?でのみ突き合わせて正しいかど?? 225 * 判断してください?/del> 226 * 227 * 変換方法?、各バイト?上?下位を?6???に変換後?連結して?す? 228 * これは、Tomcat等? digest 認証(MD5使用?と同じ変換方式です? 229 * 連結後???長は?2バイ?固?になります? 230 * 231 * @og.rev 5.2.2.0 (2010/11/01) util.StringUtil から移? 232 * 233 * @param input 変換前??? 234 * 235 * @return MD5でハッシュした??。32バイ?固? 236 */ 237 public static String getMD5( final String input ) { 238 String rtn = null; 239 if( input != null ) { 240 try { 241 MessageDigest md5 = MessageDigest.getInstance( "MD5" ); 242 // md5.update( input.getBytes() ); 243 md5.update( input.getBytes( DEFAULT_CHARSET ) ); // 5.5.2.6 (2012/05/25) findbugs対? 244 byte[] out = md5.digest(); 245 rtn = byte2hexa( out ); 246 } 247 catch( NoSuchAlgorithmException ex ) { 248 String errMsg = "MessageDigestで失敗しました?" + input + "]" 249 + ex.getMessage() ; 250 throw new RuntimeException( errMsg,ex ); 251 } 252 } 253 return rtn; 254 } 255 256 /** 257 * MessageDigestにより、MD5 でハッシュした?に変換します? 258 * 259 * MD5で?6Byteのバイトに変換されますが、ここでは?6?数で??に変換して?す? 260 * 261 * 変換方法?、各バイト?上?下位を?6???に変換後?連結して?す? 262 * これは、Tomcat等? digest 認証(MD5使用?と同じ変換方式です? 263 * 連結後???長は?2バイ?固?になります? 264 * 265 * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます? 266 * 267 * @param input 変換前?File 268 * 269 * @return MD5でハッシュした??。32バイ?固? 270 */ 271 public static String getMD5( final File input ) { 272 String rtn = null; 273 if( input != null ) { 274 FileInputStream fis = null; 275 FileChannel fc = null; 276 try { 277 MessageDigest md5 = MessageDigest.getInstance( "MD5" ); 278 fis = new FileInputStream( input ); 279 fc =fis.getChannel(); 280 ByteBuffer bb = fc.map( FileChannel.MapMode.READ_ONLY , 0L , fc.size() ); 281 md5.update( bb ); 282 byte[] out = md5.digest(); 283 rtn = byte2hexa( out ); 284 } 285 catch( NoSuchAlgorithmException ex ) { 286 String errMsg = "MessageDigestで MD5 インスタンスの作?に失敗しました?" + input + "]" 287 + ex.getMessage() ; 288 throw new RuntimeException( errMsg,ex ); 289 } 290 catch( IOException ex ) { 291 String errMsg = "ファイルの読み取りを失敗しました?" + input + "]" 292 + ex.getMessage() ; 293 throw new RuntimeException( errMsg,ex ); 294 } 295 finally { 296 Closer.ioClose( fc ); 297 Closer.ioClose( fis ); 298 } 299 } 300 return rtn; 301 } 302 303 /** 304 * 暗号化??トを行う為のメインメソ? 305 * 306 * java HybsCryptography KEY TEXT で起動します? 307 * KEY : 秘?(8 の倍数 (32 以?448 以??? 308 * TEXT : 変換する?? 309 * 310 * @og.rev 5.2.2.0 (2010/11/01) 循環参?の解?LogWriter 削除) 311 * 312 * @param args 引数配? 313 */ 314 public static void main( final String[] args ) throws Exception { 315 if( args.length != 2 ) { 316 // LogWriter.log( "java HybsCryptography KEY TEXT" ); 317 // LogWriter.log( " KEY : 秘?(8 の倍数 (32 以?448 以???" ); 318 // LogWriter.log( " TEXT : 変換する??" ); 319 System.out.println( "java HybsCryptography KEY TEXT" ); 320 System.out.println( " KEY : 秘?(8 の倍数 (32 以?448 以???" ); 321 System.out.println( " TEXT : 変換する??" ); 322 return; 323 } 324 325 HybsCryptography cript = new HybsCryptography( args[0] ); 326 327 System.out.println( "IN TEXT : " + args[1] ); 328 329 String hexa = cript.encrypt( args[1] ); 330 System.out.println( "HEXA TEXT : " + hexa ); 331 332 String data = cript.decrypt( hexa ); 333 System.out.println( "OUT DATA : " + data ); 334 } 335 }