在Android中使用密码加密和解密

时间:2016-04-27 08:09:39

标签: android encryption

我有一个像这样的哭泣课:

import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * Usage:
 *

 * String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
 * ...
 * String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
 *

 * @author ferenc.hechler
 */

public class SimpleCrypto {

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

这是我的activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="xmaxsoft.delsifremax.MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:text="tv1"
        android:id="@+id/tv1"
        android:background="#120b0b"
        android:textColor="#f75555"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="tvText"
        android:id="@+id/tvText"
        android:background="#120b0b"
        android:textColor="#f75555"
        android:layout_below="@+id/tv1"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="10dp" />



    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="tvTextEnc"
        android:id="@+id/tvTextEnc"
        android:background="#120b0b"
        android:textColor="#f75555"
        android:layout_below="@+id/tvText"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="encrypt"
        android:id="@+id/btnEncrypt"
        android:layout_below="@+id/tvText"
        android:layout_centerHorizontal="true" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/etPw"
        android:layout_below="@+id/tvText"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_toLeftOf="@+id/btnEncrypt"
        android:layout_toStartOf="@+id/btnEncrypt"
        android:background="#110f0f"
        android:paddingTop="10dp"
        android:layout_marginTop="10dp"
        android:text="etPw"
        android:textColor="#28bf25" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Decrypt"
        android:id="@+id/btnDecrypt"
        android:layout_below="@+id/tvTextEnc"
        android:layout_toRightOf="@+id/etPw"
        android:layout_toEndOf="@+id/etPw" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="tvTextDec"
        android:id="@+id/tvTextDec"
        android:background="#120b0b"
        android:textColor="#f75555"
        android:layout_below="@+id/btnDecrypt"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />
</RelativeLayout>

这是我的MainActivity:

import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class MainActivity extends AppCompatActivity {
    TextView tv1;
    TextView tvText;
    TextView tvTextEnc;
    TextView tvTextDec;
    Button btnEncrypt;
    Button btnDecrypt;
    EditText etPw;

    private GoogleApiClient client;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1 = (TextView) findViewById(R.id.tv1);
        tvText = (TextView) findViewById(R.id.tvText);
        tvTextEnc = (TextView) findViewById(R.id.tvTextEnc);
        tvTextDec = (TextView) findViewById(R.id.tvTextDec);
        btnEncrypt = (Button) findViewById(R.id.btnEncrypt);
        btnDecrypt = (Button) findViewById(R.id.btnDecrypt);
        etPw = (EditText) findViewById(R.id.etPw);

        btnEncrypt.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                String normalText = tvText.getText().toString().trim();
                String normalTextEnc = "";
                String seedValue = etPw.getText().toString().trim();
                try {

                    normalTextEnc = SimpleCrypto.encrypt(seedValue,normalText.trim());

                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                tvTextEnc.setText(normalTextEnc.toString().trim());
            }
        });

        btnDecrypt.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                String normalTextEnc = tvTextEnc.getText().toString().trim();
                String normalTextDec = "";
                String seedValue = etPw.getText().toString().trim();
                try {

                    normalTextDec = SimpleCrypto.decrypt(seedValue, normalTextEnc.trim());
                    tvTextDec.setText(normalTextDec.toString().trim());

                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    tvTextDec.setText(e.toString());
                }
            }
        });

        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    }

    @Override
    public void onStart() {
        super.onStart();

        client.connect();
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://xmaxsoft.delsifremax/http/host/path")
        );
        AppIndex.AppIndexApi.start(client, viewAction);
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://xmaxsoft.delsifremax/http/host/path")
        );
        AppIndex.AppIndexApi.end(client, viewAction);
        client.disconnect();
    }
}

我可以加密字符串,但我无法再次解密加密字符串。为什么?这段代码有什么问题?我得到&#34; javax.crypto.BadPaddingException:pad block corrupted&#34;错误。

1 个答案:

答案 0 :(得分:0)

我有一个使用密码和盐对某些String进行加密和解密的类:

public class Crypto {
    private static String IV = "IV_VALUE_16_BYTE";
    private static String PASSWORD = "some-hash-password";
    private static String SALT = "some-hash-salt";

    public static String encryptAndEncode(String raw) {
        try {
            Cipher c = getCipher(Cipher.ENCRYPT_MODE);
            byte[] encryptedVal = c.doFinal(getBytes(raw));
            String s = Base64.encodeToString(encryptedVal, Base64.DEFAULT);
            return s;
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static String decodeAndDecrypt(String encrypted) throws Exception {
        byte[] decodedValue = Base64.decode(getBytes(encrypted),Base64.DEFAULT);
        Cipher c = getCipher(Cipher.DECRYPT_MODE);
        byte[] decValue = c.doFinal(decodedValue);
        return new String(decValue);
    }

    private String getString(byte[] bytes) throws UnsupportedEncodingException {
        return new String(bytes, "UTF-8");
    }

    private static byte[] getBytes(String str) throws UnsupportedEncodingException {
        return str.getBytes("UTF-8");
    }

    private static Cipher getCipher(int mode) throws Exception {
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] iv = getBytes(IV);
        c.init(mode, generateKey(), new IvParameterSpec(iv));
        return c;
    }

    private static Key generateKey() throws Exception {
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        char[] password = PASSWORD.toCharArray();
        byte[] salt = getBytes(SALT);

        KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
        SecretKey tmp = factory.generateSecret(spec);
        byte[] encoded = tmp.getEncoded();
        return new SecretKeySpec(encoded, "AES");
    }

}

加密:

Crypto.encryptAndEncode("String_to_encrypt");

解密:

Crypto.decodeAndDecrypt("String_encrypted");

希望有帮助!