无法在Android应用程序中解密String

我正在尝试开发一个可以加密和解密值的android应用程序。 所以我按照这个链接在这里输入链接描述

到目前为止,我能够加密文本,但我无法解密它。 在我的代码中,我使用了相同的AESHelper类,该类在提供的链接中提到。

以下是我用来加密和解密值的活动类

import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends ActionBarActivity { EditText text ; TextView encp,decriptom; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (EditText) findViewById(R.id.editText); encp = (TextView) findViewById(R.id.valueexcript); decriptom = (TextView) findViewById(R.id.deexcript); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public void Ecript(View v) { String Key = "avc"; try { String normalTextEnc = AHShelper.encrypt(Key, text.getText().toString()); Toast.makeText(this,normalTextEnc,Toast.LENGTH_LONG).show(); encp.setText(normalTextEnc); } catch (Exception e) { e.printStackTrace(); } // Toast.makeText(this,"Hello",Toast.LENGTH_LONG).show(); String decript; try { decript = AHShelper.decrypt(Key,encp.getText().toString()); decriptom.setText(decript); Toast.makeText(this,decript,Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); } } } 

我使用的AHShelper类如下

 import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class AHShelper { public static String encrypt(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, cleartext.getBytes()); return toHex(result); } public static String decrypt(String seed, String encrypted) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); 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) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] decrypted = cipher.doFinal(encrypted); 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 > 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } } 

基本上这个代码依赖于一个小技巧:如果在使用SUN提供程序和Bouncy Castle提供程序之前为其生成SHA1PRNG,那么它将始终生成相同的随机字节流。

但对于每个提供商而言并非总是如此; 其他提供者只是混合种子。 换句话说,他们可以使用预播种的PRNG并混合种子。 在这种情况下, getRawKey方法为加密和解密生成不同的密钥,这将导致解密失败。

也可能是提供商决定使用基于SHA-1的不同算法的情况,因为SUN / Oracle使用的算法没有明确规定 – 至少公开。


基本上这个可怕的代码片段滥用SHA1PRNG作为密钥派生函数或KDF。 如果输入是密码,则应使用真正的KDF,例如PBKDF2;如果输入是密钥,则应使用HKDF。 PBKDF2构建为Java。

应删除该代码段。 它已从Android代码段中复制,但我找不到该网站了。 它似乎甚至更加function失调,换句话说它是可用的。


使用SUN加密时检索数据的可能解决方案是在Oracle提供的JDK上解密它。 否则,您还可以复制SHA1PRNG的内部实现类的代码,并使用它来解密您的数据。 请注意,您需要记住SUN的来源是GPL; 如果你这样做,你需要遵守该许可证。 对于较旧的Android版本,您可以使用其源代码。 我强烈建议之后删除这段可怕的代码并依赖PBKDF2代替。

如果您使用的是一个返回完全随机密钥的实现,那么您就完全没有运气了。 你的数据已经消失了。 请放心,它将在最后时刻保密。