web-dev-qa-db-ja.com

Androidでファイルを暗号化および復号化する方法は?

ファイルを暗号化し、SDカードに保存したい。暗号化されたファイルを復号化し、SDカードに再度保存したいです。ファイルストリームとして開くことでファイルを暗号化しようとしましたが、暗号化は機能しますが、機能しません。これを行う方法についてのアイデアが欲しい。

64
Pratik

CipherOutputStream または CipherInputStreamCipherと一緒に使用し、 FileInputStream / FileOutputStream

Cipherクラスを作成するには、Cipher.getInstance("AES/CBC/PKCS5Padding")のようなものをお勧めします。 CBCモードは安全であり、 非ランダムプレーンテキストに対するECBモードの脆弱性 はありません。汎用の暗号化ライブラリに存在し、高い互換性を確保する必要があります。

同じキーで複数のファイルを暗号化する場合は、 初期化ベクトル (IV) セキュアランダムジェネレーター によって生成されることを忘れないでください。暗号文の先頭にプレーンIVのプレフィックスを付けることができます。サイズは常に正確に1ブロック(16バイト)です。

パスワードを使用する場合は、適切なキー派生メカニズムを使用してください(パスワードベースの暗号化またはパスワードベースのキー派生を調べてください)。 PBKDF2は最も一般的に使用されるパスワードベースのキー派生スキームであり、Androidを含む ほとんどのJava runtimes に存在します。SHA-1は少し古いハッシュ関数であることに注意してください。 、しかしPBKDF2では問題ないはずで、現在最も互換性のあるオプションを提供しています。

文字列をエンコード/デコードするときは常に文字エンコードを指定します。そうしないと、プラットフォームのエンコードが以前のものと異なる場合に問題が発生します。つまり、String.getBytes()を使用せず、 String.getBytes(StandardCharsets.UTF_8) を使用します。

セキュリティを強化するには、暗号化テキストとIVに安全なチェックサム(MACまたはHMAC)を追加し、できれば別のキーを使用して、暗号の整合性と信頼性を追加してください。認証タグがなければ、暗号文は変更を検出できないような方法で変更される可能性があります。

CipherInputStreammayBadPaddingExceptionを報告せず、これにはGCMなどの認証された暗号用に生成されたBadPaddingExceptionが含まれます。これにより、これらの種類の認証された暗号のストリームは互換性がなくなり、安全ではなくなります。

63
Maarten Bodewes

私は同様の問題を抱えていましたが、暗号化/復号化のために私はこの解決策を思いつきました:

public static byte[] generateKey(String password) throws Exception
{
    byte[] keyStart = password.getBytes("UTF-8");

    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
    sr.setSeed(keyStart);
    kgen.init(128, sr);
    SecretKey skey = kgen.generateKey();
    return skey.getEncoded();
}

public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
{

    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(fileData);

    return encrypted;
}

public static byte[] decodeFile(byte[] key, byte[] fileData) throws Exception
{
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);

    byte[] decrypted = cipher.doFinal(fileData);

    return decrypted;
}

暗号化されたファイルをsdに保存するには:

File file = new File(Environment.getExternalStorageDirectory() + File.separator + "your_folder_on_sd", "file_name");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] yourKey = generateKey("password");
byte[] filesBytes = encodeFile(yourKey, yourByteArrayContainigDataToEncrypt);
bos.write(fileBytes);
bos.flush();
bos.close();

ファイルをデコードするには:

byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);

ファイルをバイト配列に読み込むには、別の方法があります。例: http://examples.javacodegeeks.com/core-Java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/

50
ZeroTek

Java-aes-crypto または Facebook's Conceal を使用できます

Java-aes-crypto

レポからの引用

単純なAndroid文字列の暗号化と暗号化解除のためのクラス。ほとんどのクラスが被る古典的な間違いを避けることを目指しています。

Facebookの隠蔽

レポからの引用

隠蔽は、データの高速暗号化と認証を実行するための簡単なAndroid APIを提供します

0
user158