Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to retrieve the certificate chain from Azure Trusted Signing (socket write error) #220

Open
ROGG437063 opened this issue May 15, 2024 · 24 comments

Comments

@ROGG437063
Copy link

jsign: Unable to retrieve the certificate chain 'codesigningaccount/codesigningprofile'
java.security.KeyStoreException: Unable to retrieve the certificate chain 'codesigningaccount/codesigningprofile'
	at net.jsign.jca.AzureTrustedSigningService.getCertificateChain(AzureTrustedSigningService.java:101)
	at net.jsign.jca.SigningServiceKeyStore.engineGetCertificateChain(SigningServiceKeyStore.java:43)
	at java.base/java.security.KeyStore.getCertificateChain(Unknown Source)
	at net.jsign.SignerHelper.build(SignerHelper.java:321)
	at net.jsign.SignerHelper.sign(SignerHelper.java:435)
	at net.jsign.SignerHelper.execute(SignerHelper.java:278)
	at net.jsign.JsignCLI.execute(JsignCLI.java:166)
	at net.jsign.JsignCLI.main(JsignCLI.java:45)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
	at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(Unknown Source)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
	at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(Unknown Source)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
	at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
	at net.jsign.jca.RESTClient.query(RESTClient.java:89)
	at net.jsign.jca.RESTClient.post(RESTClient.java:60)
	at net.jsign.jca.AzureTrustedSigningService.sign(AzureTrustedSigningService.java:142)
	at net.jsign.jca.AzureTrustedSigningService.getCertificateChain(AzureTrustedSigningService.java:98)
	... 7 more
	Suppressed: java.net.SocketException: Software caused connection abort: socket write error
		at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
		at java.base/java.net.SocketOutputStream.socketWrite(Unknown Source)
		at java.base/java.net.SocketOutputStream.write(Unknown Source)
		at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(Unknown Source)
		at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
		at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
		... 18 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
	at java.base/sun.security.ssl.SSLSocketInputRecord.read(Unknown Source)
	at java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(Unknown Source)
	at java.base/sun.security.ssl.SSLSocketInputRecord.decode(Unknown Source)
	at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
	... 20 more

Command used

Get-ChildItem -Include $includes -Recurse | Foreach-Object { "--storetype TRUSTEDSIGNING --keystore $rootUrl --storepass $token --alias $signingAccount/$signingProfile $($_.fullname)"} | foreach-object {Start-Process "jsign" $_ -NoNewWindow}

Is it possible, running the process like this causes it to fight over the connection.
I am using jsign installed through chocolatey with the jar replaced by the in-dev version from https://github.com/ebourg/jsign/actions/runs/9038916734.

@ebourg
Copy link
Owner

ebourg commented May 15, 2024

Thank you for reporting this issue. What version of Java do you use? Are you behind a proxy?

@ROGG437063
Copy link
Author

I am not behind a proxy and I am using the java version that is bundled with the 6.0 chocolatey release.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

Do you get the same error if you run this command from another location (at home or at work) ?

@ebourg ebourg changed the title jsign: Unable to retrieve the certificate chain 'codesigningaccount/codesigningprofile' (Trusted Signing) JSIGN (development build) Unable to retrieve the certificate chain from Azure Trusted Signing (socket write error) May 16, 2024
@ROGG437063
Copy link
Author

I actually had tested the command before without getting the error, on the same machine manually, whereas when getting the error it was using that machine as a build agent for azure devops. So I assume it is a race condition kind of thing, caused by starting multiple jsign processes at the same time.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

What's the execution context when it fails? A Docker container on a Windows server?

The error messages "Software caused connection abort: socket write error" and "SSL peer shut down incorrectly" smell like a network issue typically caused by a firewall or antivirus software terminating the connection.

@ROGG437063
Copy link
Author

It is running on a windows server in this context.

@ROGG437063
Copy link
Author

As a sidenote, my approach goes against your advice to provide a filelist as the input for the command when using trusted signing. The reason for that is that we ran into the max lenght of the command line, which is most likely caused by the fact that the chocolatey bin uses a .cmd wrapper. Would you be open to using a powershell wrapper instead.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

we ran into the max lenght of the command line

How many files are you signing? I just noticed that your script invokes Start-Process so I guess several processes are spawned in parallel, and that may be the cause of this issue. A network component probably saturates at some point, maybe the Azure server simply blocks the flood of connections. What happens if you add a 1 second delay before starting the process?

Would you be open to using a powershell wrapper instead.

Is it possible to have both? I'm not familiar with PowerShell, any help would be welcome.

@ROGG437063
Copy link
Author

I am signing about 200 files when the error happened. I was assuming the same thing, I am just not very familiar with the kind of network resources used, and if you can over saturate those or maybe have them be locked by the other process.

I am not sure if it is possible to have both a powershell wrapper and cmd wrapper at the same time. I assume it would be possible to make either an entirely separate powershell module for it, or to register the powershell wrapper as a different bin, maybe called jsignps, during the chocolatey installation. I am not sure if this kind of command line max length is also an issue on ohter platforms than windows.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

Alternatively, Jsign could be improved to support glob patterns and/or signing a whole directory tree recursively. Or accept a file containing a list of files to sign as input.

@ROGG437063
Copy link
Author

