【问题标题】:Android - Crittografy Cipher decrypt doesn't workAndroid - Crittografy Cipher 解密不起作用
【发布时间】:2013-01-24 10:46:11
【问题描述】:

我需要加密一个字符串然后解密。加密函数运行良好,但是当我将加密值传递给解密函数时,我收到一个空指针异常。如果我在 Java 应用程序中使用相同的代码一切正常。

public class Cripthografy {
private static String TAG="freeliberomail";

 public static String encrypt(String seed, String cleartext){
   byte[] rawKey;
   byte[] result=null;
 try {
rawKey = getRawKey(seed.getBytes());

     result = encrypt(rawKey, cleartext.getBytes());
  } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
  }
   return toHex(result);
  }

  public static String decrypt(String seed, String encrypted) {
    byte[] rawKey;
    byte[] result=null;
   try {
rawKey = getRawKey(seed.getBytes());

    byte[] enc = toByte(encrypted);
    result = decrypt(rawKey, enc);
    } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
   }
    return new String(result);
   }


   private static byte[] getRawKey(byte[] seed) throws Exception {
      KeyGenerator kgen = KeyGenerator.getInstance("AES");
      SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
      sr.setSeed(seed);
      kgen.init(128, sr); // 192 and 256 bits may not be available
      SecretKey skey = kgen.generateKey();
      byte[] raw = skey.getEncoded();
      return raw;
    }
    private static byte[] encrypt(byte[] raw, byte[] clear){
 byte[] encrypted=null;
      SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
      Cipher cipher;
     try {
 cipher = Cipher.getInstance("AES");
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
     encrypted = cipher.doFinal(clear);
     } catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
    } catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
    } catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
    } catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
    }
     return encrypted;
    }


     private static byte[] decrypt(byte[] raw, byte[] encrypted) {
 byte[] decrypted = null;
     SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
     Cipher cipher;
     try {
 cipher = Cipher.getInstance("AES");
     cipher.init(Cipher.DECRYPT_MODE, skeySpec);
     decrypted = cipher.doFinal(encrypted);
     }catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace(); 
     } catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
   } catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
   }

    return decrypted;
   }


  public static String toHex(String txt) {
  return toHex(txt.getBytes());
  }

 public static String fromHex(String hex) {
 return new String(toByte(hex));
 }

 public static byte[] toByte(String hexString) {
  int len = hexString.length()/2;
  byte[] result = new byte[len];
  for (int i = 0; i < len; i++)
  result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
  return result;
 }


  public static String toHex(byte[] buf) {
    if (buf == null)
    return "";
    StringBuffer result = new StringBuffer(2*buf.length);
      for (int i = 0; i < buf.length; i++) {
        appendHex(result, buf[i]);
    }
     return result.toString();
   }
  private final static String HEX = "0123456789ABCDEF";
  private static void appendHex(StringBuffer sb, byte b) {
  sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
  }

}

然后我打电话:

          String encValue=Cripthografy.encrypt("MY_KEY", "helloworld");
      String decValue=Cripthografy.decrypt("MY_KEY",  encValue);
      Log.d(TAG,"encript:"+encValue+" "+"decript:"+decValue);

