- PR -

復号化時のdoFinalについて

投稿者投稿内容
fuzuki
常連さん
会議室デビュー日: 2003/08/23
投稿数: 48
投稿日時: 2003-10-07 01:06
こんにちは。ご返事ありがとうございます。

Wataさんが教えてくださった方法でStringにダンプしてやってみたのですが、最後にそのStringをgetBytes()で再度byte配列に変換してdoFinal()を行ったところでやはり同様のエラーになってしまいます。

String sendData = s.dump(ciphertext, 2);
byte[] receiveText = sendData.getBytes();
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
byte[] decriptedText = pbeCipher.doFinal(receiveText);

dumpのメソッド内でtoStringに奇数を与える場合、何を引数にするべきか分からないのでとりあえず2にしておきました。これはどのような数字でも見た目変わってないようなのですが。
String→byte[]への変換はgetBytes()で行っても問題ないでしょうか?

なんとかjavaだけを使用して暗号化した文をソケットを通してクライアントに送って、それを解読したいのですが、こういうことをする人があまりいないからなのか分かりませんが、このようなことを解説しているページはあまり無くて困っています。どこかそのようなページをご存知でしたら教えていただけないでしょうか?
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2003-10-07 02:09
fuzukiさん、こんにちは。

暗号化、復号化の問題は、6日の13時半には解決しているようです。

今、fuzukiさんが抱えている問題は、もはや暗号化とは直接関係なく、
バイナリのデータをどのようにしてクライアント・サーバ間で交換
するかということのようですね。
wataさんが言うように、暗号化したバイト列は文字ではないのですから。
(別にスレッドを新しくするべきだといっているのではありません。)

ところで fuzukiさん、確認ですが、
本件のC/S通信では文字列を使う必要があるのですね?(バイナリは
使用不可?)

さて、バイナリをテキストとして扱う方法には幾つかあるのをご存知だ
と思いますが、単純な 16進ダンプを使うという手があります。
Java Mail, J2EEや Jigsawなどが使えるなら、Base64がお勧めです。

# 私はよく、uuencode使いますが… お勧めはしません。
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-10-07 09:44
こんにちは、Wataです。別スレッドを立てるべきなのかもしれませんが...。

引用:

fuzukiさんの書き込み (2003-10-07 01:06) より:
Wataさんが教えてくださった方法でStringにダンプしてやってみたのですが、最後にそのStringをgetBytes()で再度byte配列に変換してdoFinal()を行ったところでやはり同様のエラーになってしまいます。


すみません。逆変換の方を書き忘れました。
しかも、もっぱらUnitテストやデバッグに使ってたので、
逆変換にはあまり向いてなかったりして...。

引用:

dumpのメソッド内でtoStringに奇数を与える場合、何を引数にするべきか分からないのでとりあえず2にしておきました。これはどのような数字でも見た目変わってないようなのですが。
String→byte[]への変換はgetBytes()で行っても問題ないでしょうか?


基数を2にした場合は、出力される文字列は'0'と'1'の2進表現になります。
16を指定すれば、16進ダンプです。
java.lang.Character#MAX_RADIXの値まで指定できます。
また、String#getBytes()は文字コードのバイト配列を得るメソッドなので、当然ここでは使えません。

ちなみに、BigIntegerを利用したdumpの逆変換は次のようにできます。
コード:

public static byte[] toByteArray(String string, int radix) {
byte[] bytes = new BigInteger(string, radix).toByteArray();

if (bytes.length != 0 && bytes[0] == 0) {
byte[] abs = new byte[bytes.length - 1];
System.arraycopy(bytes, 1, abs, 0, abs.length);
return abs;
}
else {
return bytes;
}
}


可能ならば、Kissingerさんの言うように、Base64などのきちっとしたものを使うとよいでしょう。

# バグ修正。あと、さきのdumpメソッドも同様ですが、先頭が0だとバイトが失われます。
# よって、バイト数が重要な場合は使用しないで下さい。 (^^;
# ていうか使えんね。これ。


[ メッセージ編集済み 編集者: Wata 編集日時 2003-10-07 10:06 ]

