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のバイトに変換されますが、ここでは?6?数で??に変換して?す? 223 * 224 * 変換方法?、各バイト?上?下位を?6???に変換後?連結して?す? 225 * これは、Tomcat等? digest 認証(MD5使用?と同じ変換方式です? 226 * 連結後???長は?2バイ?固?になります? 227 * 228 * @og.rev 5.2.2.0 (2010/11/01) util.StringUtil から移? 229 * 230 * @param input 変換前??? 231 * 232 * @return MD5でハッシュした??。32バイ?固? 233 */ 234 public static String getMD5( final String input ) { 235 String rtn = null; 236 if( input != null ) { 237 try { 238 MessageDigest md5 = MessageDigest.getInstance( "MD5" ); 239 // md5.update( input.getBytes() ); 240 md5.update( input.getBytes( DEFAULT_CHARSET ) ); // 5.5.2.6 (2012/05/25) findbugs対? 241 byte[] out = md5.digest(); 242 rtn = byte2hexa( out ); 243 } 244 catch( NoSuchAlgorithmException ex ) { 245 String errMsg = "MessageDigestで失敗しました?" + input + "]" 246 + ex.getMessage() ; 247 throw new RuntimeException( errMsg,ex ); 248 } 249 } 250 return rtn; 251 } 252 253 /** 254 * MessageDigestにより、MD5 でハッシュした?に変換します? 255 * 256 * MD5で?6Byteのバイトに変換されますが、ここでは?6?数で??に変換して?す? 257 * 258 * 変換方法?、各バイト?上?下位を?6???に変換後?連結して?す? 259 * これは、Tomcat等? digest 認証(MD5使用?と同じ変換方式です? 260 * 連結後???長は?2バイ?固?になります? 261 * 262 * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます? 263 * 264 * @param input 変換前?File 265 * 266 * @return MD5でハッシュした??。32バイ?固? 267 */ 268 public static String getMD5( final File input ) { 269 String rtn = null; 270 if( input != null ) { 271 FileInputStream fis = null; 272 FileChannel fc = null; 273 try { 274 MessageDigest md5 = MessageDigest.getInstance( "MD5" ); 275 fis = new FileInputStream( input ); 276 fc =fis.getChannel(); 277 ByteBuffer bb = fc.map( FileChannel.MapMode.READ_ONLY , 0L , fc.size() ); 278 md5.update( bb ); 279 byte[] out = md5.digest(); 280 rtn = byte2hexa( out ); 281 } 282 catch( NoSuchAlgorithmException ex ) { 283 String errMsg = "MessageDigestで MD5 インスタンスの作?に失敗しました?" + input + "]" 284 + ex.getMessage() ; 285 throw new RuntimeException( errMsg,ex ); 286 } 287 catch( IOException ex ) { 288 String errMsg = "ファイルの読み取りを失敗しました?" + input + "]" 289 + ex.getMessage() ; 290 throw new RuntimeException( errMsg,ex ); 291 } 292 finally { 293 Closer.ioClose( fc ); 294 Closer.ioClose( fis ); 295 } 296 } 297 return rtn; 298 } 299 300 /** 301 * 暗号化??トを行う為のメインメソ? 302 * 303 * java HybsCryptography KEY TEXT で起動します? 304 * KEY : 秘?(8 の倍数 (32 以?448 以??? 305 * TEXT : 変換する?? 306 * 307 * @og.rev 5.2.2.0 (2010/11/01) 循環参?の解?LogWriter 削除) 308 * 309 * @param args 引数配? 310 * @throws Exception なんらか?エラーが発生した?合? 311 */ 312 public static void main( final String[] args ) throws Exception { 313 if( args.length != 2 ) { 314 // LogWriter.log( "java HybsCryptography KEY TEXT" ); 315 // LogWriter.log( " KEY : 秘?(8 の倍数 (32 以?448 以???" ); 316 // LogWriter.log( " TEXT : 変換する??" ); 317 System.out.println( "java HybsCryptography KEY TEXT" ); 318 System.out.println( " KEY : 秘?(8 の倍数 (32 以?448 以???" ); 319 System.out.println( " TEXT : 変換する??" ); 320 return; 321 } 322 323 HybsCryptography cript = new HybsCryptography( args[0] ); 324 325 System.out.println( "IN TEXT : " + args[1] ); 326 327 String hexa = cript.encrypt( args[1] ); 328 System.out.println( "HEXA TEXT : " + hexa ); 329 330 String data = cript.decrypt( hexa ); 331 System.out.println( "OUT DATA : " + data ); 332 } 333 }