When signing XML files with Xades4j (which uses Apache Santuario
underneath) using a smart card the latter will be reset by Windows when
the signing process takes more than 5 seconds. This issue exists only on
Windows 8+.
The problem is that the key store gets initialized before the digest
values are computed. If this calculation takes more than 5 seconds
Windows resets the smart card because of an inactive transaction. (See
the attached screen shot of the log of that event). After the
calculations are done and the actual signing process starts the
smartcard is no more available and the task fails.
This behavior is documented here
https://msdn.microsoft.com/en-us/library/windows/desktop/aa379469%28v=vs.85%29.aspx
The solution is quite simple. The order of calculating the digest values
and initializing the key store has to be changed. I located this in
org.apache.xml.security.signature.XmlSignature on line 628 in method
public void sign(Key signingKey) throws XMLSignatureException {
...
try {
//Create a SignatureAlgorithm object
SignedInfo si = this.getSignedInfo();
SignatureAlgorithm sa = si.getSignatureAlgorithm();
OutputStream so = null;
try {
* // initialize SignatureAlgorithm for signing**
** sa.initSign(signingKey);**
****
** // generate digest values for all References in this
SignedInfo**
** si.generateDigestValues(); *
so = new UnsyncBufferedOutputStream(new
SignerOutputStream(sa));
// get the canonicalized bytes from SignedInfo
si.signInOctetStream(so);
} catch (XMLSecurityException ex) {
throw ex;
} finally {
...
To solve the problem it should be
public void sign(Key signingKey) throws XMLSignatureException {
...
try {
//Create a SignatureAlgorithm object
SignedInfo si = this.getSignedInfo();
SignatureAlgorithm sa = si.getSignatureAlgorithm();
OutputStream so = null;
try {
* // generate digest values for all References in this
SignedInfo**
** si.generateDigestValues();**
****
** // initialize SignatureAlgorithm for signing**
** sa.initSign(signingKey); *
so = new UnsyncBufferedOutputStream(new
SignerOutputStream(sa));
// get the canonicalized bytes from SignedInfo
si.signInOctetStream(so);
} catch (XMLSecurityException ex) {
throw ex;
} finally {
...
This code works for this particular setup and is able to sign an XML of
60GB on a Windows 10 machine. This task takes more than a minute and
doesn't fail since Windows doesn't reset the smart card transaction.
Kind regards
Adrian Greiler
--
Adrian Greiler
Software Engineer
Glue Software Engineering AG | Schwarztorstrasse 31 | CH-3007 Bern | www.glue.ch
[email protected] | Office : +41 31 385 30 11 | Direkt: +41 31 385 30 34