Honestly, i'd like to see both, though the second is more powerful, and will probably help more people. I am not sure if globs on windows and linux are equivalent enough to add that without too much difficulty.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

I've implemented the file list in d668c2e. You just have to create a text file with the list of files to sign, one per line, and then specify this file with the @ prefix:

jsign --storetype TRUSTEDSIGNING --keystore {url} --storepass {token} --alias account/profile @files.txt

@ROGG437063
Copy link
Author

ROGG437063 commented May 16, 2024

Sounds good, i'll test if it works for me.
Edit: I see some of the tests failed, so the build did not complete.

@ROGG437063
Copy link
Author

I also have some more or less working code for a very simple powershell module wrapper around jsign, though it probably needs more testing to become part of the main package.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

I see some of the tests failed, so the build did not complete

I've fixed the build error, you can get the artifacts here: https://github.com/ebourg/jsign/actions/runs/9113199977/artifacts/1509522053

@ROGG437063
Copy link
Author

I saw, and will test the feature on my side.

@ROGG437063
Copy link
Author

ROGG437063 commented May 16, 2024

I get below error when using it with the following list file

jsign: Failed to read the file list: temp.txt
java.nio.charset.MalformedInputException: Input length = 1
        at java.base/java.nio.charset.CoderResult.throwException(Unknown Source)
        at java.base/sun.nio.cs.StreamDecoder.implRead(Unknown Source)
        at java.base/sun.nio.cs.StreamDecoder.read(Unknown Source)
        at java.base/java.io.InputStreamReader.read(Unknown Source)
        at java.base/java.io.BufferedReader.fill(Unknown Source)
        at java.base/java.io.BufferedReader.readLine(Unknown Source)
        at java.base/java.io.BufferedReader.readLine(Unknown Source)
        at java.base/java.nio.file.Files.readAllLines(Unknown Source)
        at java.base/java.nio.file.Files.readAllLines(Unknown Source)
        at net.jsign.JsignCLI.expand(JsignCLI.java:183)
        at net.jsign.JsignCLI.execute(JsignCLI.java:171)
        at net.jsign.JsignCLI.main(JsignCLI.java:50)

temp.txt
I also tried without the quotes
Does this require a specific java distribution. I believe I am using Azul Zulu JRE 17.48.15

@ROGG437063
Copy link
Author

ROGG437063 commented May 16, 2024

Edit: I am probably wrong about this because the error outputs the filename correctly.

I think the cause might be the substring(1) for the filename.
I use below command or similar
java -jar .\jsign-6.1-SNAPSHOT.jar --storetype TRUSTEDSIGNING --keystore neu.codesigning.azure.net --storepass $token --alias prd10523MKBTsa/codesigning "@temp.txt"
I assume the quotes around the filename become part of the string, meaning the @ and endquote remain as part of the filepath.
I can however not leave them out, because powershell assumes I am trying to use variable splatting using the @ otherwise.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

jsign: Failed to read the file list: temp.txt
java.nio.charset.MalformedInputException: Input length = 1
        at java.base/java.nio.charset.CoderResult.throwException(Unknown Source)
        at java.base/sun.nio.cs.StreamDecoder.implRead(Unknown Source)
        at java.base/sun.nio.cs.StreamDecoder.read(Unknown Source)
        at java.base/java.io.InputStreamReader.read(Unknown Source)
        at java.base/java.io.BufferedReader.fill(Unknown Source)
        at java.base/java.io.BufferedReader.readLine(Unknown Source)
        at java.base/java.io.BufferedReader.readLine(Unknown Source)
        at java.base/java.nio.file.Files.readAllLines(Unknown Source)
        at java.base/java.nio.file.Files.readAllLines(Unknown Source)
        at net.jsign.JsignCLI.expand(JsignCLI.java:183)
        at net.jsign.JsignCLI.execute(JsignCLI.java:171)
        at net.jsign.JsignCLI.main(JsignCLI.java:50)

Files.readAllLines() fails to read the text file due its encoding (UTF-16 with byte order marks). Try writing the file in UTF-8 without BOM or in ISO-8859-1.

@temp.txt can be quoted, but not the files inside.

@ebourg
Copy link
Owner

ebourg commented May 16, 2024

Another iteration, supporting UTF-16 files and quoted file names:
https://github.com/ebourg/jsign/actions/runs/9116054327/artifacts/1510286219

@ROGG437063
Copy link
Author

New build seems to be working well.

@ROGG437063
Copy link
Author

Given that the filelist makes it unneccesary to solve this issue, that doesn't really seem to be a real bug, I think this issue can be closed.
However, I was wondering if you already have an ETA on the full 6.1 release?

@ebourg
Copy link
Owner

ebourg commented May 17, 2024

I've further refined the command line tool, it now supports wildcard patterns. For example:

  • C:\Users\ROGG437063\Desktop\testscripts\*.ps1 to sign all the ps1 files in the testscripts directory
  • build/**/*.exe to scan the build directory recursively and sign all the executable files

The artifacts are here if you want to give it a try:
https://github.com/ebourg/jsign/actions/runs/9129076140/artifacts/1513339707

The original issue wasn't a bug but it still led to interesting improvements.

I think I'll cut the new release next month.

@ROGG437063
Copy link
Author

Sounds good, wildcard pasterns are a great addition, especially as signtool and trusted singing powershell seem to omit these features, which makes signing multiple files a nightmare.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants