Нулевое исключение PointerException в алгоритме AES - PullRequest
0 голосов
/ 06 июля 2010

Это код для шифрования и дешифрования строки в Java с использованием алгоритма AES.

StackTrace:

    javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
    at test.AES.AESdecryptalgo(AES.java:76)
    at test.AES.main(AES.java:95)

Код:

package test;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;

public class AES
{
  public byte[] encrypted;
  public byte[] original;

  public String originalString;
  Cipher cipher;
  SecretKeySpec skeySpec;
  IvParameterSpec spec;
  byte [] iv;
  /*public static String asHex (byte buf[])
  {
    StringBuffer strbuf = new StringBuffer(buf.length * 2);
    int i;
    for (i = 0; i < buf.length; i++) {
    if (((int) buf[i] & 0xff) < 0x10)
    strbuf.append("0");
    strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
  }
  return strbuf.toString();
}*/
  public AES()
  {
        try
        {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128);
            SecretKey skey = kgen.generateKey();
            byte[] raw = skey.getEncoded();
            skeySpec = new SecretKeySpec(raw, "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        }
        catch(Exception ex)
        {ex.printStackTrace();}
  }
public String AESencryptalgo(byte[] text)
{
    String newtext="";
    try
    {
        // byte[] raw = skey.getEncoded();
        //SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            AlgorithmParameters param = cipher.getParameters();
            IvParameterSpec ivspec=param.getParameterSpec(IvParameterSpec.class);
            iv=ivspec.getIV();
            spec=new IvParameterSpec(iv);
        //AlgorithmParameters params = cipher.getParameters();
        //iv = params.getParameterSpec(IvParameterSpec.class).getIV();
        encrypted = cipher.doFinal(text);

    }
   catch(Exception e)
   {
       e.printStackTrace();
   }
   finally
   {
      newtext=new String(encrypted);
       //System.out.println("ENCRYPTED "+newtext);
       return newtext;
    }
}
public  String AESdecryptalgo(byte[] text)
{
    try
    {

        cipher.init(Cipher.DECRYPT_MODE, skeySpec,spec);
        original = cipher.doFinal(text);   //Exception occurs here
        originalString = new String(original);

    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {

        return originalString;
    }
}
public static void main(String[] args)
{
    AES a=new AES();
    String encrypt=a.AESencryptalgo("hello".getBytes());
    System.out.println(encrypt);
    String decrypt=a.AESdecryptalgo(encrypt.getBytes());
    System.out.println(decrypt);
}

} `

1 Ответ

2 голосов
/ 06 июля 2010

Проблема в том, что ваш конструктор на самом деле не конструктор, поэтому skey, cipher и другие закрытые члены никогда не инициализируются.

Конструкторы определены без возвращаемых типов, поэтому вам нужноизмените public void AES() на public AES.


Хорошо, очевидно, вы исправили эту проблему.Следующим является то, что cipher.init не берет SecretKey, а SecretKeySpec.Работая с этого примера, который я нашел вам нужно что-то вроде:

byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

... и тогда вы можете передать skeySpec, где вы в данный момент передаете skey на cipher.init.


Вперед, я полагаю, если только я не считаю неправильно, ваша проблема с этой строкой:

 iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();

Если вы убедитесь, что cipher не ноль, местав этой строке, которая может выдать NullPointerException, после вызова getParameters() или после вызова getParameterSpec().Вы можете легко определить, какой из этих вызовов вызывает исключение, разбив его на несколько строк и изучив трассировку стека ( вам следует посмотреть на трассировку стека и определить, где на самом деле генерируется исключение).

Если бы мне пришлось сделать ставку, я бы предположил, что cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); недействительно.Я подозреваю, что это сработало бы хорошо, если бы у вас было

cipher = Cipher.getInstance("AES");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...