例外是:

      01-17 03:57:23.986: W/System.err(29846): javax.crypto.BadPaddingException: pad      block corrupted
       01-17 03:57:23.991: W/System.err(29846):     at      com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(B           aseBlockCipher.java:709)
       01-17 03:57:23.991: W/System.err(29846):     at       javax.crypto.Cipher.doFinal(Cipher.java:1111)
        01-17 03:57:23.991: W/System.err(29846):    at    marvellous.freeliberomail.Cripthografy.decrypt(Cripthografy.java:111)
        01-17 03:57:23.991: W/System.err(29846):    at   marvellous.freeliberomail.Cripthografy.decrypt(Cripthografy.java:55)
         01-17 03:57:23.991: W/System.err(29846):   at   marvellous.freeliberomail.Auth.writeCookieTofile(Auth.java:307)
        01-17 03:57:23.991: W/System.err(29846):    at marvellous.freeliberomail.Auth.createSessionCookie(Auth.java:287)
        01-17 03:57:23.991: W/System.err(29846):    at marvellous.freeliberomail.Auth.scenario(Auth.java:196)
        01-17 03:57:23.991: W/System.err(29846):    at marvellous.freeliberomail.Auth.accessMail(Auth.java:117)
        01-17 03:57:23.991: W/System.err(29846):    at marvellous.freeliberomail.Auth.run(Auth.java:96)
       01-17 03:57:23.991: W/System.err(29846):     at java.lang.Thread.run(Thread.java:856)
        01-17 03:57:23.996: W/dalvikvm(29846): threadid=11: thread exiting with uncaught exception (group=0x41584930)
            01-17 03:57:23.996: E/AndroidRuntime(29846): FATAL EXCEPTION: Thread-32785
            01-17 03:57:23.996: E/AndroidRuntime(29846): java.lang.NullPointerException
            01-17 03:57:23.996: E/AndroidRuntime(29846):    at java.lang.String.<init>(String.java:141)
            01-17 03:57:23.996: E/AndroidRuntime(29846):    at marvellous.freeliberomail.Cripthografy.decrypt(Cripthografy.java:60)
            01-17 03:57:23.996: E/AndroidRuntime(29846):    at marvellous.freeliberomail.Auth.writeCookieTofile(Auth.java:307)
             01-17 03:57:23.996: E/AndroidRuntime(29846):   at marvellous.freeliberomail.Auth.createSessionCookie(Auth.java:287)
            01-17 03:57:23.996: E/AndroidRuntime(29846):    at marvellous.freeliberomail.Auth.scenario(Auth.java:196)
            01-17 03:57:23.996: E/AndroidRuntime(29846):    at marvellous.freeliberomail.Auth.accessMail(Auth.java:117)
             01-17 03:57:23.996: E/AndroidRuntime(29846):   at marvellous.freeliberomail.Auth.run(Auth.java:96)
            01-17 03:57:23.996: E/AndroidRuntime(29846):    at java.lang.Thread.run(Thread.java:856)

【问题讨论】:

    标签: android encryption


    【解决方案1】:

    是的,android Cipher 确实存在一些问题。 一是 cipher.doFinal(encrypted) 中的 byte[] 有时必须具有正确的长度。尝试使用 128 位的加密数组(用 0 填充?)

    经过许多痛苦的时间后,这个例子终于奏效了:

    private static byte[] key = "12345678".getBytes();// 64 bit 
    private static byte[] iv = "12345678".getBytes();
    
    public static String encrypt(String in) {
        String cypert = in;
        try {
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            SecretKeySpec k = new SecretKeySpec(key, "DES");
            Cipher c = Cipher.getInstance("DES/CBC/PKCS7Padding");
            c.init(Cipher.ENCRYPT_MODE, k, ivSpec);
            byte[] encryptedData = c.doFinal(in.getBytes());
            cypert = Base64.encodeLines(encryptedData);
        } catch (Exception e) {
            Debugger.error(e);
        }
        return cypert;
    }
    
    
    public static String decrypt(String in) throws Exception {
        String plain=in;
        try {
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            SecretKeySpec keys = new SecretKeySpec(key, "DES");
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS7Padding");
            cipher.init(Cipher.DECRYPT_MODE, keys, ivSpec);
            // decryption pass
            byte[] cipherText = Base64.decodeLines(in);
            int ctLength = cipherText.length;
            byte[] plainText = new byte[cipher.getOutputSize(ctLength)];
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bos.write(cipher.doFinal(cipherText));
            plainText = bos.toByteArray();
            bos.close();
            plain = new String(plainText, "UTF8");
        } catch (Exception e) {
            Debugger.error(e);
        }
        return plain;
    }
    

    【讨论】:

    • 谢谢,它有效!它是否接受长度超过 8 个字节的密钥?
    • 上次我尝试使用更长的密钥没有用。似乎密钥必须具有特定形式。让我们继续挖掘......
    • 谢谢...!!!你能告诉我 Base64.encodeline() 的特定导入是什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2021-12-29
    • 2015-01-13
    • 2012-11-02
    相关资源
    最近更新 更多