最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Loosing XML cryptographic tooling in android release mode of a MAUI hybrid app - Stack Overflow

programmeradmin0浏览0评论

I have a Blazor MAUI Hybrid app in .NET 9. I also have a library in that solution doing some XML signature verification. I have a null exception, but only in release mode on android.

The code is as follows:

public static ConfigRoot ValidateAndLoadSignedConfig(string signedXml, RSA publicKey)
{
    // Load the signed XML
    XmlDocument xmlDoc = new();
    xmlDoc.LoadXml(signedXml);

    // Verify the signature
    SignedXml signedXmlVerifier = new(xmlDoc);
    XmlNodeList signatureNodes = xmlDoc.GetElementsByTagName("Signature");
    
    if (signatureNodes?.Count != 1)
    {
        throw new CryptographicException("No signature");
    }

    signedXmlVerifier.LoadXml((XmlElement)signatureNodes[0]);

    if (!signedXmlVerifier.CheckSignature(publicKey)) // <<<= this row throws the exception
    {
        throw new CryptographicException("XML compromised!");
    }

    // Deserialize the validated XML to ConfigRoot
    XmlSerializer serializer = new(typeof(ConfigRoot));
    using StringReader reader = new(xmlDoc.OuterXml);

    return (ConfigRoot)serializer.Deserialize(reader);
}

The stack trace of the exception is this:

It works fine in debug mode both on the device and emulator, and I have no issues on Windows either, only on Android.

The RSA public key is correctly populated form an XML, the signed XML is loaded and the signature node is also correct.

I think something is optimized away. So I have added these to my application project's csproj:

<ItemGroup>
  <TrimmerRootAssembly Include="System.Security.Cryptography.Xml" RootMode="All" />
  <TrimmerRootAssembly Include="System.Security.Cryptography.Pkcs" RootMode="All" />
</ItemGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-android|AnyCPU'">
    <AndroidPackageFormat>apk</AndroidPackageFormat>
    <AndroidEnableR8>true</AndroidEnableR8>
    <AndroidLinkTool>r8</AndroidLinkTool>
    <AndroidProguardConfig>proguard.cfg</AndroidProguardConfig>
    <DebugType>portable</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <AndroidLinkMode>SdkOnly</AndroidLinkMode>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net9.0-android'">
  <ProguardConfiguration Include="Platforms\Android\proguard.cfg" />
</ItemGroup>

With this proguard.cfg (I have to admit, I have no clue what I am doing here related to the android linker and optimizer. All of it was suggested by AI and/or found online - make sense, but no difference):

    -keep class androidx.security.crypto.** { *; }
    -keep class com.google.crypto.tink.** { *; }
    
    # Keep all classes in System.Security.Cryptography.Xml
    -keep class System.Security.Cryptography.Xml.** { *; }
    
    # Keep classes used by SignedXml and RSA
    -keep class System.Security.Cryptography.Xml.SignedXml { *; }
    -keep class System.Security.Cryptography.Xml.RSAPKCS1SignatureDescription { *; }
    
    # Keep XML serialization classes (if used)
    -keep class System.Xml.** { *; }

But it makes no difference...

[Solved]

Right after posting this I found this one on github:

It was promisingly similar, hence I have added System.Security.Cryptography to my TrimRootAssembly list, and it worked. I might fine-tune later with the TrimmerRootDescriptor, but for now, I am happy with what I have. I have also removed all the android linker related stuff.

I have a Blazor MAUI Hybrid app in .NET 9. I also have a library in that solution doing some XML signature verification. I have a null exception, but only in release mode on android.

The code is as follows:

