Signing of big XMLs fails on Windows 8/10 using smart cards

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Signing of big XMLs fails on Windows 8/10 using smart cards

Adrian Greiler

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
[hidden email] | Office : +41 31 385 30 11 | Direkt: +41 31 385 30 34

WindowsEventLog.png (86K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Signing of big XMLs fails on Windows 8/10 using smart cards

Colm O hEigeartaigh-2
Could you create a JIRA here and submit a patch please?

https://issues.apache.org/jira/browse/SANTUARIO

Colm.

On Thu, Jun 2, 2016 at 9:53 AM, Adrian Greiler <[hidden email]> wrote:

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
[hidden email] | Office : <a href="tel:%2B41%2031%20385%2030%2011" value="+41313853011" target="_blank">+41 31 385 30 11 | Direkt: <a href="tel:%2B41%2031%20385%2030%2034" value="+41313853034" target="_blank">+41 31 385 30 34



--
Colm O hEigeartaigh

Talend Community Coder
http://coders.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Signing of big XMLs fails on Windows 8/10 using smart cards

Frank Cornelis

Sure that this fixes the issue? What happens when the user takes more than 5 seconds to enter the smart card PIN code?


Kind Regards,
Frank.

Op 02-06-16 om 10:54 schreef Colm O hEigeartaigh:
Could you create a JIRA here and submit a patch please?

https://issues.apache.org/jira/browse/SANTUARIO

Colm.

On Thu, Jun 2, 2016 at 9:53 AM, Adrian Greiler <[hidden email]> wrote:

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
[hidden email] | Office : <a moz-do-not-send="true" href="tel:%2B41%2031%20385%2030%2011" value="+41313853011" target="_blank">+41 31 385 30 11 | Direkt: <a moz-do-not-send="true" href="tel:%2B41%2031%20385%2030%2034" value="+41313853034" target="_blank">+41 31 385 30 34



--
Colm O hEigeartaigh

Talend Community Coder
http://coders.talend.com

-- 
Frank Cornelis
e-Contract.be BVBA
https://www.e-contract.be
Reply | Threaded
Open this post in threaded view
|

Re: Signing of big XMLs fails on Windows 8/10 using smart cards

Lijun Liao-2
Maybe the solution as suggested in section "Disable Smart Card Plug and Play through Group Policy for managed computers" of https://support.microsoft.com/en-us/kb/976832 works.

Kind Regards,

Lijun

On Thu, Jun 2, 2016 at 12:29 PM, Frank Cornelis <[hidden email]> wrote:

Sure that this fixes the issue? What happens when the user takes more than 5 seconds to enter the smart card PIN code?


Kind Regards,
Frank.

Op 02-06-16 om 10:54 schreef Colm O hEigeartaigh:
Could you create a JIRA here and submit a patch please?

https://issues.apache.org/jira/browse/SANTUARIO

Colm.

On Thu, Jun 2, 2016 at 9:53 AM, Adrian Greiler <[hidden email]> wrote:

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
[hidden email] | Office : <a href="tel:%2B41%2031%20385%2030%2011" value="+41313853011" target="_blank">+41 31 385 30 11 | Direkt: <a href="tel:%2B41%2031%20385%2030%2034" value="+41313853034" target="_blank">+41 31 385 30 34



--
Colm O hEigeartaigh

Talend Community Coder
http://coders.talend.com

-- 
Frank Cornelis
e-Contract.be BVBA
https://www.e-contract.be



--
Lijun Liao
Reply | Threaded
Open this post in threaded view
|

Re: Signing of big XMLs fails on Windows 8/10 using smart cards

Adrian Greiler
In reply to this post by Frank Cornelis

I just tested with a way longer delay (more than 5 minutes) and it still worked. We have Siemens CardOS V4.3B (SuisseID) and there it fixes the problem.


Thanks for the hint / test case and kind regards

Adrian


Am 02.06.2016 um 12:29 schrieb Frank Cornelis:

Sure that this fixes the issue? What happens when the user takes more than 5 seconds to enter the smart card PIN code?


Kind Regards,
Frank.

Op 02-06-16 om 10:54 schreef Colm O hEigeartaigh:
Could you create a JIRA here and submit a patch please?

https://issues.apache.org/jira/browse/SANTUARIO

Colm.

On Thu, Jun 2, 2016 at 9:53 AM, Adrian Greiler <[hidden email]> wrote:

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
[hidden email] | Office : <a moz-do-not-send="true" href="tel:%2B41%2031%20385%2030%2011" value="+41313853011" target="_blank">+41 31 385 30 11 | Direkt: <a moz-do-not-send="true" href="tel:%2B41%2031%20385%2030%2034" value="+41313853034" target="_blank">+41 31 385 30 34



--
Colm O hEigeartaigh

Talend Community Coder
http://coders.talend.com

-- 
Frank Cornelis
e-Contract.be BVBA
https://www.e-contract.be

Reply | Threaded
Open this post in threaded view
|

Re: Signing of big XMLs fails on Windows 8/10 using smart cards

Adrian Greiler
In reply to this post by Lijun Liao-2

We do not have permission to change group policies on the target computers.

Thanks anyway for the interesting input and kind regards

Adrian



Am 02.06.2016 um 12:43 schrieb Lijun Liao:
Maybe the solution as suggested in section "Disable Smart Card Plug and Play through Group Policy for managed computers" of https://support.microsoft.com/en-us/kb/976832 works.

Kind Regards,

Lijun

On Thu, Jun 2, 2016 at 12:29 PM, Frank Cornelis <[hidden email]> wrote:

Sure that this fixes the issue? What happens when the user takes more than 5 seconds to enter the smart card PIN code?


Kind Regards,
Frank.

Op 02-06-16 om 10:54 schreef Colm O hEigeartaigh:
Could you create a JIRA here and submit a patch please?

https://issues.apache.org/jira/browse/SANTUARIO

Colm.

On Thu, Jun 2, 2016 at 9:53 AM, Adrian Greiler <[hidden email]> wrote:

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
[hidden email] | Office : <a moz-do-not-send="true" href="tel:%2B41%2031%20385%2030%2011" value="+41313853011" target="_blank">+41 31 385 30 11 | Direkt: <a moz-do-not-send="true" href="tel:%2B41%2031%20385%2030%2034" value="+41313853034" target="_blank">+41 31 385 30 34



--
Colm O hEigeartaigh

Talend Community Coder
http://coders.talend.com

-- 
Frank Cornelis
e-Contract.be BVBA
https://www.e-contract.be



--
Lijun Liao