【问题标题】:Encrypt/Decrypt database file in Android with FileInputStream/Cipher使用 FileInputStream/Cipher 在 Android 中加密/解密数据库文件
【发布时间】:2016-09-25 00:17:14
【问题描述】:

我正在使用 Cipher/CipherInputStream 加密和解密 Android 中的数据库文件 (sqlite) 以备份它。
当我使用没有密码的 FileInputStream 时,它工作得很好。但是当我使用密码时,文件加密成功,但是当我解密(恢复)它时,数据库不会解密为原始的“源代码”。
原来的字符(源代码)好像是象形文字/象形文字/汉字(我不知道),而我加解密的时候,“源代码”是sql(english)还原的O.O
这使得“数据库损坏”

只是为了澄清

备份

File dbFile = new File(PATH_DB);

FileInputStream fileInputStream = new FileInputStream(PATH_DB);

FileOutputStream outputStream = new FileOutputStream(PATH_BKP);

byte[] s = Arrays.copyOf(KEY_DATABASE.getBytes(),16);
SecretKeySpec sks = new SecretKeySpec(s, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, sks);

CipherOutputStream cos = new CipherOutputStream(outputStream, cipher);

//Transferencia dos dados do inputfile para o output
byte[] buffer = new byte[1024];
int length;
while ((length = fileInputStream.read(buffer))!= -1) {
    cos.write(buffer,0,length);
}

//Fecha as streams
cos.flush();
cos.close();
fileInputStream.close();

恢复:

FileInputStream fis = new FileInputStream(PATH_BKP);

FileOutputStream fos = new FileOutputStream(PATH_DB);

byte[] s = Arrays.copyOf(KEY_DATABASE.getBytes(),16);
SecretKeySpec sks = new SecretKeySpec(s, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, sks);

CipherInputStream cis = new CipherInputStream (fis, cipher);

byte[] buffer = new byte[1024];
int length;
while ((length = cis.read(buffer)) != -1) {
    fos.write(buffer, 0, length);
}

fos.flush();
fos.close();
cis.close();

【问题讨论】:

    标签: android sqlite encryption cryptography


    【解决方案1】:

    CBC 模式需要一个初始化向量 (IV) 才能运行。这个 IV 不是一个秘密值,但它必须是不可预测的(阅读:随机选择)。为了使解密工作,您必须使用相同的 IV。否则,第一个块将被破坏。解决这个问题的常用方法是在密文前面写IV。

    如果您在没有 IvParameterSpec 作为第三个参数的情况下调用 Cipher#init,则会自动为您生成 IV。如果你不保存它,它就会丢失。

    加密期间

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.ENCRYPT_MODE, sks);
    
    outputStream.write(cipher.getIV()); // store the generated IV
    
    CipherOutputStream cos = new CipherOutputStream(outputStream, cipher);
    

    解密过程中

    byte[] iv = new byte[16]; // 16 is the block size of AES
    if (fis.read(iv) != 16) {
        throw new Exception("Incomplete IV"); // TODO: rename to a different exception
    }
    
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.DECRYPT_MODE, sks, new IvParameterSpec(iv));
    
    CipherInputStream cis = new CipherInputStream (fis, cipher);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-18
      • 2011-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      • 2015-01-13
      相关资源
      最近更新 更多