tink
tink copied to clipboard
No matching key found for the ciphertext in the stream.
Hi, I am using jetpack security encryption library for encrypting the file. I have generate Master Key with below code.
MasterKey masterKey = null; try { masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); } catch (GeneralSecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
I have encrypted my text file Sample.txt and write encrypted file to device external storage. The code as given below.
InputStream inputStream = new BufferedInputStream(appCtx.getAssets().open("Sample.txt")); byte[] fileBytes=new byte[inputStream.available()]; inputStream.read(fileBytes); File file = new File(Environment.getExternalStorageDirectory(), "Sample.txt"); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { EncryptedFile encryptedFile = new EncryptedFile.Builder( appCtx, file, masterKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); OutputStream outputStream = encryptedFile.openFileOutput(); outputStream.write(fileBytes); outputStream.flush(); outputStream.close();
I put encrypted file in asset folder and now trying to decrypt but as per documentation EncryptedFile.Builder always have file Object as parameter and currently i have Inputstream after reading file from asset. So, to get file object i am writing this Inutstream to external storage as Temp.txt and passing this file for decryption. But I am getting exception as java.io.IOException: No matching key found for the ciphertext in the stream.
The code for decryption as follows:
InputStream myInputstream = new BufferedInputStream(appCtx.getAssets().open("Sample.txt")); File enfile = createFileFromInputStream(myInputstream,appCtx); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { EncryptedFile encryptedFile = new EncryptedFile.Builder( appCtx, enfile, masterKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); InputStream inputStream1 = encryptedFile.openFileInput(); BufferedOutputStream os1 = new BufferedOutputStream( new FileOutputStream(new File(dstPath))); int length = 0; byte[] buffer = new byte[1024]; while ((length = inputStream1.read(buffer)) != -1) { os1.write(buffer, 0, length); } os1.close(); }
private static File createFileFromInputStream(InputStream stream, Context context) { File f = new File(Environment.getExternalStorageDirectory(), "Temp.txt"); BufferedOutputStream os1 = null; try { os1 = new BufferedOutputStream( new FileOutputStream(f)); int length = 0; byte[] buffer = new byte[1024]; while ((length = stream.read(buffer)) != -1) { os1.write(buffer, 0, length); } os1.close(); stream.close(); return f; } catch (FileNotFoundException e) { e.printStackTrace(); }catch (IOException e) { //Logging exception } return null; }
Scenario: If write encrypted file to external storage and read it for decryption directly from external storage, then everything is working file. But If i paste encrypted file in asset folder and write Inputstream getting from asset folder to some temporary file and then try to decrypt it is giving error java.io.IOException: No matching key found for the ciphertext in the stream.
please anyone help me with this issue. Thanks
@tholenst @chuckx
Acknowledged. I haven't got cycles to take a closer look, CC a few folks who might be able to assist.
encrypt an decrypt should use same KeysetHandle and ADD..
Update: I know what was wrong. I forgot to flush the output when writing. After adding it, everything works.
@1004145468 What do you mean by same KeysetHandle and ADD? I'm having the same issue, although I'm reading and saving files.
Here is my code for saving:
fun save(context: Context, name: String, dir: String, source: Any) : Boolean {
var realName = name
val masterKeyAlias = MasterKey.Builder(
context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
var file = File(context.filesDir.path + dir, realName)
// Check if file doesn't yet exist and change filename if necessary
var changes: Boolean
do {
changes = false
if (file.exists()) {
realName += ".1"
file = File(context.filesDir.path + dir, realName)
changes = true
}
} while (changes)
// Create missing directories
if (!file.parentFile!!.exists()) {
file.parentFile!!.mkdirs()
}
val encryptedFile = EncryptedFile.Builder(
context,
file,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
val encryptedOutputStream = encryptedFile.openFileOutput()
val objectOutputStream = ObjectOutputStream(encryptedOutputStream)
objectOutputStream.writeObject(source)
// Added this
// Close streams
objectOutputStream.close()
encryptedOutputStream.flush()
encryptedOutputStream.close()
return true
}
And here is how I'm reading it:
fun get(context: Context, dir: String) : Array<Any> {
val directory = File(context.filesDir.path + dir)
if (directory.exists() && directory.isDirectory) {
val files = directory.listFiles()
val masterKeyAlias = MasterKey.Builder(
context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val list = mutableListOf<Any>()
files?.forEach {
ArchipelagoError.d(it.path)
val encryptedFile = EncryptedFile.Builder(
context,
it,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
val encryptedInputStream = encryptedFile.openFileInput()
val objectInputStream = ObjectInputStream(encryptedInputStream)
val sourceObject = objectInputStream.readObject()
list.add(sourceObject)
}
return list.toTypedArray()
} else {
return arrayOf()
}
}
It's in kotlin for Android of course
Edit: ~~Or is the issue that I'm using objectStreams and I should be writing and reading byteArrays?~~ It's not, I checked
@Kwasow Thanks for that, it worked. I was having the same issue! :D
@Kwasow As I can see you have read file from directory but the main issue is we are unable to read file from assets in android. When I tried to read, I got this issue 'No matching key found for the ciphertext in the stream' . I have copied the file from assets to filesDir to get the File object so that it can be passed to EncryptedFile.Builder constructor, but no luck. Can anyone help. Stuck in this issue from last 3 days. Thanks in advance.
Okay thanks, everyone. Finally got the solution. If anyone faces this same issue then make sure the following things:-
- Update to the latest version of the library.
- The file that will be copied from assets to the external files directory must have the same name as that of the original encrypted file at the time of encryption otherwise it will not work and throw the same error. (This point I was missing. After so many efforts I came to know this. Maybe this is a kind of bug or maybe not.)
@mittalkartik1 @Kwasow Does this issue solved for you ? My Condition is below:
- Encrypt File using custom key alias
- Save file to external directory
- Uninstall and reinstall the same application.
- While reading the saved file with same key alias , i got this error " No matching key found for the ciphertext in the stream."
Any ideas ???
@mittalkartik1 @Kwasow Does this issue solved for you ? My Condition is below:
- Encrypt File using custom key alias
- Save file to external directory
- Uninstall and reinstall the same application.
- While reading the saved file with same key alias , i got this error " No matching key found for the ciphertext in the stream."
Any ideas ???
If you're talking about an Android application then the accosiated key is stored in SharedPreferences and it is cleared on app uninstall, so there is no key to be found.
@mittalkartik1 @Kwasow Does this issue solved for you ? My Condition is below:
- Encrypt File using custom key alias
- Save file to external directory
- Uninstall and reinstall the same application.
- While reading the saved file with same key alias , i got this error " No matching key found for the ciphertext in the stream."
Any ideas ???
If you're talking about an Android application then the accosiated key is stored in SharedPreferences and it is cleared on app uninstall, so there is no key to be found.
Is there a way to retrive the accosiated key from SharedPreferences ?
@mittalkartik1 @Kwasow Does this issue solved for you ? My Condition is below:
- Encrypt File using custom key alias
- Save file to external directory
- Uninstall and reinstall the same application.
- While reading the saved file with same key alias , i got this error " No matching key found for the ciphertext in the stream."
Any ideas ???
This approach cannot be used in your case. If you clear app data or reinstall app, then encryption keys will be deleted and next time keys will regenerate. You can retrieve the keys from shared preferences, but if you store them somewhere else, then also they cannot be used as android will regenarate keys everytime on app install making old keys invalid. So, this approach can only be used if want to store encrypted data in file after app install and want to use that until app uninstall or clearing data. (In short for managing specific user session.)
I am getting the same error while decrypting the file. error happening in val fileInputStream = ObjectInputStream(encryptedFile.openFileInput())
`fun encryptFile(source: File, destination: File, applicationContext: Context) {
val mainKey = MasterKey.Builder(applicationContext, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val encryptedFile = EncryptedFile.Builder(
applicationContext,
destination,
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
val fileOutputStream = encryptedFile.openFileOutput()
val fileInputStream = FileInputStream(source)
val buffer = ByteArray(1024)
var read: Int
while (fileInputStream.read(buffer).also { read = it } != -1) {
fileOutputStream.write(buffer, 0, read)
}
fileInputStream.close()
fileOutputStream.flush()
fileOutputStream.close()
source.delete()
destination.renameTo(source)
}
fun decryptFile(source: File, destination: File, applicationContext: Context){
val mainKey = MasterKey.Builder(applicationContext, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val encryptedFile = EncryptedFile.Builder(
applicationContext,
source,
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
val fileInputStream = ObjectInputStream(encryptedFile.openFileInput())
val fileOutputStream = BufferedOutputStream(FileOutputStream(destination))
val buffer = ByteArray(1024)
var read: Int
while (fileInputStream.read(buffer).also { read = it } != -1) {
fileOutputStream.write(buffer, 0, read)
}
fileInputStream.close()
fileOutputStream.flush()
fileOutputStream.close()
source.delete()
destination.renameTo(source)
}`
Okay thanks, everyone. Finally got the solution. If anyone faces this same issue then make sure the following things:-
- Update to the latest version of the library.
- The file that will be copied from assets to the external files directory must have the same name as that of the original encrypted file at the time of encryption otherwise it will not work and throw the same error. (This point I was missing. After so many efforts I came to know this. Maybe this is a kind of bug or maybe not.)
I am hit hard by this hidden behavior when upgrading androidx.security.
must have the same name as that of the original encrypted file at the time of encryption otherwise it will not work
In order to support API level 21, I updated my project with this alpha release:
androidx.security:security-crypto:1.1.0-alpha03
and migrate my code to use the new API with "MasterKey". Then my code began to fail, but only with reading part.
I have tried a lot of ways, only the above hint saved my day at last.
In the old code, I first create a temp file, save the content as encrypted in this temp file, and if all goes well, I will rename the temp file with a desired one.
This code path worked well with demo code from "androidx.security:security-crypto:1.0.0", but after the upgrade, it began to fail with "No matching key" exceptions.
Hint by the discussion here, I just left the file name unchanged after encryption, then the reading part works. Hopefully if the alpha version released, either the document can be updated to reflect this requirement, or the old behavior can be kept.
Okay thanks, everyone. Finally got the solution. If anyone faces this same issue then make sure the following things:-
- Update to the latest version of the library.
- The file that will be copied from assets to the external files directory must have the same name as that of the original encrypted file at the time of encryption otherwise it will not work and throw the same error. (This point I was missing. After so many efforts I came to know this. Maybe this is a kind of bug or maybe not.)
Thank you! It saved me a lot of time.
I've recently encountered this problem but unlike others that have had this issue, I am not using the assets
folder or moving the EncryptedFile
between directories. I also cannot reproduce it but see it showing up occasionally in non-fatal crash logs.
Encrypting:
val fileToWrite = File(baseDir, UUID.randomUUID().toString())
val encryptedFile = EncryptedFile.Builder(
context,
fileToWrite,
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB).build()
encryptedFile.openFileOutput().use {
val inputStream = FileInputStream(file)
inputStream.copyTo(it)
it.flush()
}
Decrypting:
val tmpFile = File(baseDir, "${UUID.randomUUID()}.pdf")
val encryptedFile = EncryptedFile.Builder(
context,
File(path),
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
encryptedFile.openFileInput().use { input ->
FileOutputStream(tmpFile).use { output ->
input.copyTo(output)
output.flush()
}
}
The exception comes from the input.copyTo(output)
line when decrypting.
Both methods use the same key and relative base path. Since I can't reproduce it I'm shooting in the dark -- does the file name for the file that it is being decrypted to need to be the same as what the encrypted file name was?
On Mon, Mar 7, 2022, 10:53 AM Luca Ventura @.***> wrote:
I've recently encountered this problem but unlike others that have had this issue, I am not using the assets folder or moving the EncryptedFile between directories. I also cannot reproduce it but see it showing up occasionally in crash logs.
Encrypting:
`val fileToWrite = File(baseDir, UUID.randomUUID().toString()) val encryptedFile = EncryptedFile.Builder( context, fileToWrite, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build()
encryptedFile.openFileOutput().use { val inputStream = FileInputStream(file) inputStream.copyTo(it) it.flush() }`
Decrypting:
`val encryptedFile = EncryptedFile.Builder( context, File(path), mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build()
encryptedFile.openFileInput().use { input -> FileOutputStream(tmpFile).use { output -> input.copyTo(output) output.flush() } }`
Both use the same key and relative base path. Since I can't reproduce it I'm shooting in the dark -- does the file name for the file that it is being decrypted to need to be the same as what the encrypted file name was?
Yes. If you move the file it won't be decrypted correctly.
— Reply to this email directly, view it on GitHub https://github.com/google/tink/issues/401#issuecomment-1061017946, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAB23HNNGR6UUCSXZBKRWDU6ZGA3ANCNFSM4PHUMTFQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
You are receiving this because you commented.Message ID: @.***>
@thaidn The EncryptedFile
is never actually moved though, it always stays in the same directory. Even when I decrypt it to a new file of the same name it doesn't resolve the issue (this is an extreme edge case right now, and is only happening like .1% of the time).
There were some race conditions in the AndroidKeysetManager that have been fixed. I think if you use lastest version of androidx security crypto, 1.1.0-alpha06, https://developer.android.com/jetpack/androidx/releases/security#security-crypto-1.1.0-alpha06 the issue should hopefully be resolved.