Xamarin.Android 绑定 Spongy Castle / Bouncy Castle
Xamarin.Android binding Spongy Castle / Bouncy Castle
有人成功绑定 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 时,它会完成,但是当 运行 应用程序在设备上处于调试模式时,调试会中断。
有没有办法在没有绑定库的情况下只使用 ARR?我只需要调用我在这个 ARR 中制作的包装器方法并从中获取输出。我不需要通过 C# 访问完整的库。或者有更好的方法吗?
更新:
当我构建 CPU 时,它看起来像这样(看 Java):
ARR
是指 AAR
吗?在只使用部分项目的情况下,可以直接使用JNI
:https://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/working_with_jni/
最简单的方法是 <remove-node>
您不想保留的所有项目,然后处理您确实想保留的项目。但是,您可能需要确保保留依赖关系,以便它们正确绑定。这很快就会变得令人讨厌。
我有一个通用指南,可能会在某些领域使用此绑定提供帮助:
正如@jzeferino 所提到的,您总是可以使用经过实战验证的东西,而不是自己动手绑定。
BouncyCastle-PCL: https://github.com/onovotny/BouncyCastle-PCL
PCL 密码:https://github.com/AArnott/PCLCrypto
这两者都提供了各自的加密方法来完成您的任务。在 PCLCrypto 的情况下,它们要么由 Mono 的实现提供,要么由平台的实现提供。
我最终在绑定项目的 metadata.xml 文件中删除了与 BouncyCastle 和 SpongyCastle 相关的几乎所有内容。然后,我从绑定项目中生成的文件文件夹中复制了生成的 BouncyCastleProvider 的一部分。所以我只为需要调用的部分创建了自己的 JNI 包装器。
效果很好。现在编译时间减少到几秒钟,调试期间部署速度很快。我喜欢第三方图书馆。
我从中得到的是首先生成 C# 类,然后选择在我自己的库中实现部分 JNI 和 Metadata.xml 中的 add/remove 个节点。
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
{
}
}
}
}
有人成功绑定 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 时,它会完成,但是当 运行 应用程序在设备上处于调试模式时,调试会中断。
有没有办法在没有绑定库的情况下只使用 ARR?我只需要调用我在这个 ARR 中制作的包装器方法并从中获取输出。我不需要通过 C# 访问完整的库。或者有更好的方法吗?
更新:
当我构建 CPU 时,它看起来像这样(看 Java):
ARR
是指 AAR
吗?在只使用部分项目的情况下,可以直接使用JNI
:https://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/working_with_jni/
最简单的方法是 <remove-node>
您不想保留的所有项目,然后处理您确实想保留的项目。但是,您可能需要确保保留依赖关系,以便它们正确绑定。这很快就会变得令人讨厌。
我有一个通用指南,可能会在某些领域使用此绑定提供帮助:
正如@jzeferino 所提到的,您总是可以使用经过实战验证的东西,而不是自己动手绑定。
BouncyCastle-PCL: https://github.com/onovotny/BouncyCastle-PCL
PCL 密码:https://github.com/AArnott/PCLCrypto
这两者都提供了各自的加密方法来完成您的任务。在 PCLCrypto 的情况下,它们要么由 Mono 的实现提供,要么由平台的实现提供。
我最终在绑定项目的 metadata.xml 文件中删除了与 BouncyCastle 和 SpongyCastle 相关的几乎所有内容。然后,我从绑定项目中生成的文件文件夹中复制了生成的 BouncyCastleProvider 的一部分。所以我只为需要调用的部分创建了自己的 JNI 包装器。
效果很好。现在编译时间减少到几秒钟,调试期间部署速度很快。我喜欢第三方图书馆。
我从中得到的是首先生成 C# 类,然后选择在我自己的库中实现部分 JNI 和 Metadata.xml 中的 add/remove 个节点。
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
{
}
}
}
}