2014-10-06 80 views
1

有人可以帮我使用我希望用于我的项目的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) 
+0

先发表您的看法? – Gattsu 2014-10-06 11:31:37

+0

对不起。我已经附上了代码。顺便说一句,我只是想测试代码并在我自己的项目中实现它。谢谢 – 2014-10-06 12:04:01

回答

0

您有一个UnsupportedEncodingException。我怀疑这是因为你试图将加密的密文分配给一个字符串。如果要将其视为字符串,则应将连字符视为字节数据或使用Base64编码。你需要检查MCrypt.encryptPkcs12()方法给你什么样的回报。

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

+0

这里是从decryptPKCS12方法 byte [] salt = fromBase64(fields [0]); byte [] cipherBytes = fromBase64(fields [1]); ..arent他们足以将字符串转换为base64? – 2014-10-06 14:10:06

+0

这不是解密,而是加密。您正在直接对字符串进行加密。试图将原始字节视为字符串会导致格式错误。或者,您需要在两侧明确指定字符串格式。 – rossum 2014-10-06 15:23:33

+0

对不起,但根据我所了解的,encryptPKCS方法返回字符串格式 return String.format(“%s%s%s”,toBase64(salt),DELIMITER,toBase64(cipherText)); ..也是它然后用此方法将cipherText转换为base64 public static String toBase64(byte [] bytes){return Base64.encodeToString(bytes,Base64.NO_WRAP); .. – 2014-10-06 22:52:10