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    
019    import javax.crypto.spec.SecretKeySpec;
020    import javax.crypto.Cipher;
021    
022    import java.security.MessageDigest;
023    import java.security.NoSuchAlgorithmException;
024    import java.nio.charset.Charset;                // 5.5.2.6 (2012/05/25)
025    
026    /**
027     * HybsCryptography は、セキュリãƒ?‚£強化ã?為の Hybs独自の暗号化クラスですã?
028     *
029     * こã?クラスは、暗号化キーを受け取りã?それに基づã�?�¦暗号åŒ?復号化を行いますã?
030     * ここでの暗号化ã?、秘å¯?‚­ー方式でバイト文字å?に変換されたものをã??‘6é?アスキーæ–?­—に
031     * 直して、扱ってã�?�¾すã?よって、暗号åŒ?復号化å?に、文字å?として扱ã�?�“とが可能ですã?
032     *
033     * @og.rev 4.0.0.0 (2005/08/31) 新規追åŠ?
034     * @og.group ライセンス管ç�?
035     *
036     * @version  4.0
037     * @author   Kazuhiko Hasegawa
038     * @since    JDK5.0,
039     */
040    public final class HybsCryptography {
041            private final SecretKeySpec sksSpec ;
042            private static final String CIPHER_TYPE = "Blowfish" ;
043    
044            /**
045             * プラãƒ?ƒˆフォーãƒ?¾�存ã?ãƒ?ƒ•ォルトã? Charset ですã?
046             * プラãƒ?ƒˆフォーãƒ?¾�存æ?をè?慮する場合ã?エンコード指定で作æ?しておく事をお勧めしますã?
047             *
048             * @og.rev 5.5.2.6 (2012/05/25) findbugs対å¿?
049             */
050            private static final Charset DEFAULT_CHARSET = Charset.defaultCharset() ;
051    
052            // 注意:秘å¯?‚­ーはã€?¼˜ã?倍数でなã�?�¨ã�?�‘なã�??
053            private static final String HYBS_CRYPT_KEY = "2a5a88891d37ae59" ;
054    
055            /**
056             * å†?ƒ¨設定ã?秘å¯?�µを使用して?Œ暗号化を行うオブジェクトを構築しますã?
057             * ここでの暗号化ã?、Java標準ã?セキュリãƒ?‚£パッケージを使用してã�?�¾すã?
058             */
059            public HybsCryptography() {
060    //              sksSpec = new SecretKeySpec( HYBS_CRYPT_KEY.getBytes(), CIPHER_TYPE );
061                    sksSpec = new SecretKeySpec( HYBS_CRYPT_KEY.getBytes( DEFAULT_CHARSET ), CIPHER_TYPE );         // 5.5.2.6 (2012/05/25) findbugs対å¿?
062            }
063    
064            /**
065             * 秘å¯?�µのæ–?­—å?を受け取って?Œ暗号化を行うオブジェクトを構築しますã?
066             * ここでの暗号化ã?、Java標準ã?セキュリãƒ?‚£パッケージを使用してã�?�¾すã?
067             * 秘å¯?�µのサイズをã?8 の倍数 (32 以ä¸?448 以ä¸? にするå¿?¦�がありますã?
068             *
069             * @param       cryptKey        暗号化を行う秘å¯?�µ
070             */
071            public HybsCryptography( final String cryptKey ) {
072    //              sksSpec = new SecretKeySpec( cryptKey.getBytes(), CIPHER_TYPE );
073                    sksSpec = new SecretKeySpec( cryptKey.getBytes( DEFAULT_CHARSET ), CIPHER_TYPE );               // 5.5.2.6 (2012/05/25) findbugs対å¿?
074            }
075    
076            /**
077             * セキュリãƒ?‚£カラãƒ??DBTyepに対してHybs独自の暗号化を行いますã?
078             * 暗号化されたãƒ??タはã€??常 byte æ–?­—ですがã€?¼‘6é?数アスキーæ–?­—å?に変換
079             * したもã?を返しますã?
080             * こã?暗号化では、引数ã�?null の場合ã?、ゼロæ–?­—å?を返しますã?
081             *
082             * @param       org     暗号化を行うå…??æ–?­—å?
083             *
084             * @return      暗号化されたæ–?­—å?(HEXADECIMALåŒ?
085             */
086            public String encrypt( final String org ) {
087                    if( org == null || org.length() == 0 ) { return ""; }
088    
089                    try {
090                            Cipher cipher = Cipher.getInstance( CIPHER_TYPE );
091                            cipher.init( Cipher.ENCRYPT_MODE, sksSpec );
092    //                      byte[] encrypted = cipher.doFinal( org.getBytes() );
093                            byte[] encrypted = cipher.doFinal( org.getBytes( DEFAULT_CHARSET ) );           // 5.5.2.6 (2012/05/25) findbugs対å¿?
094    
095                            return byte2hexa( encrypted );
096                    }
097                    catch( javax.crypto.IllegalBlockSizeException   ex ) { throw new RuntimeException( ex ); }
098                    catch( java.security.InvalidKeyException                ex ) { throw new RuntimeException( ex ); }
099                    catch( java.security.NoSuchAlgorithmException   ex ) { throw new RuntimeException( ex ); }
100                    catch( javax.crypto.BadPaddingException                 ex ) { throw new RuntimeException( ex ); }
101                    catch( javax.crypto.NoSuchPaddingException              ex ) { throw new RuntimeException( ex ); }
102            }
103    
104            /**
105             * セキュリãƒ?‚£カラãƒ??DBTyepに対してHybs独自の復号化を行いますã?
106             * ここでの復号化ã?、encrypt で暗号化されたæ–?­—を戻すå?合に使用しますã?
107             * こã?復号化では、null は復号化できなã�?�Ÿめã?ゼロæ–?­—å?を返しますã?
108             *
109             * @param       hex     復号化を行う暗号化された?‘6é?数アスキーæ–?­—å?
110             *
111             * @return      復号化されたå…??æ–?­—å?
112             */
113            public String decrypt( final String hex ) {
114                    if( hex == null || hex.length() == 0 ) { return ""; }
115    
116                    try {
117                            Cipher cipher = Cipher.getInstance( CIPHER_TYPE );
118                            cipher.init( Cipher.DECRYPT_MODE, sksSpec );
119                            byte[] encrypted = hexa2byte( hex );
120                            byte[] decrypted = cipher.doFinal( encrypted );
121    //                      return new String( decrypted );
122                            return new String( decrypted,DEFAULT_CHARSET );         // 5.5.2.6 (2012/05/25) findbugs対å¿?
123                    }
124                    catch( javax.crypto.IllegalBlockSizeException   ex ) { throw new RuntimeException( ex ); }
125                    catch( java.security.InvalidKeyException                ex ) { throw new RuntimeException( ex ); }
126                    catch( java.security.NoSuchAlgorithmException   ex ) { throw new RuntimeException( ex ); }
127                    catch( javax.crypto.BadPaddingException                 ex ) { throw new RuntimeException( ex ); }
128                    catch( javax.crypto.NoSuchPaddingException              ex ) { throw new RuntimeException( ex ); }
129            }
130            /**
131             * 数字から16é?æ–?­—に変換するãƒ??ブルですã?
132             */
133            private static final char[] hexadecimal =
134                    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
135                      'a', 'b', 'c', 'd', 'e', 'f' };
136    
137            /**
138             * バイトé?列を?‘6é?数アスキーæ–?­—å?に変換しますã?
139             *
140             * バイトé?列をã€?¼’文字ã?0??,a?žï½??アスキーに変換されますã?
141             * これにより、すべてのæ–?­—を、アスキー化できますã?
142             * アスキー化で、上位が0F以下ã?場合でもã?0 をå?すことで、固定長に変換しますã?
143             *
144             * よって、å?力バイトã??’å?のlength()を持ったStringを作æ?しますã?
145             *
146             * @param       input バイトé?åˆ?
147             *
148             * @return      ?‘6é?数アスキーæ–?­—å?
149             */
150            public static String byte2hexa( final byte[] input ) {
151                    String rtn = null;
152                    if( input != null ) {
153                            int len = input.length ;
154                            char[] ch = new char[len*2];
155                            for( int i=0; i<len; i++ ) {
156                                    int high = ((input[i] & 0xf0) >> 4);
157                                    int low  = (input[i] & 0x0f);
158                                    ch[i*2]   = hexadecimal[high];
159                                    ch[i*2+1] = hexadecimal[low];
160                            }
161                            rtn =  new String(ch);
162                    }
163                    return rtn;
164            }
165    
166            /**
167             * ?‘6é?数アスキーæ–?­—å?をバイトé?列に変換しますã?
168             *
169             * ?’文字ã?0??,a?žï½??アスキーæ–?­—å?をã?バイトé?列に変換されますã?
170             *
171             * よって、å?力Stringの???’å?のlengthを持ったバイトé?列を作æ?しますã?
172             *
173             * @param       input ?‘6é?数アスキーæ–?­—å?
174             *
175             * @return      バイトé?åˆ?
176             */
177            public static byte[] hexa2byte( final String input ) {
178                    byte[] rtn = null;
179                    if( input != null ) {
180                            int len = input.length() ;
181                            rtn = new byte[len/2];
182                            for( int i=0; i<len/2; i++ ) {
183                                    char ch = input.charAt( i*2 );
184                                    int high = ( ch < 'a' ) ? ch-'0' : ch-'a'+10 ;
185                                    ch = input.charAt( i*2+1 );
186                                    int low  = ( ch < 'a' ) ? ch-'0' : ch-'a'+10 ;
187                                    rtn[i] = (byte)(high << 4 | low);
188                            }
189                    }
190                    return rtn;
191            }
192    
193            /**
194             * MessageDigestにより、MD5 でハッシュしたæ–?­—に変換しますã?
195             *
196             * MD5でã€?¼‘6Byteのバイトに変換されますが、ここではã€?del>マイナス時には,
197             * 符号を反転させてã€?/del>?‘6é?数でæ–?­—å?に変換してã�?�¾すã?
198             * <del>よって、このメソãƒ?ƒ‰で変換したæ–?­—でのみ突き合わせて正しいかどã�?�‹ã‚?
199             * 判断してくださいã€?/del>
200             *
201             * 変換方法ã?、各バイトã?上ä½?下位を?‘6é?æ–?­—å?に変換後ã?連結してã�?�¾すã?
202             * これは、Tomcat等ã? digest 認証(MD5使用æ™?と同じ変換方式ですã?
203             * 連結後ã?æ–?­—å?長はã€?¼“2バイãƒ?固å®?になりますã?
204             *
205             * @og.rev 5.2.2.0 (2010/11/01) util.StringUtil から移å‹?
206             *
207             * @param       input 変換前ã?æ–?­—å?
208             *
209             * @return      MD5でハッシュしたæ–?­—å?。32バイãƒ?固å®?
210             */
211            public static String getMD5( final String input ) {
212                    String rtn = null;
213                    if( input != null ) {
214                            try {
215                                    MessageDigest md5 = MessageDigest.getInstance( "MD5" );
216    //                              md5.update( input.getBytes() );
217                                    md5.update( input.getBytes( DEFAULT_CHARSET ) );        // 5.5.2.6 (2012/05/25) findbugs対å¿?
218                                    byte[] out = md5.digest();
219                                    rtn = byte2hexa( out );
220                            }
221                            catch( NoSuchAlgorithmException ex ) {
222                                    String errMsg = "MessageDigestで失敗しましたã€?" + input + "]"
223                                                            + ex.getMessage() ;
224                                    throw new RuntimeException( errMsg,ex );
225                            }
226                    }
227                    return rtn;
228            }
229    
230            /**
231             * 暗号化ã?ãƒ?‚¹トを行う為のメインメソãƒ?ƒ‰
232             *
233             * java HybsCryptography KEY TEXT で起動しますã?
234             *   KEY  : 秘å¯?�µ(8 の倍数 (32 以ä¸?448 以ä¸?æ–?­?
235             *   TEXT : 変換するæ–?­—å?
236             *
237             * @og.rev 5.2.2.0 (2010/11/01) 循環参ç?の解æ¶?LogWriter 削除)
238             *
239             * @param       args    引数配å?
240             */
241            public static void main( final String[] args ) throws Exception {
242                    if( args.length != 2 ) {
243    //                      LogWriter.log( "java HybsCryptography KEY TEXT" );
244    //                      LogWriter.log( "  KEY  : 秘å¯?�µ(8 の倍数 (32 以ä¸?448 以ä¸?æ–?­?" );
245    //                      LogWriter.log( "  TEXT : 変換するæ–?­—å?" );
246                            System.out.println( "java HybsCryptography KEY TEXT" );
247                            System.out.println( "  KEY  : 秘å¯?�µ(8 の倍数 (32 以ä¸?448 以ä¸?æ–?­?" );
248                            System.out.println( "  TEXT : 変換するæ–?­—å?" );
249                            return;
250                    }
251    
252                    HybsCryptography cript = new HybsCryptography( args[0] );
253    
254                    System.out.println( "IN   TEXT : " + args[1] );
255    
256                    String hexa = cript.encrypt( args[1] );
257                    System.out.println( "HEXA TEXT : " + hexa );
258    
259                    String data = cript.decrypt( hexa );
260                    System.out.println( "OUT  DATA : " + data );
261            }
262    }