2017-05-10 13 views
1

いくつかのオブジェクトを含むArrayListがあります。オブジェクトはログイン/パスのコンテナです。
別の起動後にレクリエーション用にローカルファイルにシリアル化する必要があるため、デコードしようとしています。
問題は、私はjavax.crypto.IllegalBlockSizeException:16バイトの倍数ではない入力長

javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes 
    at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1039) 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:983) 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) 

を受け取ると、私は完全に理由を理解していない暗号化中です。私の意見では、Base64はこれに対処する必要があります。しかし、私はその意味を正しく理解していないかもしれません。私は暗号化に使用
/deccode

public class Move 
{ 
    private static Move instance; 

    String key = "pT5IkWNR90gJo5YM"; 
    String initVector = "RandomInitVector"; 
    Cipher cipher; 


    private Move() 
    { 
//  try 
//  { 
//   cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
//  } 
//  catch (NoSuchAlgorithmException | NoSuchPaddingException e) 
//  { 
//   e.printStackTrace(); 
//  } 
    } 


    public void saveData(ArrayList<Account> dataToSave) 
    { 
     try 
     { 
      FileOutputStream fileOut = new FileOutputStream(Config.SERIAL_FILE); 
      ObjectOutputStream out = new ObjectOutputStream(fileOut); 
      out.writeObject(encrypt(dataToSave)); 
      out.close(); 
      fileOut.close(); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 


    @SuppressWarnings("unchecked") 
    public ArrayList<Account> loadData() 
    { 
     ArrayList<Account> loadedData = new ArrayList<Account>(); 
     File f = new File(Config.SERIAL_FILE); 
     if (f.exists()) 
     { 
      try 
      { 
       FileInputStream fileIn = new FileInputStream(Config.SERIAL_FILE); 
       ObjectInputStream in = new ObjectInputStream(fileIn); 
       loadedData = (ArrayList<Account>) in.readObject(); 
       in.close(); 
       fileIn.close(); 
      } 
      catch (IOException | ClassNotFoundException e) 
      { 
       e.printStackTrace(); 
      } 
      loadedData = decrypt(loadedData); 
     } 
     else 
     { 
      loadedData = new ArrayList<Account>(); 
     } 
     return loadedData; 
    } 


    private ArrayList<Account> encrypt(List<Account> decrypted) 
    { 
     ArrayList<Account> encrypted = new ArrayList<Account>(); 

     try 
     { 
      IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 
      SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 
      cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
      cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 
      for (int i = 0; i < decrypted.size(); i++) 
      { 
       try 
       { 
        byte[] login = cipher.doFinal(Base64.getDecoder().decode(decrypted.get(i).getLogin().getBytes())); 
        encrypted.add(new Account(login.toString(), "pass")); 
       } 
       catch (Exception ex) 
       { 
        ex.printStackTrace(); 
       } 
      } 
     } 
     catch (InvalidKeyException | InvalidAlgorithmParameterException | UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException e) 
     { 
      e.printStackTrace(); 
     } 
     return encrypted; 
    } 


    private ArrayList<Account> decrypt(List<Account> encrypted) 
    { 
     ArrayList<Account> decrypted = new ArrayList<Account>(); 

     try 
     { 
      SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 
      IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 
      cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
      cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 

      for (int i = 0; i < encrypted.size(); i++) 
      { 
       byte[] login = cipher.doFinal(Base64.getDecoder().decode(encrypted.get(i).getLogin())); 
       decrypted.add(new Account(new String(login), "pass")); 
      } 
     } 
     catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException e) 
     { 
      e.printStackTrace(); 
     } 
     return decrypted; 
    } 


    public static Move getMove() 
    { 
     if (instance == null) 
     { 
      instance = new Move(); 
     } 
     return instance; 
    } 
} 
+0

なぜハッシュの代わりにパスワードを暗号化/復号化するのですか? – Justas

+0

私はそれらをファイルに保存し、アプリケーションの起動中にそれらをロードするので。 – rainbow

答えて

1

AESブロックサイズは、それがこの数の倍数で入力を受け取る必要があり、常に128ビットです。

小さい入力は、16バイトにパディングする必要があります。パディングのタイプはアルゴリズムに指定します。

「AES/CBC/PKCS5Padding」を使用すると、このトリックが実行されます。

cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

NoPaddingを使用する場合、暗号化のために独自のパディングを実装し、解読時に結果の文字列から確実に削除する必要があります。

+0

詰め物が正しく完成していることを正しく理解していますか? – rainbow

+0

たとえば、パスワードが「1234」の場合、AESは「1234000000000000」のようなものを期待します。 – didiz

関連する問題