Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/235.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 应用程序重新启动时加密密钥是否更改?_Java_Android_Encryption_Gson_Aes - Fatal编程技术网

Java 应用程序重新启动时加密密钥是否更改?

Java 应用程序重新启动时加密密钥是否更改?,java,android,encryption,gson,aes,Java,Android,Encryption,Gson,Aes,我正在尝试加密一些视频,然后在需要时解密它们。代码工作正常,但由于密钥是随机生成的,如果我加密视频并退出应用程序,我将无法再次解密,因为下次打开应用程序时密钥会发生更改。我正在使用Gson保存我的钥匙。但即使这样也不起作用 下面是我的加密类代码。提前谢谢 package com.example.videoplay; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; impo

我正在尝试加密一些视频,然后在需要时解密它们。代码工作正常,但由于密钥是随机生成的,如果我加密视频并退出应用程序,我将无法再次解密,因为下次打开应用程序时密钥会发生更改。我正在使用Gson保存我的钥匙。但即使这样也不起作用

下面是我的加密类代码。提前谢谢

package com.example.videoplay;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.google.gson.Gson;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.util.Log;

public class Encrypter { 
Context contxt;
File inFile;
File outFile;
File outFile_dec;
SecretKey key;
byte[] keyData;
SecretKey key2;
byte[] iv;
AlgorithmParameterSpec paramSpec;

private final static int IV_LENGTH = 16; // Default length with Default 128
                                            // key AES encryption 
private final static int DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE = 1024;

private final static String ALGO_RANDOM_NUM_GENERATOR = "SHA1PRNG";
private final static String ALGO_SECRET_KEY_GENERATOR = "AES";
private final static String ALGO_VIDEO_ENCRYPTOR = "AES/CBC/PKCS5Padding";

public static String str_key,str_paramSpec,str_key2;

@SuppressWarnings("resource") 
public static void encrypt(SecretKey key, AlgorithmParameterSpec paramSpec, InputStream in, OutputStream out)
        throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
        InvalidAlgorithmParameterException, IOException {
    try { 
         byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 
         0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 
         0x07, 0x72, 0x6F, 0x5A }; 
         paramSpec = new IvParameterSpec(iv); 
        Cipher c = Cipher.getInstance(ALGO_VIDEO_ENCRYPTOR);
        c.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        out = new CipherOutputStream(out, c);
        int count = 0;
        byte[] buffer = new byte[DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE];
        while ((count = in.read(buffer)) >= 0) {
            out.write(buffer, 0, count);
        } 
    } finally { 
        out.close();
    } 
} 

