解密加密数据时出错

时间:2014-10-06 11:29:04

标签: android encryption

有人可以帮我解决Github中我想用于项目的代码吗 我是Android编程的新手,也是加密的新手。

为什么我在解密代码时遇到错误?这样做的正确方法是什么?

        import android.app.*;
        import android.os.*;
        import android.view.*;
        import android.widget.*;
         import javax.crypto.*;
import android.util.*;

public class MainActivity extends Activity
{

MCrypt mc;
TextView tv1;
TextView tv2;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
{
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

tv1 = (TextView) findViewById(R.id.textView1);
tv2 = (TextView) findViewById(R.id.textView2);

byte[] salt = MCrypt.generateSalt();
SecretKey sk = MCrypt.deriveKeyPkcs12(salt, "password");
String tvText = MCrypt.encryptPkcs12("text",sk,salt);
tv1.setText(tvText);



String tvText2 = MCrypt.decryptPkcs12(tvText,"password");
tv2.setText(tvText2);

    }
}

我从Github复制的课程如下。我只想使用PKCS12方法加密/解密

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.Provider.Service;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.KeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import android.util.Base64;
import android.util.Log;

public class Crypto {

    private static final String TAG = Crypto.class.getSimpleName();

    public static final String PKCS12_DERIVATION_ALGORITHM = "PBEWITHSHA256AND256BITAES-CBC-BC";
    public static final String PBKDF2_DERIVATION_ALGORITHM = "PBKDF2WithHmacSHA1";
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";

    private static String DELIMITER = "]";

    private static int KEY_LENGTH = 256;
    // minimum values recommended by PKCS#5, increase as necessary
    private static int ITERATION_COUNT = 1000;
    private static final int PKCS5_SALT_LENGTH = 8;

    private static SecureRandom random = new SecureRandom();

    private Crypto() {
    }

    public static void listAlgorithms(String algFilter) {
        Provider[] providers = Security.getProviders();
        for (Provider p : providers) {
            String providerStr = String.format("%s/%s/%f\n", p.getName(),
                    p.getInfo(), p.getVersion());
            Log.d(TAG, providerStr);
            Set<Service> services = p.getServices();
            List<String> algs = new ArrayList<String>();
            for (Service s : services) {
                boolean match = true;
                if (algFilter != null) {
                    match = s.getAlgorithm().toLowerCase()
                            .contains(algFilter.toLowerCase());
                }

                if (match) {
                    String algStr = String.format("\t%s/%s/%s", s.getType(),
                            s.getAlgorithm(), s.getClassName());
                    algs.add(algStr);
                }
            }

            Collections.sort(algs);
            for (String alg : algs) {
                Log.d(TAG, "\t" + alg);
            }
            Log.d(TAG, "");
        }
    }

    // Illustration code only: don't use in production!
    public static SecretKey deriveKeyPad(String password) {
        try {
            long start = System.currentTimeMillis();
            byte[] keyBytes = new byte[KEY_LENGTH / 8];
            // explicitly fill with zeros
            Arrays.fill(keyBytes, (byte) 0x0);

            // if password is shorter then key length, it will be zero-padded
            // to key length
            byte[] passwordBytes = password.getBytes("UTF-8");
            int length = passwordBytes.length < keyBytes.length ? PasswordBytes.length
                    : keyBytes.length;
            System.arraycopy(passwordBytes, 0, keyBytes, 0, length);

            SecretKey result = new SecretKeySpec(keyBytes, "AES");
            long elapsed = System.currentTimeMillis() - start;
            Log.d(TAG, String.format("Padding key derivation took %d [ms].",
                    elapsed));

            return result;
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    // Illustration code only: don't use in production!
    public static SecretKey deriveKeySha1prng(String password) {
        try {
            long start = System.currentTimeMillis();
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            byte[] seed = password.getBytes("UTF-8");
            sr.setSeed(seed);
            kgen.init(KEY_LENGTH, sr);

            SecretKey result = kgen.generateKey();
            long elapsed = System.currentTimeMillis() - start;
            Log.d(TAG, String.format("SHA1PRNG key derivation took %d [ms].",
                    elapsed));

            return result;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static SecretKey deriveKeyPkcs12(byte[] salt, String password) {
        try {
            long start = System.currentTimeMillis();
            KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt,
                    ITERATION_COUNT, KEY_LENGTH);
            SecretKeyFactory keyFactory = SecretKeyFactory
                    .getInstance(PKCS12_DERIVATION_ALGORITHM);
            SecretKey result = keyFactory.generateSecret(keySpec);
            long elapsed = System.currentTimeMillis() - start;
            Log.d(TAG, String.format("PKCS#12 key derivation took %d [ms].",
                    elapsed));

            return result;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }

    public static SecretKey deriveKeyPbkdf2(byte[] salt, String password) {
        try {
            long start = System.currentTimeMillis();
            KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt,
                    ITERATION_COUNT, KEY_LENGTH);
            SecretKeyFactory keyFactory = SecretKeyFactory
                    .getInstance(PBKDF2_DERIVATION_ALGORITHM);
            byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
            Log.d(TAG, "key bytes: " + toHex(keyBytes));

            SecretKey result = new SecretKeySpec(keyBytes, "AES");
            long elapsed = System.currentTimeMillis() - start;
            Log.d(TAG, String.format("PBKDF2 key derivation took %d [ms].",
                    elapsed));

            return result;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] generateIv(int length) {
        byte[] b = new byte[length];
        random.nextBytes(b);

        return b;
    }

    public static byte[] generateSalt() {
        byte[] b = new byte[PKCS5_SALT_LENGTH];
        random.nextBytes(b);

        return b;
    }

    public static String encryptPkcs12(String plaintext, SecretKey key,
            byte[] salt) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            PBEParameterSpec pbeSpec = new PBEParameterSpec(salt,
                    ITERATION_COUNT);
            cipher.init(Cipher.ENCRYPT_MODE, key, pbeSpec);
            Log.d(TAG, "Cipher IV: " + toHex(cipher.getIV()));
            byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));

            return String.format("%s%s%s", toBase64(salt), DELIMITER,
                    toBase64(cipherText));
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String encrypt(String plaintext, SecretKey key, byte[] salt) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            byte[] iv = generateIv(cipher.getBlockSize());
            Log.d(TAG, "IV: " + toHex(iv));
            IvParameterSpec ivParams = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
            Log.d(TAG, "Cipher IV: "
                    + (cipher.getIV() == null ? Null : toHex(cipher.getIV())));
            byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));

