Android API≥24下DOM文档类型适配的安全提供商咨询
问题
我尝试使用javax.xml.crypto.dsig.XMLSignatureFactory构建XML文档,实例化时需向getInstance()方法传入安全提供商,即XMLSignatureFactory.getInstance("DOM", provider)。
常规做法是采用Apache Santuario库的XMLDSigRI():
private val xmlSigFactory = XMLSignatureFactory.getInstance("DOM", org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI())
但该库依赖的java.util.Base64类在Android API<26环境下无法运行。我尝试使用BouncyCastle安全提供商(标识为BC),运行时抛出错误:
Caused by: javax.xml.crypto.NoSuchMechanismException: no such mechanism type: DOM for provider BC
换成SpongyCastle(标识为SC)也出现相同问题。我已通过以下代码遍历所有安全提供商,确认BC和SC均已加载:
for(p in Security.getProviders()) { Log.d("PROVIDER NAME", p.name) Log.d("PROVIDER INFO", p.info) }
尝试修改库替换java.util.Base64的难度较大,现咨询:
- Android API≥24下是否有适配DOM文档类型的安全提供商?
- 若无,可行的替代方案是什么?
解决方案
适配API≥24的系统自带提供商
Android API 24及以上系统自带的AndroidOpenSSL提供商(名称为AndroidOpenSSL)原生支持DOM类型的XML签名机制,可直接使用:
private val xmlSigFactory = XMLSignatureFactory.getInstance("DOM", Security.getProvider("AndroidOpenSSL"))
验证方式:遍历提供商时,AndroidOpenSSL的信息会包含XMLDSIG相关支持声明,无需额外引入第三方库。
替代方案(系统提供商不可用时)
1. 局部替换Apache Santuario的Base64依赖
无需整体修改库,仅针对XMLDSigRI中用到java.util.Base64的代码片段进行替换:
- 定位Santuario库中调用
Base64.getEncoder()/getDecoder()的代码 - 替换为Android兼容的
android.util.Base64类(API 8及以上支持),对应映射:Base64.getEncoder().encodeToString(bytes)→android.util.Base64.encodeToString(bytes, Base64.DEFAULT)Base64.getDecoder().decode(str)→android.util.Base64.decode(str, Base64.DEFAULT)
- 可通过自定义类继承或字节码工具(如ASM)实现,难度远低于整体改库。
2. 使用SpongyCastle专属XML签名API
SpongyCastle不直接支持JDK标准的DOM类型XMLSignatureFactory,但提供了独立的XML签名实现:
- 引入SpongyCastle的
spongycastle-xml依赖 - 使用
org.spongycastle.xml.XMLSignatureFactory替代JDK的javax.xml.crypto.dsig.XMLSignatureFactory - 该实现完全不依赖JDK的
java.util.Base64,兼容Android API≥24。
内容的提问来源于stack exchange,提问作者filip1234
相关产品推荐
相关产品推荐

