Android ローカルファイルは、バイナリで。。

先日書いたAndroid ローカルファイルへMapデータ保存は、Google GSONJSON 形式データだった。
暗号化&バイナリでの保存の方がより解読しにくいであろうから、
JSON ではなく Mapのシリアライズから、暗号化してバイナリで保存しようと考えた。

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.content.Context;
import android.content.ContextWrapper;
/**
 * PrivateStorage.  Map データ→暗号化ローカルファイル管理
 * ファイルの更新 commit() を実行すること
 */

public final class PrivateStorage extends ContextWrapper{
   private static PrivateStorage inst;
   private Map<String,String> map;
   private Criptor criptor;
   private String filename = "app.dat";
   public PrivateStorage(Context base){
      super(base);
      criptor = new Criptor();
      map = new HashMap<String,String>();
      load();
   }
   /**
    * インスタンス取得
    * @param base Context
    * @return PrivateStorage
    */

   public static synchronized PrivateStorage getInstance(Context base){
      if (inst==null){
         inst = new PrivateStorage(base);
      }
      return inst;
   }
   /**
    * キーによる値取得
    * @param key String
    * @return value
    */

   public String get(String key){
      return map.get(key);
   }
   /**
    * key-value 格納
    * @param key String
    * @param value String
    */

   public void put(String key,String value){
      map.put(key,value);
   }
   /**
    * ローカルファイル削除
    */

   public void deleteAll(){
      try{
      deleteFile(filename);
      map.clear();
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }
   /**
    * @return Key Setの参照
    */

   public Set<String> keySet(){
      return map.keySet();
   }
   /**
    * ローカルファイル更新
    */

   public void commit(){
      try{
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      ObjectOutputStream os = new ObjectOutputStream(bos);
      os.writeObject(map);
      os.flush();
      os.close();
      bos.close();
      OutputStream out = openFileOutput(filename,MODE_PRIVATE);
      out.write(criptor.encrypt(bos.toByteArray()));
      out.close();
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }
   /**
    * ローカルファイル読込
    */

   @SuppressWarnings("unchecked")
   public void load(){
      map.clear();
      try{
      FileInputStream inputStream = openFileInput(filename);
      int len = inputStream.available();
      if (len > 0){
         BufferedInputStream stream = new BufferedInputStream(inputStream);
         byte b = new byte[len];
         stream.read(b);
         map.clear();
         ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(criptor.decrypt(b)));
         map = (HashMap<String,String>)is.readObject();
         is.available();
         stream.close();
      }
      inputStream.close();
      }catch(Exception e){
      }
   }
   //------------------------------------------------------
   class Criptor{
      /** 128-bit;16byte の鍵 */
      protected String key = "abcdefg123456789";
      /** 初期化ベクトル 16byte */
      protected String initvecor = "0123456789ABCDEF";
      private Key secretKey;
      private AlgorithmParameterSpec ivParamSpec;

      public Criptor(){
         byte
 keybyte = key.getBytes();
         this.secretKey = new SecretKeySpec(keybyte,"AES");
         byte vector = initvecor.getBytes();
         this.ivParamSpec = new IvParameterSpec(vector);
      }
      public final byte
 encrypt(byte data){
         try{
         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
         cipher.init(Cipher.ENCRYPT_MODE,this.secretKey,this.ivParamSpec);
         byte
 iv = cipher.getIV();
         byte enc = cipher.doFinal(data);
         byte
 bs = new byte[iv.length + enc.length];
         System.arraycopy(iv,0,bs,0,iv.length);
         System.arraycopy(enc,0,bs,iv.length,enc.length);
         return bs;
         }catch(Exception e){
            throw new RuntimeException(e);
         }
      }
      public final byte decrypt(byte data){
         try{
         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
         cipher.init(Cipher.DECRYPT_MODE,this.secretKey,this.ivParamSpec);
         int blocksize = cipher.getBlockSize();
         return cipher.doFinal(data,blocksize,data.length - blocksize);
         }catch(Exception e){
            throw new RuntimeException(e);
         }
      }
   }

}