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 */
016package org.opengion.fukurou.security;
017
018import java.io.File;
019import java.io.FileInputStream;
020import java.io.InputStream;                                                                     // 5.10.9.0 (2019/03/01)
021import java.io.IOException;
022import java.nio.ByteBuffer;                                                                     // 5.5.2.6 (2012/05/25)
023import java.nio.channels.FileChannel;                                           // 5.7.2.1 (2014/01/17)
024import java.nio.charset.Charset;                                                        // 5.5.2.6 (2012/05/25)
025import org.opengion.fukurou.system.Closer;                                      // 5.5.2.6 (2012/05/25)
026import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
027import org.opengion.fukurou.model.FileOperation;                        // 5.10.9.0 (2019/03/01)
028import static org.opengion.fukurou.system.HybsConst.CR;         // 8.1.2.0 (2022/03/10)
029
030
031import javax.crypto.spec.SecretKeySpec;
032import javax.crypto.Cipher;
033
034import java.security.MessageDigest;
035import java.security.NoSuchAlgorithmException;
036import java.security.GeneralSecurityException;                          // 5.7.2.1 (2014/01/17)
037import java.security.DigestInputStream;                                         // 5.10.9.0 (2019/03/01)
038
039/**
040 * HybsCryptography は、セキュリティ強化の為の Hybs独自の暗号化クラスです。
041 *
042 * このクラスは、暗号化キーを受け取り、それに基づいて暗号化/復号化を行います。
043 * ここでの暗号化は、秘密キー方式でバイト文字列に変換されたものを、16進アスキー文字に
044 * 直して、扱っています。よって、暗号化/復号化共に、文字列として扱うことが可能です。
045 *
046 * @og.rev 4.0.0.0 (2005/08/31) 新規追加
047 * @og.rev 5.9.10.0 (2019/03/01) クラウドストレージ対応を追加。(Fileクラスを拡張)
048 *
049 * @og.group ライセンス管理
050 *
051 * @version  4.0
052 * @author   Kazuhiko Hasegawa
053 * @since    JDK5.0,
054 */
055public final class HybsCryptography {
056        private final SecretKeySpec sksSpec ;
057        private static final String CIPHER_TYPE = "Blowfish" ;
058
059        /**
060         * 数字から16進文字に変換するテーブルです。
061         */
062        private static final char[] HEXA_DECIMAL =
063                { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
064                  'a', 'b', 'c', 'd', 'e', 'f' };
065
066        /**
067         * プラットフォーム依存のデフォルトの Charset です。
068         * プラットフォーム依存性を考慮する場合、エンコード指定で作成しておく事をお勧めします。
069         *
070         * @og.rev 5.5.2.6 (2012/05/25) findbugs対応
071         */
072        private static final Charset DEFAULT_CHARSET = Charset.defaultCharset() ;
073
074        // 注意:秘密キーは、8の倍数でないといけない。
075        private static final String HYBS_CRYPT_KEY = "2a5a88891d37ae59" ;
076
077        /**
078         * 内部設定の秘密鍵を使用して,暗号化を行うオブジェクトを構築します。
079         * ここでの暗号化は、Java標準のセキュリティパッケージを使用しています。
080         *
081         * @og.rev 6.2.5.0 (2015/06/05) 引数付コンストラクタを使用
082         */
083        public HybsCryptography() {
084                this( HYBS_CRYPT_KEY );
085        }
086
087        /**
088         * 秘密鍵の文字列を受け取って,暗号化を行うオブジェクトを構築します。
089         * ここでの暗号化は、Java標準のセキュリティパッケージを使用しています。
090         * 秘密鍵のサイズを、8 の倍数 (32 以上 448 以下) にする必要があります。
091         *
092         * @og.rev 5.8.8.0 (2015/06/05) null時の挙動はデフォルトキーを利用する
093         *
094         * @param       cryptKey        暗号化を行う秘密鍵
095         */
096        public HybsCryptography( final String cryptKey ) {
097                // 5.8.8.0 (2015/06/05) null時はデフォルトキーを利用
098                final String useKey;
099                if( cryptKey == null || cryptKey.length() == 0 ){
100                        useKey = HYBS_CRYPT_KEY;
101                }
102                else{
103                        useKey = cryptKey;
104                }
105                sksSpec = new SecretKeySpec( useKey.getBytes( DEFAULT_CHARSET ), CIPHER_TYPE );
106        }
107
108        /**
109         * セキュリティカラムのDBTyepに対してHybs独自の暗号化を行います。
110         * 暗号化されたデータは、通常 byte 文字ですが、16進数アスキー文字列に変換
111         * したものを返します。
112         * この暗号化では、引数が null の場合は、ゼロ文字列を返します。
113         *
114         * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます。
115         *
116         * @param       org     暗号化を行う元の文字列
117         *
118         * @return      暗号化された文字列(HEXADECIMAL化)
119         * @og.rtnNotNull
120         */
121        public String encrypt( final String org ) {
122                if( org == null || org.isEmpty() ) { return ""; }
123
124                try {
125                        final Cipher cipher = Cipher.getInstance( CIPHER_TYPE );
126                        cipher.init( Cipher.ENCRYPT_MODE, sksSpec );
127                        final byte[] encrypted = cipher.doFinal( org.getBytes( DEFAULT_CHARSET ) );             // 5.5.2.6 (2012/05/25) findbugs対応
128
129                        return byte2hexa( encrypted );
130                }
131                // 5.7.2.1 (2014/01/17) Exceptionをまとめます。
132                catch( final GeneralSecurityException   ex ) {
133                        final String errMsg = "暗号化処理に失敗しました。[" + org + "]"
134                                                        + ex.getMessage() ;
135                        throw new OgRuntimeException( errMsg,ex );
136                }
137        }
138
139        /**
140         * セキュリティカラムのDBTyepに対してHybs独自の復号化を行います。
141         * ここでの復号化は、encrypt で暗号化された文字を戻す場合に使用します。
142         * この復号化では、null は復号化できないため、ゼロ文字列を返します。
143         *
144         * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます。
145         *
146         * @param       hex     復号化を行う暗号化された16進数アスキー文字列
147         *
148         * @return      復号化された元の文字列
149         * @og.rtnNotNull
150         */
151        public String decrypt( final String hex ) {
152                if( hex == null || hex.isEmpty() ) { return ""; }
153
154                try {
155                        final Cipher cipher = Cipher.getInstance( CIPHER_TYPE );
156                        cipher.init( Cipher.DECRYPT_MODE, sksSpec );
157                        final byte[] encrypted = hexa2byte( hex );
158                        final byte[] decrypted = cipher.doFinal( encrypted );
159                        return new String( decrypted,DEFAULT_CHARSET );         // 5.5.2.6 (2012/05/25) findbugs対応
160                }
161                // 5.7.2.1 (2014/01/17) Exceptionをまとめます。
162                catch( final GeneralSecurityException   ex ) {
163                        final String errMsg = "復号化処理に失敗しました。[" + hex + "]"
164                                                        + ex.getMessage() ;
165                        throw new OgRuntimeException( errMsg,ex );
166                }
167        }
168
169        /**
170         * バイト配列を16進数アスキー文字列に変換します。
171         *
172         * バイト配列を、2文字の0~9,a~fのアスキーに変換されます。
173         * これにより、すべての文字を、アスキー化できます。
174         * アスキー化で、上位が0F以下の場合でも、0 を出すことで、固定長に変換します。
175         *
176         * よって、入力バイトの2倍のlength()を持ったStringを作成します。
177         *
178         * @param       input バイト配列
179         *
180         * @return      16進数アスキー文字列
181         */
182        public static String byte2hexa( final byte[] input ) {
183                String rtn = null;
184                if( input != null && input.length > 0 ) {
185                        final int len = input.length ;
186                        char[] ch = new char[len*2];
187                        for( int i=0; i<len; i++ ) {
188                                final int high = (input[i] & 0xf0) >> 4 ;
189                                final int low  = input[i] & 0x0f ;
190                                ch[i*2]   = HEXA_DECIMAL[high];
191                                ch[i*2+1] = HEXA_DECIMAL[low];
192                        }
193                        rtn =  new String(ch);
194                }
195                return rtn;
196        }
197
198        /**
199         * 16進数アスキー文字列をバイト配列に変換します。
200         *
201         * 2文字の0~9,a~fのアスキー文字列を、バイト配列に変換されます。
202         *
203         * よって、入力Stringの1/2倍のlengthを持ったバイト配列を作成します。
204         *
205         * @param       input 16進数アスキー文字列
206         *
207         * @return      バイト配列
208         */
209        public static byte[] hexa2byte( final String input ) {
210                byte[] rtn = null;
211                if( input != null ) {
212                        final int len = input.length() ;
213                        rtn = new byte[len/2];
214                        for( int i=0; i<len/2; i++ ) {
215                                char ch = input.charAt( i*2 );
216                                final int high = ch < 'a' ? ch-'0' : ch-'a'+10 ;
217                                ch = input.charAt( i*2+1 );
218                                final int low  = ch < 'a' ? ch-'0' : ch-'a'+10 ;
219                                rtn[i] = (byte)(high << 4 | low);
220                        }
221                }
222                return rtn;
223        }
224
225        /**
226         * MessageDigestにより、システム定数に定義されている ハッシュコード で
227         * ハッシュした文字に変換します。
228         *
229         * 連結後の文字列長は、ハッシュコードにより異なります。
230         *
231         * @og.rev 8.1.2.0 (2022/03/10) getMD5参照して新規作成
232         *
233         * @param       hashCode        ハッシュコード (MD5, SHA-1, SHA-256, SHA-512)
234         * @param       input           変換前の文字列
235         *
236         * @return      ハッシュコードでハッシュした文字列
237         */
238        public static String getHash( final String hashCode, final String input ) {
239                String rtn = null;
240                if( hashCode != null && input != null ) {
241                        try {
242                                final MessageDigest md = MessageDigest.getInstance( hashCode );
243                                md.update( input.getBytes( DEFAULT_CHARSET ) );                         // 5.5.2.6 (2012/05/25) findbugs対応
244                                final byte[] out = md.digest();
245                                rtn = byte2hexa( out );
246                        }
247                        catch( final NoSuchAlgorithmException ex ) {
248                                final String errMsg = "MessageDigestで失敗しました。" + CR
249                                                        + "ハッシュコード=[" + hashCode + "] , 変換前=[" + input + "]" + CR
250                                                        + ex.getMessage() ;
251                                throw new OgRuntimeException( errMsg,ex );
252                        }
253                }
254                return rtn;
255        }
256
257        /**
258         * MessageDigestにより、システム定数に定義されている ハッシュコード で
259         * ハッシュした文字に変換します。
260         *
261         * 連結後の文字列長は、ハッシュコードにより異なります。
262         *
263         * @og.rev 8.1.2.0 (2022/03/10) getMD5参照して新規作成
264         *
265         * @param       hashCode        ハッシュコード (MD5, SHA-1, SHA-256, SHA-512)
266         * @param       input           変換前のFileOperationオブジェクト
267         *
268         * @return      ハッシュコードでハッシュした文字列
269         */
270        public static String getHash( final String hashCode, final FileOperation input ) {
271                String rtn = null;
272                if( hashCode != null && input != null ) {
273                        InputStream is = null;
274                        DigestInputStream dis = null;
275                        try {
276                                final MessageDigest md = MessageDigest.getInstance( hashCode );
277                                is = input.read();
278                                dis = new DigestInputStream(is, md);
279
280                                final byte[] readBuf = new byte[1024];
281                                while(dis.read(readBuf) > 0) {
282                                        ;       // disを読み込んで、ダイジェスト情報を更新
283                                }
284
285                                // ダイジェスト情報を取得
286                                final byte[] out = md.digest();
287                                rtn = byte2hexa( out );
288                        }
289                        catch( NoSuchAlgorithmException ex ) {
290                                final String errMsg = "MessageDigestで失敗しました。" + CR
291                                                        + "ハッシュコード=[" + hashCode + "] , 変換前=[" + input + "]" + CR
292                                                        + ex.getMessage() ;
293                                throw new RuntimeException( errMsg,ex );
294                        }
295                        catch( IOException ex ) {
296                                final String errMsg = "ファイルの読み取りを失敗しました。[" + input + "]"
297                                                        + ex.getMessage() ;
298                                throw new RuntimeException( errMsg,ex );
299                        }
300                        finally {
301                                Closer.ioClose(dis);
302                                Closer.ioClose(is);
303                        }
304                }
305                return rtn;
306        }
307
308        /**
309         * MessageDigestにより、システム定数に定義されている ハッシュコード で
310         * ハッシュした文字に変換します。
311         *
312         * 連結後の文字列長は、ハッシュコードにより異なります。
313         *
314         * @og.rev 8.1.2.0 (2022/03/10) getMD5参照して新規作成
315         *
316         * @param       hashCode        ハッシュコード (MD5, SHA-1, SHA-256, SHA-512)
317         * @param       input           変換前のFile
318         *
319         * @return      ハッシュコードでハッシュした文字列
320         */
321        public static String getHash( final String hashCode, final File input ) {
322                // 2019/X FileOperationクラスの場合は、クラウドストレージ対応のメソッドを実行します。 oota tmp
323                if( input instanceof FileOperation ) {
324                        return getHash( hashCode, (FileOperation)input );
325                }
326
327                String rtn = null;
328                if( hashCode != null && input != null ) {
329                        FileInputStream fis     = null;
330                        FileChannel             fc      = null;
331                        try {
332                                final MessageDigest md = MessageDigest.getInstance( hashCode );
333                                fis = new FileInputStream( input );
334                                fc  =fis.getChannel();
335                                final ByteBuffer bb = fc.map( FileChannel.MapMode.READ_ONLY , 0L , fc.size() );
336                                md.update( bb );
337                                final byte[] out = md.digest();
338                                rtn = byte2hexa( out );
339                        }
340                        catch( final NoSuchAlgorithmException ex ) {
341                                final String errMsg = "MessageDigestで失敗しました。" + CR
342                                                        + "ハッシュコード=[" + hashCode + "] , 変換前=[" + input + "]" + CR
343                                                        + ex.getMessage() ;
344                                throw new OgRuntimeException( errMsg,ex );
345                        }
346                        catch( final IOException ex ) {
347                                final String errMsg = "ファイルの読み取りを失敗しました。[" + input + "]"
348                                                        + ex.getMessage() ;
349                                throw new OgRuntimeException( errMsg,ex );
350                        }
351                        finally {
352                                Closer.ioClose( fc );
353                                Closer.ioClose( fis );
354                        }
355                }
356                return rtn;
357        }
358
359        // 8.1.2.0 (2022/03/10) Delete
360//      /**
361//       * MessageDigestにより、MD5 でハッシュした文字に変換します。
362//       *
363//       * MD5で、16Byteのバイトに変換されますが、ここでは、16進数で文字列に変換しています。
364//       *
365//       * 変換方法は、各バイトの上位/下位を16進文字列に変換後、連結しています。
366//       * これは、Tomcat等の digest 認証(MD5使用時)と同じ変換方式です。
367//       * 連結後の文字列長は、32バイト(固定)になります。
368//       *
369//       * @og.rev 5.2.2.0 (2010/11/01) util.StringUtil から移動
370//       *
371//       * @param       input 変換前の文字列
372//       *
373//       * @return      MD5でハッシュした文字列。32バイト(固定)
374//       */
375//      public static String getMD5( final String input ) {
376//              String rtn = null;
377//              if( input != null ) {
378//                      try {
379//                              final MessageDigest md5 = MessageDigest.getInstance( "MD5" );
380//                              md5.update( input.getBytes( DEFAULT_CHARSET ) );        // 5.5.2.6 (2012/05/25) findbugs対応
381//                              final byte[] out = md5.digest();
382//                              rtn = byte2hexa( out );
383//                      }
384//                      catch( final NoSuchAlgorithmException ex ) {
385//                              final String errMsg = "MessageDigestで失敗しました。[" + input + "]"
386//                                                      + ex.getMessage() ;
387//                              throw new OgRuntimeException( errMsg,ex );
388//                      }
389//              }
390//              return rtn;
391//      }
392
393        // 8.1.2.0 (2022/03/10) Delete
394//      /**
395//       * MessageDigestにより、MD5 でハッシュした文字に変換します。
396//       *
397//       * MD5で、16Byteのバイトに変換されますが、ここでは、16進数で文字列に変換しています。
398//       *
399//       * 変換方法は、各バイトの上位/下位を16進文字列に変換後、連結しています。
400//       * これは、Tomcat等の digest 認証(MD5使用時)と同じ変換方式です。
401//       * 連結後の文字列長は、32バイト(固定)になります。
402//       * 下記サイトを参考に作成しています。
403//       * https://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java
404//       *
405//       * @og.rev 5.9.10.0 (2019/03/01) 新規追加。クラウドストレージ対応。
406//       *
407//       * @param       input 変換前のFileOperationオブジェクト
408//       *
409//       * @return      MD5でハッシュした文字列。32バイト(固定)
410//       */
411//      public static String getMD5( final FileOperation input ) {
412//              String rtn = null;
413//              if( input != null ) {
414//
415//                      InputStream is = null;
416//                      DigestInputStream dis = null;
417//                      try {
418//                              final MessageDigest md5 = MessageDigest.getInstance( "MD5" );
419//                              is = input.read();
420//                              dis = new DigestInputStream(is, md5);
421//
422//                              while(dis.read() > 0) {
423//                                      ;       // disを読み込んで、ダイジェスト情報を更新
424//                              }
425//
426//                              // ダイジェスト情報を取得
427//                              final byte[] out = md5.digest();
428//                              rtn = byte2hexa( out );
429//                      }
430//                      catch( NoSuchAlgorithmException ex ) {
431//                              final String errMsg = "MessageDigestで MD5 インスタンスの作成に失敗しました。[" + input + "]"
432//                                                      + ex.getMessage() ;
433//                              throw new RuntimeException( errMsg,ex );
434//                      }
435//                      catch( IOException ex ) {
436//                              final String errMsg = "ファイルの読み取りを失敗しました。[" + input + "]"
437//                                                      + ex.getMessage() ;
438//                              throw new RuntimeException( errMsg,ex );
439//                      }
440//                      finally {
441//                              Closer.ioClose(dis);
442//                              Closer.ioClose(is);
443//                      }
444//              }
445//              return rtn;
446//      }
447
448        // 8.1.2.0 (2022/03/10) Delete
449//      /**
450//       * MessageDigestにより、MD5 でハッシュした文字に変換します。
451//       *
452//       * MD5で、16Byteのバイトに変換されますが、ここでは、16進数で文字列に変換しています。
453//       *
454//       * 変換方法は、各バイトの上位/下位を16進文字列に変換後、連結しています。
455//       * これは、Tomcat等の digest 認証(MD5使用時)と同じ変換方式です。
456//       * 連結後の文字列長は、32バイト(固定)になります。
457//       *
458//       * @og.rev 5.7.2.1 (2014/01/17) Exceptionをまとめます。
459//       * @og.rev 5.9.10.0 (2019/03/01) クラウドストレージ対応を追加
460//       *
461//       * @param       input 変換前のFile
462//       *
463//       * @return      MD5でハッシュした文字列。32バイト(固定)
464//       */
465//      public static String getMD5( final File input ) {
466//              // 2019/X FileOperationクラスの場合は、クラウドストレージ対応のメソッドを実行します。 oota tmp
467//              if(input instanceof FileOperation) {
468//                      return getMD5((FileOperation)input);
469//              }
470//
471//              String rtn = null;
472//              if( input != null ) {
473//                      FileInputStream fis     = null;
474//                      FileChannel             fc      = null;
475//                      try {
476//                              final MessageDigest md5 = MessageDigest.getInstance( "MD5" );
477//                              fis = new FileInputStream( input );
478//                              fc  =fis.getChannel();
479//                              final ByteBuffer bb = fc.map( FileChannel.MapMode.READ_ONLY , 0L , fc.size() );
480//                              md5.update( bb );
481//                              final byte[] out = md5.digest();
482//                              rtn = byte2hexa( out );
483//                      }
484//                      catch( final NoSuchAlgorithmException ex ) {
485//                              final String errMsg = "MessageDigestで MD5 インスタンスの作成に失敗しました。[" + input + "]"
486//                                                      + ex.getMessage() ;
487//                              throw new OgRuntimeException( errMsg,ex );
488//                      }
489//                      catch( final IOException ex ) {
490//                              final String errMsg = "ファイルの読み取りを失敗しました。[" + input + "]"
491//                                                      + ex.getMessage() ;
492//                              throw new OgRuntimeException( errMsg,ex );
493//                      }
494//                      finally {
495//                              Closer.ioClose( fc );
496//                              Closer.ioClose( fis );
497//                      }
498//              }
499//              return rtn;
500//      }
501
502//      /**
503//       * MessageDigestにより、SHA1 でハッシュした文字に変換します。
504//       *
505//       * 16進数で文字列に変換しています。
506//       *
507//       * 変換方法は、各バイトの上位/下位を16進文字列に変換後、連結しています。
508//       * これは、Tomcat等の digest 認証と同じ変換方式です。
509//       *
510//       * @og.rev 5.9.27.1 (2010/12/08) 新規作成
511//       *
512//       * @param       input 変換前の文字列
513//       *
514//       * @return      SHA1でハッシュした文字列。32バイト(固定)
515//       */
516//      public static String getSHA1( final String input ) {
517//              String rtn = null;
518//              if( input != null ) {
519//                      try {
520//                              final MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
521//                              sha1.update( input.getBytes( DEFAULT_CHARSET ) );
522//                              final byte[] out = sha1.digest();
523//                              rtn = byte2hexa( out );
524//                      }
525//                      catch( final NoSuchAlgorithmException ex ) {
526//                              final String errMsg = "MessageDigestで失敗しました。[" + input + "]"
527//                                                                              + ex.getMessage() ;
528//                              throw new RuntimeException( errMsg,ex );
529//                      }
530//              }
531//              return rtn;
532//      }
533
534        // 8.1.2.0 (2022/03/10) Delete
535//      /**
536//       * MessageDigestにより、SHA-512 でハッシュした文字に変換します。
537//       *
538//       * 16進数で文字列に変換しています。
539//       *
540//       * 変換方法は、各バイトの上位/下位を16進文字列に変換後、連結しています。
541//       * これは、Tomcat等の digest 認証と同じ変換方式です。
542//       *
543//       * @og.rev 5.10.10.2 (2019/04/12) 新規作成
544//       *
545//       * @param       input 変換前の文字列
546//       *
547//       * @return      SHA-512でハッシュした文字列 128バイト
548//       */
549//      public static String getSHA512( final String input ) {
550//              String rtn = null;
551//              if( input != null ) {
552//                      try {
553//                              final MessageDigest sha1 = MessageDigest.getInstance("SHA-512");
554//                              sha1.update( input.getBytes( DEFAULT_CHARSET ) );
555//                              final byte[] out = sha1.digest();
556//                              rtn = byte2hexa( out );
557//                      }
558//                      catch( final NoSuchAlgorithmException ex ) {
559//                              final String errMsg = "MessageDigestで失敗しました。[" + input + "]"
560//                                                      + ex.getMessage() ;
561//                              throw new RuntimeException( errMsg,ex );
562//                      }
563//              }
564//              return rtn;
565//      }
566
567        /**
568         * 暗号化のテストを行う為のメインメソッド
569         *
570         * java HybsCryptography KEY TEXT で起動します。
571         *   KEY  : 秘密鍵(8 の倍数 (32 以上 448 以下)文字)
572         *   TEXT : 変換する文字列
573         *
574         * @og.rev 5.2.2.0 (2010/11/01) 循環参照の解消(LogWriter 削除)
575         *
576         * @param       args    引数配列
577         */
578        public static void main( final String[] args ) {
579                if( args.length != 2 ) {
580                        System.out.println( "java HybsCryptography KEY TEXT" );
581                        System.out.println( "  KEY  : 秘密鍵(8 の倍数 (32 以上 448 以下)文字)" );
582                        System.out.println( "  TEXT : 変換する文字列" );
583                        return;
584                }
585
586                final HybsCryptography cript = new HybsCryptography( args[0] );
587
588                System.out.println( "IN   TEXT : " + args[1] );
589
590                final String hexa = cript.encrypt( args[1] );
591                System.out.println( "HEXA TEXT : " + hexa );
592
593                final String data = cript.decrypt( hexa );
594                System.out.println( "OUT  DATA : " + data );
595        }
596}