スキマハコ

わすれがちなスキマな事を詰め込んでいます。ITの他に暮らしについても書いています。

暗号化/復号化@AES

一日悩んでよーやく!
後から追記しますー

	public byte[] CryptFile(String data,int mode){
		byte[] bytes;
		//暗号化された文字列の取得
		if(mode==1){
			//ファイルから取得
			bytes= ReadFile(data);
		}else{
			//仮引数から取得
			bytes=data.getBytes();
		}
		
		return CryptFile(bytes,mode);
	}
	
	public byte[] CryptFile(byte[] data,int mode){
		byte[] bytes=data;
		 try {
			 // 復号化
			 //byteに変換
			 byte[] bkey=new byte[16];
			 System.out.println(bytes.length);
			 
			//データからキーを取得
			 BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(bytes));
			 bis.read(bkey, 0, 16);
			 
			 //暗号文のみのデータを格納
			 byte[] bytetmp = new byte[bytes.length-16];
			 int ilen = bytetmp.length;
			 bis.read(bytetmp, 0, ilen);
			
			 //鍵生成
			 SecretKeySpec key = new SecretKeySpec(bkey, "AES");

			//引数で指定した暗号化/復号化変換を実装する Cipher オブジェクトを生成
			Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
			//鍵を使用して初期化
			//DECRYPT_MODE:データの暗号解読
			c.init(Cipher.DECRYPT_MODE, key);
			//復号化実行
			bytes=c.doFinal(bytetmp); 
			
			//終了処理
			bis.close();
			
		} catch (Exception e) {
			System.out.println(e);
		}
		return bytes;
	}

	public byte[] EncryptFile(String data,int mode){
		byte[] bytes;
		byte[] bytesres=null;
		//平文文字列の取得
		if(mode==1){
			//ファイルから取得
			bytes= ReadFile(data);
		}else{
			//仮引数から取得
			bytes=data.getBytes();
		}
		 try {
			// 暗号化
			 //引数で指定したアルゴリズムの KeyGenerator オブジェクトを生成。
			 KeyGenerator kg = KeyGenerator.getInstance("AES"); //<-16byte
			 //秘密鍵を生成。
			 Key key= kg.generateKey();
			 // 鍵を一次符号化形式で返す
			 
			 //引数で指定した暗号化/復号化変換を実装する Cipher オブジェクトを生成
			 Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
			 //鍵を使用してこの暗号を初期化
			 //ENCRYPT_MODE:データの暗号化 
			 c.init(Cipher.ENCRYPT_MODE, key);
			 //暗号化実行
			 byte encrypted[] = c.doFinal(bytes); 
			 
			 //暗号化文字列と共通かぎをbyte[]に格納
			 byte[] bytetmp = new byte[encrypted.length+key.getEncoded().length];
			 ByteBuffer bb = ByteBuffer.wrap(bytetmp);
			 bb.put(key.getEncoded());
			 
			 bb.put(encrypted);
			 //共通かぎ+暗号化された文字列
			 bytesres = bb.array();
			 
			 bb.clear();
			 
		 } catch (Exception e) {
			System.out.println(e);

		 }
		 return bytesres;
	}

参考元:http://lab.moyo.biz/recipes/java/security/commonkey.xsp

暗号化するのはやっぱり簡単で、問題だったのは鍵の渡し方。
今回共通かぎ暗号方式で、しかも鍵はファイル内に書き込むタイプにしたかったため(場所は本当はもっと他のデータを基準に暗号文字列内にランダムに設置するけど…今回は頭で)、初めに返す文字は生成した鍵と暗号文字列ともどもnew String(バイト配列)でString文字列に変換してた。
でも復号化で文字列を読み込んで文字列抽出〜とかしても復号化できない・・・。
あと発生する、

  1. バッファに文字列をいれて、読み込もう→文字列オーバーしてるよエラー
  2. 抽出した文字列で復号化→復号する文字列がたりないよエラー

が発生…えええ。
文字列オーバーが発生したのは

//暗号文のみのデータを格納
byte[] bytetmp = new byte[bytes.length-16];
int ilen = bytetmp.length;
bis.read(bytetmp, 0, ilen);

この部分。はじめ、
bis.read(bytetmp, 16, ilen);
ってしていたのが悪かったみたい。
read ≒ readline
ってことを忘れてました。初めに読み取り位置を0にセットして、一回実行するごとにそこまで読み込むのね。
なので配列を大幅に超えてアクセスしてエラーが発生してたよう。

も一つのエラーは、文字足らずらしい。
で、暗号化して鍵とくっつけた後の文字サイズと復号化で読み込んだ時の文字列を比較すると、
サイズが2,3くらい違う。
どうやら型変換で空白か何か分が省略されてしまった?らしい。
そこで返す値をすべてbyte[]でやり取りすることに。
これでなんとか解決〜