Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java.Lang.UnsupportedOperationException: 'For encrypted files, please open the relevant FileInput/FileOutputStream.' #405

Open
AlexanderVolkovDA opened this issue Oct 2, 2021 · 5 comments
Labels
binding-issue Java error when attempting to use bound type/method

Comments

@AlexanderVolkovDA
Copy link

AlexanderVolkovDA commented Oct 2, 2021

Version Information

  • Visual Studio version (eg. 16.8 or 8.8): 16.11.3
  • Xamarin.Android version (eg. 11.1): 11.4.0.5
  • Using AndroidX or Support Libraries:
    Xamarin.Android.Support.Design 27.0.2.1
    Xamarin.Android.Support.v4 27.0.2.1
    Xamarin.Android.Support.v7.AppCompat 27.0.2.1
    Xamarin.Android.Support.v7.CardView 27.0.2.1
    Xamarin.Android.Support.v7.MediaRouter 27.0.2.1
    Xamarin.AndroidX.AppCompat.Resources 1.1.0
    Xamarin.AndroidX.Arch.Core.Runtime 2.1.0.8
    Xamarin.AndroidX.Legacy.Support.V4 1.0.0.7
    Xamarin.AndroidX.MediaRouter 1.2.4
    Xamarin.AndroidX.Palette 1.0.07
    Xamarin.AndroidX.Security.SecurityCrypto 1.0.0.3
  • If Support Libraries, version (eg 28.0.0): 27.0.2.1

Describe your Issue:

When trying to open encrypted stream to read file with AndroidX.Security.Crypto.EncryptedFile.OpenFileInput() exception Java.Lang.UnsupportedOperationException with message: 'For encrypted files, please open the relevant FileInput/FileOutputStream.' is thrown

Steps to Reproduce (with link to sample solution if possible):

        string masterKeyAlias = MasterKeys.GetOrCreate(MasterKeys.Aes256GcmSpec);
        Java.IO.File file = new File(Android.App.Application.Context.FilesDir, Settings.Settings.DataFileName);
        bool fileExists = file.Exists();
        if (fileExists)
        {
            file.Delete();
        }

        AndroidX.Security.Crypto.EncryptedFile.Builder builder = new EncryptedFile.Builder(
            file,
            Android.App.Application.Context,
            masterKeyAlias,
            EncryptedFile.FileEncryptionScheme.Aes256GcmHkdf4kb);
        AndroidX.Security.Crypto.EncryptedFile encryptedFile = builder.Build();

        using (System.IO.Stream output = encryptedFile.OpenFileOutput())
        {
            await output.WriteAsync(Encoding.UTF8.GetBytes("Just sample text"));
        }

        using (System.IO.Stream input = encryptedFile.OpenFileInput())
        {
            int notReachable = input.ReadByte();
        }

Include any relevant Exception Stack traces, build logs, adb logs:

  at Java.Interop.JniEnvironment+InstanceMethods.CallObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0006e] in <bd6bd528a8784b7caf03e9f25c9f0d7b>:0 
  at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0002a] in <bd6bd528a8784b7caf03e9f25c9f0d7b>:0 
  at Java.IO.FileInputStream.get_Channel () [0x00000] in /Users/builder/azdo/_work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-30/mcw/Java.IO.FileInputStream.cs:160 
  at Android.Runtime.InputStreamInvoker..ctor (Java.IO.InputStream stream) [0x00025] in /Users/builder/azdo/_work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/InputStreamInvoker.cs:21 
  at (wrapper remoting-invoke-with-check) Android.Runtime.InputStreamInvoker..ctor(Java.IO.InputStream)
  at Android.Runtime.InputStreamInvoker.FromJniHandle (System.IntPtr handle, Android.Runtime.JniHandleOwnership transfer) [0x00035] in /Users/builder/azdo/_work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/InputStreamInvoker.cs:168 
  at AndroidX.Security.Crypto.EncryptedFile.OpenFileInput () [0x00018] in D:\a\1\s\generated\androidx.security.security-crypto\obj\Release\monoandroid9.0\generated\src\AndroidX.Security.Crypto.EncryptedFile.cs:223 
  at ProactisMobileApp.Data.ExpenseData.WriteDataFile (System.String text) [0x00227] in D:\Work\Projects\Proactis\MobileApp\ProactisMobileApp\ProactisMobileApp\ProactisMobileApp\Data\ExpenseData.cs:324 
  --- End of managed Java.Lang.UnsupportedOperationException stack trace ---
