- PR -

暗号化と復号化について

1
投稿者投稿内容
Dog
常連さん
会議室デビュー日: 2003/10/16
投稿数: 24
投稿日時: 2003-10-22 18:03
こんにちは。
以下のクラス(ソースが長くて申し訳ないです)を用いてString型の文字列を暗号化、復号化しようとしています。
しかしこのクラスで暗号化したものを復号化すると文字化けしてしまいます。
このクラスの問題点、もしくは代替案などありましたらご教授下さい。
よろしくお願いいたします。

コード:
public class PasswordCipher{
	public String encrypt(String password) throws Exception{
		try{
			//String-->byte[]
			byte[] btePassword = password.getBytes("Shift_JIS");

			// Salt
			byte[] salt = {
				 (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
				 (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
			};
		 	// Iteration count
			int count = 20;
			PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
						
			char[] pass = "abcdefgh".toCharArray();
			PBEKeySpec pbeKeySpec = new PBEKeySpec(pass);
			SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
			SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

			Cipher descipher = Cipher.getInstance("PBEWithMD5AndDES");
			descipher.init(Cipher.ENCRYPT_MODE,pbeKey,pbeParamSpec);
			//暗号化
			byte[] cipherPassword = descipher.doFinal(btePassword);
			//byte[]-->String
			String strPassword = toHexString(cipherPassword);

			return strPassword;
		}catch(Exception exc){
			//エラー処理
		}
	}
	
	public String decript(String strPassword)throws Exception{
		try{	
			//String-->byte[]
			byte[] cipherPassword = toBytes(strPassword);

			// Salt
			byte[] salt = {
				 (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
				 (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
			};
			// Iteration count
			int count = 20;
			PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);

			char[] pass = "abcdefgh".toCharArray();		
			PBEKeySpec pbeKeySpec = new PBEKeySpec(pass);
			SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
			SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

			Cipher descipher = Cipher.getInstance("PBEWithMD5AndDES");
			descipher.init(Cipher.DECRYPT_MODE,pbeKey,pbeParamSpec);
			//複号化
			byte[] btePassword = descipher.doFinal(cipherPassword);
			
			//byte[]-->String
			String password = new String(cipherPassword,"Shift_JIS");

			return password;
		}catch(Exception exc){
			//エラー処理
		}
	}
	
	//byte[]-->String
  	public static String toHexString(byte[] bs) {

	 	StringBuffer buffer = new StringBuffer(bs.length * 2);
	 	for (int i = 0; i < bs.length; i++) {
			if(bs[i] >= 0 && bs[i]<0x10){
		  		buffer.append('0');
			}
			buffer.append(Integer.toHexString(0xff&bs[i]));
	 	}
		return buffer.toString();
  	}

	//String-->byte[]
  	public static byte[] toBytes(String hexString) throws NumberFormatException{
   
	 	if(hexString.length()%2==1){
			hexString = '0' + hexString;
	 	}
		byte[] bytes = new byte[hexString.length()/2];
	 	for (int i = bytes.length-1; i >= 0; i--) {
			String b = hexString.substring(i*2,i*2+2);
			bytes[i] = (byte)Integer.parseInt(b, 16);
	 	}
	 	return bytes;
  	}
}

Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-10-22 18:37
引用:

ビギナーさんの書き込み (2003-10-22 18:03) より:
コード:
  //byte[]-->String
   String password = new String(cipherPassword,"Shift_JIS");



この行これであってますか?よーく見てみましょう。
ちなみに"Shift_JIS"の部分は概ねあってます。厳密に言うと"Windows-31J"がよいけど。

# いやー恐ろしいバグだ この手のバグは自分じゃ中々気付かない
Gordie
ベテラン
会議室デビュー日: 2003/10/14
投稿数: 64
投稿日時: 2003-10-22 18:56
ちゃちゃ入れですが。

コード:
public String decript(String strPassword)throws Exception{



decriptではなくdecryptです。スペル間違いに注意しませう。それに複号ではなく復号です。
昔、ErrorMassageっていう、とっても痛そうな変数を見つけたことが。

それにしても、パスワードを検証するだけなら復号処理は要りませんよね。
入力されたパスワードを暗号化して、DBに格納されている暗号化パスワードと比較すればいいですから。
#1つの平文から複数パターンの暗号文ができる場合だと復号しないと比較できませんが。


余談の余談ですが、「復号化」という単語はおかしいように思いますがどうでしょう?
「暗号」は名詞なので、暗号にする処理は「暗号化」でいいのですが、
「復号」は暗号文を元に戻すという意味の動詞で、「復号する」などのように使うのが正しいのではないでしょうか。
「暗号化」と対になるのは「平文化」ではないかと。
辞書にも載ってるから「復号化」で正しいということになってるんでしょうけど違和感を感じます。
まあ言葉なんて使われたもの勝ちですが。
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-10-22 19:39
引用:

Gordieさんの書き込み (2003-10-22 18:56) より:
余談の余談ですが、「復号化」という単語はおかしいように思いますがどうでしょう?


私もそう思います。
通ってた大学の教授も暗号をやっていて、さんざん同じ事を聞かされましたから。
Dog
常連さん
会議室デビュー日: 2003/10/16
投稿数: 24
投稿日時: 2003-10-22 19:50
Wataさん、Gordieさんありがとうございます。
解決いたしました。

コード:

//byte[]-->String
String password = new String(btePassword,"Shift_JIS");


上記の通りでした。単純なミスで申し訳ございません。
本当に自分ではなかなか気づかないものです・・・

引用:

それにしても、パスワードを検証するだけなら復号処理は要りませんよね。
入力されたパスワードを暗号化して、DBに格納されている暗号化パスワードと比較すればいいですから。
#1つの平文から複数パターンの暗号文ができる場合だと復号しないと比較できませんが。


そうですね。最初に複数パターンの暗号文ができる方法をとっていたので、復号しないと比較できないと思い込んでいました。ご指摘ありがとうございます。
1

スキルアップ/キャリアアップ(JOB@IT)