Java Android运行时错误的自定义加密类

Java Android运行时错误的自定义加密类,java,android,encryption,aes,Java,Android,Encryption,Aes,我在stackoverflow上发现了一个有趣的代码: 我做了一些更改以使其工作(删除了实现ICrypto,将抛出加密异常更改为抛出异常,添加了toHex和toByte函数,并将一些函数更改为静态) 我试图通过如下方式调用字符串对其进行加密: String EncryptedText = AdvancedCrypto.encrypt(AdvancedCrypto.getSecretKey("MyPassword", "MySalt"), "TheStringThatIwantEncrypted"

我在stackoverflow上发现了一个有趣的代码:

我做了一些更改以使其工作(删除了
实现ICrypto
,将
抛出加密异常
更改为
抛出异常
,添加了
toHex
toByte
函数,并将一些函数更改为静态)

我试图通过如下方式调用字符串对其进行加密:

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

}
公共类高级加密{
公共静态最终字符串提供程序=“BC”;
公共静态最终int_长度=20;
公共静态最终int IV_长度=16;
公共静态最终int PBE_迭代计数=100;
私有静态最终字符串随机算法=“SHA1PRNG”;
私有静态最终字符串哈希算法=“SHA-512”;
私有静态最终字符串PBE_ALGORITHM=“pbewithsha256和256biates CBC BC”;
私有静态最终字符串密码\u算法=“AES/CBC/PKCS5Padding”;
私有静态最终字符串密钥算法=“AES”;
公共静态字节[]toByte(字符串hexString){
int len=hexString.length()/2;
字节[]结果=新字节[len];
对于(int i=0;i>4)和0x0f)).append(十六进制字符(b和0x0f));
}
公共静态字符串加密(SecretKey secret,String cleartext)引发异常{
试一试{
字节[]iv=生成iv();
字符串ivHex=toHex(iv);
IvParameterSpec ivspec=新的IvParameterSpec(iv);
Cipher encryptionCipher=Cipher.getInstance(Cipher_算法,提供程序);
encryptionCipher.init(Cipher.ENCRYPT_模式,secret,ivspec);
byte[]encryptedText=encryptionCipher.doFinal(cleartext.getBytes(“UTF-8”);
字符串encryptedHex=toHex(encryptedText);
返回ivHex+加密HEX;
}捕获(例外e){
抛出新异常(“无法加密”,e);
}
}
公共静态字符串解密(SecretKey secret,字符串加密)引发异常{
试一试{
Cipher decryptionCipher=Cipher.getInstance(Cipher_算法,提供程序);
字符串ivHex=加密的.substring(0,IV_长度*2);
字符串encryptedHex=加密的.substring(IV_长度*2);
IvParameterSpec ivspec=新的IvParameterSpec(toByte(ivHex));
decryptionCipher.init(Cipher.DECRYPT_模式,secret,ivspec);
byte[]decryptedText=decryptionCipher.doFinal(toByte(encryptedHex));
已解密字符串=新字符串(解密文本,“UTF-8”);
返回解密;
}捕获(例外e){
抛出新异常(“无法解密”,e);
}
}
公共静态SecretKey getSecretKey(字符串密码,字符串salt)引发异常{
试一试{
PBEKeySpec PBEKeySpec=新的PBEKeySpec(password.toCharArray(),toByte(salt),PBE_迭代计数,256);
SecretKeyFactory factory=SecretKeyFactory.getInstance(PBE_算法,提供程序);
SecretKey tmp=factory.generateSecret(pbeKeySpec);
SecretKey secret=新的SecretKeySpec(tmp.getEncoded(),secret\u KEY\u算法);
归还秘密;
}捕获(例外e){
抛出新异常(“无法获取密钥”,e);
}
}
公共字符串getHash(字符串密码、字符串salt)引发异常{
试一试{
字符串输入=密码+盐;
MessageDigest md=MessageDigest.getInstance(哈希算法,提供者);
byte[]out=md.digest(input.getBytes(“UTF-8”);
返回HEX(输出);
}捕获(例外e){
抛出新异常(“无法获取哈希”,e);
}
}
公共字符串generateSalt()引发异常{
试一试{
SecureRandom=SecureRandom.getInstance(随机算法);
字节[]salt=新字节[salt_长度];
随机。下一个字节(盐);
字符串saltHex=toHex(salt);
返回saltHex;
}捕获(例外e){
抛出新异常(“无法生成salt”,e);
}
}
私有静态字节[]generateIv()引发NoSuchAlgorithmException,NoSuchProviderException{
SecureRandom=SecureRandom.getInstance(随机算法);
字节[]iv=新字节[iv_长度];
随机。下一字节(iv);
回报四;
}
}

读取堆栈跟踪时,传递给
getSecretKey
的salt值似乎包含无效值。具体来说,它应该是一个十六进制值,但它包含一个
h


您的密码可以包含非十六进制字符,但您的salt必须是纯十六进制。

“Logcat会弹出一些奇怪的日志,我不知道它们的意思。”>我们可能知道它们的意思-请将它们添加到问题中。“什么都没有发生”>它会引发异常吗?它是否执行结果错误的命令?只是添加了Logcat输出。当我说“什么都没有发生”时,我的意思是在视觉上什么都没有发生(而我希望代码中会显示一条带有加密消息的toast消息)。我看不出有什么错误。我得到的所有错误都是您在logcat输出中可以看到的错误。非常感谢您,我的朋友!!的确我的盐不是纯十六进制的,它含有h。我改变了它,工作起来很有魅力!