Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signature length not correct when calling PGPOnePassSignature.verify

We’re using a Java libarary called license3j for license management. The library uses asymmetric encryption and relies itself on Bouncycastle. We create a license file using a simple gpg command and verify the license within our software using our public key. So far everything worked fine. BUT: In 1,000 generated licenses, there is a very small fraction which cannot be verified correctly, although, they are in fact valid (approximately 5/1000).

What happens in this case: When the license is to be verified in com.verhas.licensor.License.setLicenseEncoded(InputStream), the org.bouncycastle.openpgp.PGPOnePassSignature.verify(PGPSignature) throws the following exception:

org.bouncycastle.openpgp.PGPRuntimeOperationException: unable to verify signature: Signature length not correct: got 511 but was expecting 512

Sounds rather obscure to me, having only basic cryptography knowledge. Spending hours googling, gave me the clue, that there is something about "leading zeros". So, in the given example, obviously a leading zero was stripped away somewhere (where?), and the lengths of the signature data to compare do not match. Makes sense.

Now, I’ve no clue, where the issue might be located. Is it during creation of the license file? Essentially, we’re just doing the following:

gpg --armor --local-user=name.of.software --sign

Which will give us the license file.

Or does the error happen during verification? Do I have to modify any Bouncycastle configuration to correctly address the leading zero issue? Their FAQ gives some hints, but the License3j source obviously never makes use of any Cipher instance, so I’m totally lost on how to integrate this into the given API.

I’m aware that this is a very special problem with a library which is obviously not very well known. Thus, I appreciate any little feedback or input.

like image 338
qqilihq Avatar asked Feb 01 '17 18:02

qqilihq


1 Answers

Looks like it is a bug in bouncycastle, only encountered in versions of Java after 1.6, bouncycastle has always created the data wrong, but Java became more strict since 1.7 in the data it will accept during verification.

Bouncycastle is failing to pad the signature to the right length when it serializes it to the file, if the integer has enough leading zeros then the byte representation of it will be smaller.
Java versions 1.7 and above expect RSA signature bytes to be the same length as the key.

Bouncycastle converts the RSA signature byte array(returned from Java's RSA JCE provider) into an integer and it discards information about its length.
Line 263 of the PGPSignatureGenerator shows where the RSA signature bytes are returned from JCE and converted into an integer.

This integer is eventually written to the outputstream using MPInteger#encode which just uses the bitlength of the underlying biginteger to determine how much data to write.

This answer describes more about why you see this aproximatley one in every 200 cases and how the version of Java plays a role.

like image 85
Magnus Avatar answered Nov 20 '22 18:11

Magnus