Xamarin.Android绑定Spongy Castle / Bouncy Castle

4

有人成功将SpongyCastle绑定到Xamarin.Android吗?在绑定项目的Metadata.xml中我遇到了一堆警告。

到目前为止,我已经:

<remove-node path="/api/package[@name='org.spongycastle.x509']" />
<remove-node path="/api/package[@name='org.spongycastle.crypto']" />
<remove-node path="/api/package[@name='org.spongycastle.crypto.tls']" />
<remove-node path="/api/package[@name='org.spongycastle.cms']" />
<remove-node path="/api/package[@name='org.spongycastle.crypto.prng']" />
<remove-node path="/api/package[@name='org.spongycastle.openpgp']" />
<remove-node path="/api/package[@name='org.spongycastle.openssl']" />
<remove-node path="/api/package[@name='org.spongycastle.cert.ocsp']" />

<remove-node path="/api/package[@name='org.spongycastle.jcajce']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.dh']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.ec']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.digest']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.keystore.bc']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.symmetric']" />

<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.dsa']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.util']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.symmetric.util']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.gost']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.ies']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.rsa']" />
<remove-node path="/api/package[@name='org.spongycastle.jcajce.provider.asymmetric.x509']" />

<remove-node path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='CertStoreCollectionSpi']" />
<remove-node path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='MultiCertStoreSpi']" />
<remove-node path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='X509CRLEntryObject']" />
<remove-node path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='X509CRLObject']" />
<remove-node path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='X509CertificateObject']" />
<remove-node path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='X509LDAPCertStoreSpi']"/>
<remove-node path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='PKIXPolicyNode']" />

<remove-node path="/api/package[@name='org.spongycastle.pqc.jcajce.provider.rainbow']" />
<remove-node path="/api/package[@name='org.spongycastle.pqc.jcajce.provider.mceliece']"/>
<remove-node path="/api/package[@name='org.spongycastle.pqc.jcajce.provider.util']" />
<remove-node path="/api/package[@name='org.spongycastle.pqc.crypto.ntru']" />
<remove-node path="/api/package[@name='org.spongycastle.pqc.math.ntru.polynomial']" />

所以它可以编译,但是在Xamarin.Android项目中使用绑定项目需要几分钟才能编译,然后它会因为Java的HEAP大小而失败。当我将堆大小设置为1GB时,它就完成了,但是在设备上以调试模式运行应用程序时,调试就会中断。
有没有一种方法可以只使用ARRs而不使用绑定库?我只需要调用我在这个ARR中创建的包装器方法并获取该输出。我不需要通过C#访问整个库。或者有更好的方法吗?
更新: 当我构建CPU时,它看起来像这样(请查看Java):enter image description here

为什么不使用Bouncy Castle? - jzeferino
我不是加密专家,但当许多人在各种论坛上表示:“安卓平台不幸地提供了一个不完整且过时的Bouncy Castle版本,这也使得安装库的更新版本变得困难。话虽如此,我们不得不选择Spongy Castle,这是一个重新打包的Bouncy Castle版本,以使其在Android上运行。” - 那么我选择Spongy Castle。参考:https://aerogear.org/docs/specs/aerogear-crypto/ - chrisva
最近我在Android中使用PCL的Bouncy Castle,没有任何问题。 - jzeferino
这可能取决于你需要做什么。我依赖于几个库,使用 NFC 做了一些很棒的东西。因此,建议使用我所依赖的库中的 SpongyCastle。无论如何,这更多是关于从 Xamarin 解决与 Java 的绑定/调用问题,而不是需要哪种类型的库。 - chrisva
2个回答

2
“ARR”是指“AAR”吗?如果只使用某些项目,您可以直接使用JNI:https://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/working_with_jni/ 最简单的方法是删除所有不想保留的项,并处理您要保留的项。但是,您可能需要确保保留依赖项以便正确绑定。这可能会很快变得麻烦。
我有一个通用指南,可能在某些绑定方面有所帮助:

https://github.com/JonDouglas/xamarin-support-docs/blob/master/Android/android-bindings-troubleshooting.md

如@jzeferino所提到的,您可以选择使用一些比自己编写绑定更为成熟的方案。
BouncyCastle-PCL: https://github.com/onovotny/BouncyCastle-PCL PCL Crypto: https://github.com/AArnott/PCLCrypto 这两个库都提供了各自的加密方法来完成您的任务。在PCLCrypto的情况下,它们是由Mono实现或平台实现提供的。

@chrisva 我认为这是最好的选择路径,这就是我建议转移到Bouncy Castle的原因。 - jzeferino
是的,我指的是AAR。感谢您指引我去PCL,那里已经有了。我很了解它们。我的第三方库依赖于Spongy Castle,所以我不想寻找简单的解决方法。我想学习如何以最优化的方式进行绑定,因为我们未来将需要几个具有不同复杂度的绑定项目。因此,在这种情况下,JNI似乎是一个非常有趣的方法。我会深入研究并更新进展。谢谢。 - chrisva
顺便说一下,那个指南非常棒 @jon-douglas - chrisva

0

我最终在绑定项目的metadata.xml文件中删除了几乎所有与BouncyCastle和SpongyCastle相关的内容。然后,我从绑定项目中的生成文件夹中复制了生成的BouncyCastleProvider的部分内容。因此,我只为我需要调用的部分创建了自己的JNI包装器。

这很有效。现在编译时间缩短到了几秒钟,调试期间部署也很快。而且我还可以使用第三方库。

我的经验是先生成C#类,然后选择在自己的库中实现JNI的部分,并添加/删除Metadata.xml中的节点。

using System;
using System.Collections.Generic;
using Android.Runtime;
namespace Org.Spongycastle.Jce.Provider
{

// Metadata.xml XPath class reference: path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='BouncyCastleProvider']"
[global::Android.Runtime.Register("org/spongycastle/jce/provider/BouncyCastleProvider", DoNotGenerateAcw = true)]
public sealed partial class BouncyCastleProvider : global::Java.Security.Provider
{
    // Metadata.xml XPath field reference: path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='BouncyCastleProvider']/field[@name='PROVIDER_NAME']"
    [Register("PROVIDER_NAME")]
    public const string ProviderName = (string)"SC";

    internal static IntPtr java_class_handle;
    internal static IntPtr class_ref
    {
        get
        {
            return JNIEnv.FindClass("org/spongycastle/jce/provider/BouncyCastleProvider", ref java_class_handle);
        }
    }

    protected override IntPtr ThresholdClass
    {
        get { return class_ref; }
    }

    protected override global::System.Type ThresholdType
    {
        get { return typeof(BouncyCastleProvider); }
    }

    internal BouncyCastleProvider(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }

    static IntPtr id_ctor;
    // Metadata.xml XPath constructor reference: path="/api/package[@name='org.spongycastle.jce.provider']/class[@name='BouncyCastleProvider']/constructor[@name='BouncyCastleProvider' and count(parameter)=0]"
    [Register(".ctor", "()V", "")]
    public unsafe BouncyCastleProvider()
        : base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
    {
        if (Handle != IntPtr.Zero)
            return;

        try
        {
            if (GetType() != typeof(BouncyCastleProvider))
            {
                SetHandle(
                        global::Android.Runtime.JNIEnv.StartCreateInstance(GetType(), "()V"),
                        JniHandleOwnership.TransferLocalRef);
                global::Android.Runtime.JNIEnv.FinishCreateInstance(Handle, "()V");
                return;
            }

            if (id_ctor == IntPtr.Zero)
                id_ctor = JNIEnv.GetMethodID(class_ref, "<init>", "()V");
            SetHandle(
                    global::Android.Runtime.JNIEnv.StartCreateInstance(class_ref, id_ctor),
                    JniHandleOwnership.TransferLocalRef);
            JNIEnv.FinishCreateInstance(Handle, class_ref, id_ctor);
        }
        finally
        {
        }
    }
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接