[ メッセージ編集済み 編集者: Wata 編集日時 2003-10-07 10:37 ]
fuzuki
常連さん
会議室デビュー日: 2003/08/23
投稿数: 48
投稿日時: 2003-10-08 14:20
こんにちは。
結局、Wataさんの方法でbyte[]->String変換を行うことにしました。C/Sで送受信するデータはStringでなければならないのです。送る文字自体は任意ではなく、何種類かあるだけで、16進ダンプを行ってやってみたところ全ての命令が正常に送受信できましたのでこれで良しとしました。
Dog
常連さん
会議室デビュー日: 2003/10/16
投稿数: 24
投稿日時: 2003-10-16 21:47
はじめまして。
私もfuzukiさんと同じようにパスワードの暗号化、復号化を使用としているのですが、String型とbyte[]型の変換でつまづいています。このスレッドの情報を参考にさせて頂いていて、Wataさんの変換法(BigIntegerを使用)を使おうとしています。

引用:-----------------------------------------------------------------------

public static byte[] toByteArray(String string, int radix) {
byte[] bytes = new BigInteger(string, radix).toByteArray();

if (bytes.length != 0 && bytes[0] == 0) {
byte[] abs = new byte[bytes.length - 1];
System.arraycopy(bytes, 1, abs, 0, abs.length);
return abs;
}
else {
return bytes;
}
}
----------------------------------------------------------------------------
しかしこの方法では英字の大文字と小文字が区別されず、復号したときに全て小文字となってしまいます。
どなたかこれを解決する方法をご存知の方、ご教授願いませんでしょうか?
(本来別スレッドを立てるべき質問内容かも知れませんが・・・)
_________________
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-10-16 23:03
Wataです。
引用:

ビギナーさんの書き込み (2003-10-16 21:47) より:
私もfuzukiさんと同じようにパスワードの暗号化、復号化を使用としているのですが、String型とbyte[]型の変換でつまづいています。このスレッドの情報を参考にさせて頂いていて、Wataさんの変換法(BigIntegerを使用)を使おうとしています。


前にも書きましたが、BigIntegerを使ったいんちき変換は先頭の0がなくなるので、
暗号とかにはあまり使わないほうが...。
(やっぱ本来の目的と違う使い方はしちゃいけないよね )

代わりにもう少し真っ当なものを載せます。
コード:
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();
}

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;
}


16進限定ですが、ちゃんと動くと思います。

引用:

ビギナーさんの書き込み (2003-10-16 21:47) より:
しかしこの方法では英字の大文字と小文字が区別されず、復号したときに全て小文字となってしまいます。


どのような目的で使用するのかわかりませんが、
16進数ので大文字・小文字の区別は必要ないのでは?

もしかして元々Stringのものをbyte配列に変換したいのですか?
だとしたら、String#getBytes(charsetName)でいいのでは?
Dog
常連さん
会議室デビュー日: 2003/10/16
投稿数: 24
投稿日時: 2003-10-17 09:35
こんにちは。
Wataさん丁寧なレスポンスありがとうございます。

引用:

どのような目的で使用するのかわかりませんが、
16進数ので大文字・小文字の区別は必要ないのでは?
もしかして元々Stringのものをbyte配列に変換したいのですか?



そのとおりです。もともとString型のデータをCipherで暗号化するためにbyte[]型に変換しているだけなんです。BigIntegerの基数としてMaxの36を渡す方法で0〜9、a〜zまでは暗号化→複合化してStringに変換できたのですが・・・。この方法自体あまり好ましくないのでしょうか?

引用:

だとしたら、String#getBytes(charsetName)でいいのでは?



String#getBytes(charsetName)を使うと例の「Input length (with padding) not multiple of 8 bytes」というエラーが出てしまうのです。この場合charsetNameは何を用いるのが良いのでしょうか?(←直接関係ないかも知れませんが)
パディングの指定なのですが、Cipherにインスタンスを渡すところで行えるのでしょうか?PKCS5Paddingではだめなのでしょうか?アルゴリズムやモードを変更していろいろ試したのですが上手くいきませんでした。

よろしくお願いします。
(要領を得ない質問で申し訳ございません。)

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