Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
153 views
in Technique[技术] by (71.8m points)

java - Unable to decrypt String in android App

I was trying to develop an android application that could encrypt and decrypt values. So I have followed this link enter link description here

So far I was able to encrypt a text but I was not able to decrypt it. In my code I have used the same AESHelper class which is mentioned in the link provided.

The below is my activity class that i have used to Encrypt and decrypt the values

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 class that i have used is below

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

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Basically this code relies on a little trick: if you seed the SHA1PRNG for the SUN provider and Bouncy Castle provider before it is used then it will always generate the same stream of random bytes.

This is not always the case for every provider though; other providers simply mix in the seed. In other words, they may use a pre-seeded PRNG and mix-in the seed instead. In that case the getRawKey method generates different keys for the encrypt and decrypt, which will result in a failure to decrypt.

It could also be the case that a provider decides to use a different algorithm based on SHA-1 altogether, as the algorithm used by SUN/Oracle is not well specified - publicly at least.


Basically this horrible code snippet abuses the SHA1PRNG as a Key Derivation Function or KDF. You should use a true KDF such as PBKDF2 if the input is a password or HKDF if the input is a key. PBKDF2 is build into Java.

That code snippet should be removed. It has been copied from Android snippets, but I cannot find that site anymore. It seems even more dysfunctional then when it was available in other words.


A possible solution to retrieve your data when encrypted with SUN is either to decrypt it on an Oracle provided JDK. Otherwise you could also copy the code of the inner implementation class of the SHA1PRNG and use that to decrypt your data. Note that you do need to keep in mind that the sources of SUN are GPL'ed; you need to adhere to that license if you do. For older Android versions you can use the source code of that. I would strongly advice to remove this horrible piece of code afterwards and rely on PBKDF2 instead.

If you're using an implementation that returns a fully random key then you're completely out of luck. Your data is gone, period. Rest assured that it will be kept confidential to the end of times.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...