            if (salt != null) {
                return String.format("%s%s%s%s%s", toBase64(salt), DELIMITER,
                        toBase64(iv), DELIMITER, toBase64(cipherText));
            }

            return String.format("%s%s%s", toBase64(iv), DELIMITER,
                    toBase64(cipherText));
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String toHex(byte[] bytes) {
        StringBuffer buff = new StringBuffer();
        for (byte b : bytes) {
            buff.append(String.format("%02X", b));
        }

        return buff.toString();
    }

    public static String toBase64(byte[] bytes) {
        return Base64.encodeToString(bytes, Base64.NO_WRAP);
    }

    public static byte[] fromBase64(String base64) {
        return Base64.decode(base64, Base64.NO_WRAP);
    }

    public static String decryptPkcs12(byte[] cipherBytes, SecretKey key,
            byte[] salt) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            PBEParameterSpec pbeSpec = new PBEParameterSpec(salt,
                    ITERATION_COUNT);
            cipher.init(Cipher.DECRYPT_MODE, key, pbeSpec);
            Log.d(TAG, "Cipher IV: " + toHex(cipher.getIV()));
            byte[] plainBytes = cipher.doFinal(cipherBytes);
            String plainrStr = new String(plainBytes, "UTF-8");

            return plainrStr;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String decrypt(byte[] cipherBytes, SecretKey key, byte[] iv) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec ivParams = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, key, ivParams);
            Log.d(TAG, "Cipher IV: " + toHex(cipher.getIV()));
            byte[] plaintext = cipher.doFinal(cipherBytes);
            String plainrStr = new String(plaintext, "UTF-8");

            return plainrStr;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String decryptPkcs12(String ciphertext, String password) {
        String[] fields = ciphertext.split(DELIMITER);
        if (fields.length != 2) {
            throw new IllegalArgumentException("Invalid encypted text format");
        }

        byte[] salt = fromBase64(fields[0]);
        byte[] cipherBytes = fromBase64(fields[1]);
        SecretKey key = deriveKeyPkcs12(salt, password);

        return decryptPkcs12(cipherBytes, key, salt);
    }

    public static String decryptPbkdf2(String ciphertext, String password) {
        String[] fields = ciphertext.split(DELIMITER);
        if (fields.length != 3) {
            throw new IllegalArgumentException("Invalid encypted text format");
        }

        byte[] salt = fromBase64(fields[0]);
        byte[] iv = fromBase64(fields[1]);
        byte[] cipherBytes = fromBase64(fields[2]);
        SecretKey key = deriveKeyPbkdf2(salt, password);

        return decrypt(cipherBytes, key, iv);
    }

    public static String decryptNoSalt(String ciphertext, SecretKey key) {
        String[] fields = ciphertext.split(DELIMITER);
        if (fields.length != 2) {
            throw new IllegalArgumentException("Invalid encypted text format");
        }
        byte[] iv = fromBase64(fields[0]);
        byte[] cipherBytes = fromBase64(fields[1]);

        return decrypt(cipherBytes, key, iv);
    }

}

logcat位于

之下
FATAL EXCEPTION: main
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           Process: com.mycompany.myapp, PID: 3945
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mycompany.myapp/com.mycompany.myapp.MainActivity}: java.lang.RuntimeException: javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2205)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2255)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.ActivityThread.access$800(ActivityThread.java:142)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1203)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.os.Handler.dispatchMessage(Handler.java:102)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.os.Looper.loop(Looper.java:136)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.ActivityThread.main(ActivityThread.java:5118)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at java.lang.reflect.Method.invoke(Native Method)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:610)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           Caused by: java.lang.RuntimeException: javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.mycompany.myapp.MCrypt.decryptPkcs12(MCrypt.java:256)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.mycompany.myapp.MCrypt.decryptPkcs12(MCrypt.java:289)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.mycompany.myapp.MainActivity.onCreate(MainActivity.java:33)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.Activity.performCreate(Activity.java:5275)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2169)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           ... 9 more
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           Caused by: javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.android.org.conscrypt.OpenSSLCipher.doFinalInternal(OpenSSLCipher.java:420)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:456)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at javax.crypto.Cipher.doFinal(Cipher.java:1204)
10-06 19:16:46.236 3945 3945 E     AndroidRuntime com.mycompany.myapp           at com.mycompany.myapp.MCrypt.decryptPkcs12(MCrypt.java:251)

1 个答案:

答案 0 :(得分:0)

您有一个UnsupportedEncodingException。我怀疑这是因为您正在尝试将加密的密文分配给字符串。如果要将Cyphertext视为字符串,则应将其视为字节数据或使用Base64进行编码。您需要检查MCrypt.encryptPkcs12()方法给您的回报类型。

如果您使用Base64,请务必在解密之前将其从Base64字符串转换回字节。