Xades4j:无法初始化密钥库
Xades4j: The keystore couldn't be initialized
我正在尝试将我最近在 Windows 中安装的证书导入 Java 以与 xades4j 一起使用。不幸的是,我在证书和密钥等方面还是个新手。
但是,每次我 运行 程序时,我都会收到以下错误:
>xades4j.verification.UnexpectedJCAException: The keystore couldn't be initialized
at xades4j.providers.impl.KeyStoreKeyingDataProvider.ensureInitialized(KeyStoreKeyingDataProvider.java:179)
at xades4j.providers.impl.KeyStoreKeyingDataProvider.getSigningCertificateChain(KeyStoreKeyingDataProvider.java:189)
at xades4j.production.SignerBES.sign(SignerBES.java:159)
at xades4j.production.SignerBES.sign(SignerBES.java:130)
at com.logic.test.signBes(test.java:138)
at com.logic.test.<init>(test.java:80)
at com.view.FrmMenu.<init>(FrmMenu.java:41)
at com.view.FrmMenu.run(FrmMenu.java:289)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: java.security.KeyStoreException: KeyStore instantiation failed
at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:1862)
at xades4j.providers.impl.KeyStoreKeyingDataProvider.ensureInitialized(KeyStoreKeyingDataProvider.java:175)
... 21 more
Caused by: java.io.IOException: DER input, Integer tag error
at sun.security.util.DerInputStream.getInteger(DerInputStream.java:192)
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1940)
at java.security.KeyStore.load(KeyStore.java:1445)
at java.security.KeyStore$Builder$FileBuilder.run0(KeyStore.java:1848)
at java.security.KeyStore$Builder$FileBuilder.run(KeyStore.java:1807)
at java.security.KeyStore$Builder$FileBuilder.run(KeyStore.java:1796)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:1858)
... 22 more
>
我需要签署一份 XaDeS-BES 格式的 XML 文件。我从光盘导入了一个密钥(或证书?),它在 Windows 受信任的根证书颁发机构证书中。我从 Windows 证书管理器 (certmgr.msc).
将它导出到 C 驱动器的根目录
我发现 one post on this website 提到尝试以下方法来初始化 KeyStore:
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
很遗憾,没有任何变化。
我使用的代码,基于 the example wiki:
private static final String CERT_FOLDER = "C:/";
private static final String CERT = "testkey.cer";
private static final String PASS = "test1234"; //the same in cert and keystorage
private static final String SIGNED = "persistent/xml/001-001-000000000new1.xml";
private static final String DOCUMENT = "persistent/xml/001-001-000000000.xml";
private static void signBes() throws Exception {
Document doc = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new File(DOCUMENT));
Element elem = doc.getDocumentElement();
DOMHelper.useIdAsXmlId(elem);
KeyingDataProvider kdp = new FileSystemKeyStoreKeyingDataProvider(
"pkcs12",
CERT_FOLDER + CERT,
new FirstCertificateSelector(),
new DirectPasswordProvider(PASS),
new DirectPasswordProvider(PASS),
true);
DataObjectDesc obj = new DataObjectReference("#" + elem.getAttribute("Id"))
.withTransform(new EnvelopedSignatureTransform());
SignedDataObjects dataObjs = new SignedDataObjects().withSignedDataObject(obj);
// KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// ks.load(null, null);
XadesSigner signer = new XadesBesSigningProfile(kdp).newSigner();
signer.sign(dataObjs, elem);
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(SIGNED));
transformer.transform(source, result);
}
感谢您的所有帮助。
要执行签名操作,您需要 key/certificate 对 ,即 PKCS12 容器。在 Windows 上,该对通常是 .pfx
或 .p12
文件。我不确定问题出在哪里,但以下是一些可能对您有所帮助的注意事项:
- 用于签名的证书通常是 "personal" 证书,而不是受信任的权威根证书。
- 根证书属于通常向其他主体颁发证书的实体。
- 验证证书过程的一部分是建立从主体证书到根证书的信任链。在 Windows,受信任的根证书在您提到的商店中:"Windows Trusted Root Certification Authorities"。您的签名证书可能不应该存在。
- 由于您正在执行签名操作(对于 BES 签名)并使用
FileSystemKeyStoreKeyingDataProvider
信任链实际上不太相关。当您验证签名时,它就变得相关了。
- 从您的代码来看,您似乎只有一个证书文件 (
.cer
)。我不知道您最初是如何获得证书的,但应该连同密钥一起提供,可能捆绑在受密码保护的 .pfx
文件中。
- 创建
FileSystemKeyStoreKeyingDataProvider
时,您应该
传递 PKCS12 文件(例如 .pfx
)
- 如果您在其他 Windows 存储中安装了证书,请尝试使用密钥导出它(如果可能;首先取决于它是如何导入的)。
希望对您有所帮助。
就我而言,密码错误
我正在尝试将我最近在 Windows 中安装的证书导入 Java 以与 xades4j 一起使用。不幸的是,我在证书和密钥等方面还是个新手。
但是,每次我 运行 程序时,我都会收到以下错误:
>xades4j.verification.UnexpectedJCAException: The keystore couldn't be initialized
at xades4j.providers.impl.KeyStoreKeyingDataProvider.ensureInitialized(KeyStoreKeyingDataProvider.java:179)
at xades4j.providers.impl.KeyStoreKeyingDataProvider.getSigningCertificateChain(KeyStoreKeyingDataProvider.java:189)
at xades4j.production.SignerBES.sign(SignerBES.java:159)
at xades4j.production.SignerBES.sign(SignerBES.java:130)
at com.logic.test.signBes(test.java:138)
at com.logic.test.<init>(test.java:80)
at com.view.FrmMenu.<init>(FrmMenu.java:41)
at com.view.FrmMenu.run(FrmMenu.java:289)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: java.security.KeyStoreException: KeyStore instantiation failed
at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:1862)
at xades4j.providers.impl.KeyStoreKeyingDataProvider.ensureInitialized(KeyStoreKeyingDataProvider.java:175)
... 21 more
Caused by: java.io.IOException: DER input, Integer tag error
at sun.security.util.DerInputStream.getInteger(DerInputStream.java:192)
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1940)
at java.security.KeyStore.load(KeyStore.java:1445)
at java.security.KeyStore$Builder$FileBuilder.run0(KeyStore.java:1848)
at java.security.KeyStore$Builder$FileBuilder.run(KeyStore.java:1807)
at java.security.KeyStore$Builder$FileBuilder.run(KeyStore.java:1796)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:1858)
... 22 more
>
我需要签署一份 XaDeS-BES 格式的 XML 文件。我从光盘导入了一个密钥(或证书?),它在 Windows 受信任的根证书颁发机构证书中。我从 Windows 证书管理器 (certmgr.msc).
将它导出到 C 驱动器的根目录我发现 one post on this website 提到尝试以下方法来初始化 KeyStore:
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
很遗憾,没有任何变化。
我使用的代码,基于 the example wiki:
private static final String CERT_FOLDER = "C:/";
private static final String CERT = "testkey.cer";
private static final String PASS = "test1234"; //the same in cert and keystorage
private static final String SIGNED = "persistent/xml/001-001-000000000new1.xml";
private static final String DOCUMENT = "persistent/xml/001-001-000000000.xml";
private static void signBes() throws Exception {
Document doc = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new File(DOCUMENT));
Element elem = doc.getDocumentElement();
DOMHelper.useIdAsXmlId(elem);
KeyingDataProvider kdp = new FileSystemKeyStoreKeyingDataProvider(
"pkcs12",
CERT_FOLDER + CERT,
new FirstCertificateSelector(),
new DirectPasswordProvider(PASS),
new DirectPasswordProvider(PASS),
true);
DataObjectDesc obj = new DataObjectReference("#" + elem.getAttribute("Id"))
.withTransform(new EnvelopedSignatureTransform());
SignedDataObjects dataObjs = new SignedDataObjects().withSignedDataObject(obj);
// KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// ks.load(null, null);
XadesSigner signer = new XadesBesSigningProfile(kdp).newSigner();
signer.sign(dataObjs, elem);
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(SIGNED));
transformer.transform(source, result);
}
感谢您的所有帮助。
要执行签名操作,您需要 key/certificate 对 ,即 PKCS12 容器。在 Windows 上,该对通常是 .pfx
或 .p12
文件。我不确定问题出在哪里,但以下是一些可能对您有所帮助的注意事项:
- 用于签名的证书通常是 "personal" 证书,而不是受信任的权威根证书。
- 根证书属于通常向其他主体颁发证书的实体。
- 验证证书过程的一部分是建立从主体证书到根证书的信任链。在 Windows,受信任的根证书在您提到的商店中:"Windows Trusted Root Certification Authorities"。您的签名证书可能不应该存在。
- 由于您正在执行签名操作(对于 BES 签名)并使用
FileSystemKeyStoreKeyingDataProvider
信任链实际上不太相关。当您验证签名时,它就变得相关了。 - 从您的代码来看,您似乎只有一个证书文件 (
.cer
)。我不知道您最初是如何获得证书的,但应该连同密钥一起提供,可能捆绑在受密码保护的.pfx
文件中。 - 创建
FileSystemKeyStoreKeyingDataProvider
时,您应该 传递 PKCS12 文件(例如.pfx
) - 如果您在其他 Windows 存储中安装了证书,请尝试使用密钥导出它(如果可能;首先取决于它是如何导入的)。
希望对您有所帮助。
就我而言,密码错误