java.lang.UnsupportedOperationException: For encrypted files, please open the relevant FileInput/FileOutputStream.
    at androidx.security.crypto.EncryptedFile$EncryptedFileInputStream.getChannel(EncryptedFile.java:319)
    at mono.java.lang.RunnableImplementor.n_run(Native Method)
    at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:30)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:235)
    at android.app.ActivityThread.main(ActivityThread.java:7441)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
@AlexanderVolkovDA
Copy link
Author

AlexanderVolkovDA commented Oct 2, 2021

Tried to investigate the issue. Have a guess that it is connected to mapping of Java androidx.security.crypto.EncryptedFile.openFileOutput() return type from FileInputStream to System.IO.Stream. Somewhere in initialization it calls FileInputStream.getChannel() that throws the exception.
But FileInputStream.getChannel() looks like this:

    @Override
    public FileChannel getChannel() {
        throw new UnsupportedOperationException("For encrypted files, please open the "
                + "relevant FileInput/FileOutputStream.");
    }

@moljac
Copy link
Member

moljac commented Oct 5, 2021

Are you using Android.Support?

@moljac
Copy link
Member

moljac commented Oct 5, 2021

Tried to investigate the issue. Have a guess that it is connected to mapping of Java androidx.security.crypto.EncryptedFile.openFileOutput() return type from FileInputStream to System.IO.Stream. Somewhere in initialization it calls FileInputStream.getChannel() that throws the exception. But FileInputStream.getChannel() looks like this:

    @Override
    public FileChannel getChannel() {
        throw new UnsupportedOperationException("For encrypted files, please open the "
                + "relevant FileInput/FileOutputStream.");
    }

True. So, this is not issue with the bindings.

You need to see what must be done in java or kotlin (native) and then port that code. This exception would happen with java or kotlin.

@AlexanderVolkovDA
Copy link
Author

this is not issue with the bindings.

I thought that the issue is in mapping to general System.IO.Stream class instead more specific one (that is used in native).

You need to see what must be done in java or kotlin (native) and then port that code.

That's exactly what I've tried to do.
In java/kotlin call of androidx.security.crypto.EncryptedFile.openFileOutput() does not lead to call of FileInputStream.getChannel(). But in C# it does.

From android documentation sample usage is:
https://developer.android.com/reference/androidx/security/crypto/EncryptedFile

  String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);

  File file = new File(context.getFilesDir(), "secret_data");
  EncryptedFile encryptedFile = EncryptedFile.Builder(
      file,
      context,
      masterKeyAlias,
      EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
  ).build();

  // write to the encrypted file
  FileOutputStream encryptedOutputStream = encryptedFile.openFileOutput();

  // read the encrypted file
  FileInputStream encryptedInputStream = encryptedFile.openFileInput();

So, as you can see in steps to reproduce, I tried to do the same in my code (just added small file existence check, usings and explicit types), but opening the file always throws this exception.

Maybe you could introduce FileInputStream class, similar to native one with no getChannel() call on file open?

Are you using Android.Support?

Yes, we use some:

Xamarin.Android.Support.Design 27.0.2.1
Xamarin.Android.Support.v4 27.0.2.1
Xamarin.Android.Support.v7.AppCompat 27.0.2.1
Xamarin.Android.Support.v7.CardView 27.0.2.1
Xamarin.Android.Support.v7.MediaRouter 27.0.2.1

@rgroenewoudt
Copy link

I'm running into the same issue with the latest 1.1.0-alpha05.

@jpobst jpobst added binding-issue Java error when attempting to use bound type/method and removed packages labels Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
binding-issue Java error when attempting to use bound type/method
Projects
None yet
Development

No branches or pull requests

4 participants