public static ConfigRoot ValidateAndLoadSignedConfig(string signedXml, RSA publicKey)
{
    // Load the signed XML
    XmlDocument xmlDoc = new();
    xmlDoc.LoadXml(signedXml);

    // Verify the signature
    SignedXml signedXmlVerifier = new(xmlDoc);
    XmlNodeList signatureNodes = xmlDoc.GetElementsByTagName("Signature");
    
    if (signatureNodes?.Count != 1)
    {
        throw new CryptographicException("No signature");
    }

    signedXmlVerifier.LoadXml((XmlElement)signatureNodes[0]);

    if (!signedXmlVerifier.CheckSignature(publicKey)) // <<<= this row throws the exception
    {
        throw new CryptographicException("XML compromised!");
    }

    // Deserialize the validated XML to ConfigRoot
    XmlSerializer serializer = new(typeof(ConfigRoot));
    using StringReader reader = new(xmlDoc.OuterXml);

    return (ConfigRoot)serializer.Deserialize(reader);
}

The stack trace of the exception is this:

It works fine in debug mode both on the device and emulator, and I have no issues on Windows either, only on Android.

The RSA public key is correctly populated form an XML, the signed XML is loaded and the signature node is also correct.

I think something is optimized away. So I have added these to my application project's csproj:

<ItemGroup>
  <TrimmerRootAssembly Include="System.Security.Cryptography.Xml" RootMode="All" />
  <TrimmerRootAssembly Include="System.Security.Cryptography.Pkcs" RootMode="All" />
</ItemGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-android|AnyCPU'">
    <AndroidPackageFormat>apk</AndroidPackageFormat>
    <AndroidEnableR8>true</AndroidEnableR8>
    <AndroidLinkTool>r8</AndroidLinkTool>
    <AndroidProguardConfig>proguard.cfg</AndroidProguardConfig>
    <DebugType>portable</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <AndroidLinkMode>SdkOnly</AndroidLinkMode>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net9.0-android'">
  <ProguardConfiguration Include="Platforms\Android\proguard.cfg" />
</ItemGroup>

With this proguard.cfg (I have to admit, I have no clue what I am doing here related to the android linker and optimizer. All of it was suggested by AI and/or found online - make sense, but no difference):

    -keep class androidx.security.crypto.** { *; }
    -keep class com.google.crypto.tink.** { *; }
    
    # Keep all classes in System.Security.Cryptography.Xml
    -keep class System.Security.Cryptography.Xml.** { *; }
    
    # Keep classes used by SignedXml and RSA
    -keep class System.Security.Cryptography.Xml.SignedXml { *; }
    -keep class System.Security.Cryptography.Xml.RSAPKCS1SignatureDescription { *; }
    
    # Keep XML serialization classes (if used)
    -keep class System.Xml.** { *; }

But it makes no difference...

[Solved]

Right after posting this I found this one on github: https://github/dotnet/runtime/issues/97242

It was promisingly similar, hence I have added System.Security.Cryptography to my TrimRootAssembly list, and it worked. I might fine-tune later with the TrimmerRootDescriptor, but for now, I am happy with what I have. I have also removed all the android linker related stuff.

Share Improve this question edited Feb 23 at 11:29 ZoZ asked Feb 23 at 10:53 ZoZZoZ 3,5982 gold badges18 silver badges46 bronze badges 3
  • Did you try to disable the trimming during the publish or disable the AOT? – Liyun Zhang - MSFT Commented Feb 24 at 1:06
  • It is a trimming issue, and in my update I have already mentioned that I have identified what's trimmed way. – ZoZ Commented Feb 25 at 6:46
  • Oh, I see it. Glad to know you have resolve it and you can post the update part as an answer and ther others will find it easily. Hapy coding! – Liyun Zhang - MSFT Commented Feb 25 at 6:48
Add a comment  | 

1 Answer 1

Reset to default 0

I found this one on github: https://github/dotnet/runtime/issues/97242

It was promisingly similar, hence I have added System.Security.Cryptography to my TrimRootAssembly list, and it worked. I might fine-tune later with the TrimmerRootDescriptor, but for now, I am happy with what I have. I have also removed all the android linker related stuff.

发布评论

评论列表(0)

  1. 暂无评论