@SuppressWarnings("resource") 
public static void decrypt(SecretKey key, AlgorithmParameterSpec paramSpec, InputStream in, OutputStream out)
        throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
        InvalidAlgorithmParameterException, IOException {
    try { 
         byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 
         0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 
         0x07, 0x72, 0x6F, 0x5A }; 
         paramSpec = new IvParameterSpec(iv); 
        Cipher c = Cipher.getInstance(ALGO_VIDEO_ENCRYPTOR);
        c.init(Cipher.DECRYPT_MODE, key, paramSpec);
        out = new CipherOutputStream(out, c);
        int count = 0;
        byte[] buffer = new byte[DEFAULT_READ_WRITE_BLOCK_BUFFER_SIZE];
        while ((count = in.read(buffer)) >= 0) {
            out.write(buffer, 0, count);
        } 
    } finally { 
        out.close();
    } 
} 

    public Encrypter(Context ctx) {
    //      
    inFile = new File(Environment.getExternalStorageDirectory().getPath() +MainActivity.Directory+MainActivity.filename );
    outFile = new File(Environment.getExternalStorageDirectory().getPath() + MainActivity.Directory+"/"+MainActivity.temponlyfilename);
    outFile_dec = new File(Environment.getExternalStorageDirectory().getPath() + MainActivity.Directory+MainActivity.filename);

    contxt=ctx;
    try { 

        //........................................................................................

        SharedPreferences  mPrefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        String json = mPrefs.getString("pref_str_key", "empty");
        if(json.equalsIgnoreCase("empty"))
        {
            key = KeyGenerator.getInstance(ALGO_SECRET_KEY_GENERATOR).generateKey();

            keyData = key.getEncoded();
            key2 = new SecretKeySpec(keyData, 0, keyData.length, ALGO_SECRET_KEY_GENERATOR); //if you want to store key bytes to db so its just how to //recreate back key from bytes array

            iv = new byte[IV_LENGTH];
            SecureRandom.getInstance(ALGO_RANDOM_NUM_GENERATOR).nextBytes(iv); // If
                                                                                // storing 
                                                                                // separately 
            paramSpec = new IvParameterSpec(iv);

            Editor prefsEditor = mPrefs.edit();
            Gson gson = new Gson();
            str_key = gson.toJson(key);
            prefsEditor.putString("pref_str_key", str_key);
            str_key2 = gson.toJson(2);
            prefsEditor.putString("pref_str_key2", str_key2);
            prefsEditor.commit();

        }else
        {
            Gson gson = new Gson();
            str_key = mPrefs.getString("pref_str_key", "");
            key = gson.fromJson(str_key, SecretKey.class);
            str_key2 = mPrefs.getString("pref_str_key2", "");
            key2 = gson.fromJson(str_key2, SecretKey.class);
        }
        //........................................................................................

    } catch (Exception e) {
        e.printStackTrace();
    } 

}

public File Decrypt(File dir)
{
    File dirout = new File(dir.getParent()+"/temp.ts");
try {
    Encrypter.decrypt(key2, paramSpec, new FileInputStream(dir), new FileOutputStream(dirout));
    outFile_dec.delete();
} catch (Exception e) {
    e.printStackTrace();
} 
return dirout;
}

public File Encrypt(File dir) {
    File dirout = new File(dir.getParent()+"/temp.ts");
    // TODO Auto-generated method stub
    try {
        Encrypter.encrypt(key, paramSpec, new FileInputStream(dir), new FileOutputStream(dirout));
        dir.delete();
    } catch (Exception e) {
        e.printStackTrace();
    } 
    return dirout;
}




public void DecryptFromTo(File dir,File dirout)
{

try {
    Encrypter.decrypt(key2, paramSpec, new FileInputStream(dir), new FileOutputStream(dirout));

} catch (Exception e) {
    e.printStackTrace();
} 

}



} 

对于临时解决方案,我认为最好使用邓肯建议的静态键。因为即使每次都会生成新密钥,如果您将密钥存储在普通JSON文件中以供下次使用,那么将其保存在代码中并重新使用还有什么不同呢?如果有人试图获取密钥并解密视频,他/她必须调试/反汇编代码以找到静态密钥,或者只查看应用程序目录中的普通JSON密钥文件,这两项任务都不是很难完成


如果您真的关心安全性(我想这就是您首先尝试加密视频流的原因),我建议您查看并尝试使用用户端提供的用户PIN或密码对视频加密密钥进行加密和存储。

代码太多了-我们不是来为您调试的。尝试分别测试密钥存储和检索-这是否返回相同的数据?如果没有,请仅显示该代码。只需检查“Encrypter(Context ctx)”方法的try块中的代码,我正在保存密钥并检索它们。请记住,这里帮助您的人是在业余时间这样做的,只是为了好玩。为什么要给我们制造困难?向我们展示您自己已经做了一些努力——例如,您完全忽略了我的问题的一部分,即“尝试分别测试密钥存储和检索-这是否返回相同的数据?”。是的,存储和检索都返回相同的Json字符串,我觉得我遗漏了存储除两个密钥之外的其他对象。但我无法找到答案。在上述代码中是否有手动提供密钥的方法。您可以使用
new SecretKeySpec(,“AES”)
尝试使用静态密钥。您甚至可以使用
新字节[16]
作为测试密钥数据。