簡體   English   中英

Android運行時錯誤的自定義加密類

[英]Custom Encryption Class for Android Runtime Error

我在stackoverflow上發現了一個有趣的代碼: 在Android中使用AES加密的最佳實踐是什么?

我進行了一些更改以使其正常運行(已刪除implements ICryptoimplements ICrypto throws CryptoException更改為throws Exception ,將其添加到toHextoByte函數中,並將某些函數更改為靜態)

我試圖通過像這樣調用它來加密字符串:

String EncryptedText = AdvancedCrypto.encrypt(AdvancedCrypto.getSecretKey("MyPassword", "MySalt"), "TheStringThatIwantEncrypted");

我究竟做錯了什么? 我正在使用Eclipse,並且代碼上沒有錯誤,但是當我在Android AVD上運行它時,什么也沒有發生。 Logcat彈出一些奇怪的日志,我不知道它們是什么意思。

這是我從logcat得到的:

 W/System.err(346): java.lang.Exception: Unable to get secret key
 W/System.err(346):     at com.example.enc.AdvancedCrypto.getSecretKey(AdvancedCrypto.java:92)
 W/System.err(346):     at com.example.enc.MainActivity$1.onClick(MainActivity.java:38)
 W/System.err(346):     at android.view.View.performClick(View.java:2364)
 W/System.err(346):     at android.view.View.onTouchEvent(View.java:4179)
 W/System.err(346):     at android.widget.TextView.onTouchEvent(TextView.java:6541)
 W/System.err(346):     at android.view.View.dispatchTouchEvent(View.java:3709)
 W/System.err(346):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
 W/System.err(346):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
 W/System.err(346):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
 W/System.err(346):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
 W/System.err(346):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659)
 W/System.err(346):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
 W/System.err(346):     at android.app.Activity.dispatchTouchEvent(Activity.java:2061)
 W/System.err(346):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643)
 W/System.err(346):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1691)
 W/System.err(346):     at android.os.Handler.dispatchMessage(Handler.java:99)
 W/System.err(346):     at android.os.Looper.loop(Looper.java:123)
 W/System.err(346):     at android.app.ActivityThread.main(ActivityThread.java:4363)
 W/System.err(346):     at java.lang.reflect.Method.invokeNative(Native Method)
 W/System.err(346):     at java.lang.reflect.Method.invoke(Method.java:521)
 W/System.err(346):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
 W/System.err(346):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
 W/System.err(346):     at dalvik.system.NativeStart.main(Native Method)
 W/System.err(346): Caused by: java.lang.NumberFormatException: unable to parse 'dh' as integer
 W/System.err(346):     at java.lang.Integer.parse(Integer.java:374)
 W/System.err(346):     at java.lang.Integer.parseInt(Integer.java:363)
 W/System.err(346):     at java.lang.Integer.valueOf(Integer.java:688)
 W/System.err(346):     at com.example.enc.AdvancedCrypto.toByte(AdvancedCrypto.java:32)
 W/System.err(346):     at com.example.enc.AdvancedCrypto.getSecretKey(AdvancedCrypto.java:86)
 W/System.err(346):     ... 22 more

到目前為止,我的代碼是:

public class AdvancedCrypto {

  public static final String PROVIDER = "BC";
  public static final int SALT_LENGTH = 20;
  public static final int IV_LENGTH = 16;
  public static final int PBE_ITERATION_COUNT = 100;

  private static final String RANDOM_ALGORITHM = "SHA1PRNG";
  private static final String HASH_ALGORITHM = "SHA-512";
  private static final String PBE_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
  private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
  private static final String SECRET_KEY_ALGORITHM = "AES";

  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));
  }

  public static String encrypt(SecretKey secret, String cleartext) throws Exception {
    try {

      byte[] iv = generateIv();
      String ivHex = toHex(iv);
      IvParameterSpec ivspec = new IvParameterSpec(iv);

      Cipher encryptionCipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER);
      encryptionCipher.init(Cipher.ENCRYPT_MODE, secret, ivspec);
      byte[] encryptedText = encryptionCipher.doFinal(cleartext.getBytes("UTF-8"));
      String encryptedHex = toHex(encryptedText);

      return ivHex + encryptedHex;

    } catch (Exception e) {
      throw new Exception("Unable to encrypt", e);
    }
  }

  public static String decrypt(SecretKey secret, String encrypted) throws Exception {
    try {
      Cipher decryptionCipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER);
      String ivHex = encrypted.substring(0, IV_LENGTH * 2);
      String encryptedHex = encrypted.substring(IV_LENGTH * 2);
      IvParameterSpec ivspec = new IvParameterSpec(toByte(ivHex));
      decryptionCipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
      byte[] decryptedText = decryptionCipher.doFinal(toByte(encryptedHex));
      String decrypted = new String(decryptedText, "UTF-8");
      return decrypted;
    } catch (Exception e) {
      throw new Exception("Unable to decrypt", e);
    }
  }

  public static SecretKey getSecretKey(String password, String salt) throws Exception {
    try {
      PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), toByte(salt), PBE_ITERATION_COUNT, 256);
      SecretKeyFactory factory = SecretKeyFactory.getInstance(PBE_ALGORITHM, PROVIDER);
      SecretKey tmp = factory.generateSecret(pbeKeySpec);
      SecretKey secret = new SecretKeySpec(tmp.getEncoded(), SECRET_KEY_ALGORITHM);
      return secret;
    } catch (Exception e) {
      throw new Exception("Unable to get secret key", e);
    }
  }

  public String getHash(String password, String salt) throws Exception {
    try {
      String input = password + salt;
      MessageDigest md = MessageDigest.getInstance(HASH_ALGORITHM, PROVIDER);
      byte[] out = md.digest(input.getBytes("UTF-8"));
      return toHex(out);
    } catch (Exception e) {
      throw new Exception("Unable to get hash", e);
    }
  }

  public String generateSalt() throws Exception {
    try {
      SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
      byte[] salt = new byte[SALT_LENGTH];
      random.nextBytes(salt);
      String saltHex = toHex(salt);
      return saltHex;
    } catch (Exception e) {
      throw new Exception("Unable to generate salt", e);
    }
  }

  private static byte[] generateIv() throws NoSuchAlgorithmException, NoSuchProviderException {
    SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
    byte[] iv = new byte[IV_LENGTH];
    random.nextBytes(iv);
    return iv;
  }

}

讀取堆棧跟蹤后,看起來傳遞給getSecretKey的salt值包含無效值。 具體來說,它應該是一個十六進制值,但其中包含一個h

您的密碼可以包含非十六進制字符,但是您的密碼必須為純十六進制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM