Skip to content

Commit

Permalink
Merge pull request #94 from eu-digital-green-certificates/feat/add-re…
Browse files Browse the repository at this point in the history
…pack

Feat: Get Detached and Embedded Signatures from Parser
  • Loading branch information
f11h authored Mar 25, 2022
2 parents dc541fd + 491867a commit f6ef97e
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 23 deletions.
37 changes: 29 additions & 8 deletions src/main/java/eu/europa/ec/dgc/signing/SignedMessageParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,28 @@ public abstract class SignedMessageParser<T> {
* <p>Base64 encoded signature of the cms message.</p>
*
* <p>This string contains only the signature which signs the message.</p>
* @deprecated Use getDetachedSignature() or getEmbeddedSignature() instead.
*/
@Getter
@Deprecated
private String signature;

/**
* <p>Base64 encoded detached signature of the cms message.</p>
*
* <p>This string contains only the signature which signs the message and not the payload.</p>
*/
@Getter
private String detachedSignature;

/**
* <p>Base64 encoded embedded signature of the cms message.</p>
*
* <p>This string contains both the signature which signs the message and the corresponding payload.</p>
*/
@Getter
private String embeddedSignature;

/**
* Method to convert the encoded bytes to the actual Class instance.
*
Expand Down Expand Up @@ -229,12 +247,14 @@ private void afterPropertiesSet() {
}
signingCertificate = certificateHolderCollection.iterator().next();

// Try to extract detached CMS Signature
// Try to repack CMS
try {
signature = Base64.getEncoder().encodeToString(repackToDetachedCms(cmsSignedData).getEncoded());
detachedSignature = Base64.getEncoder().encodeToString(repack(cmsSignedData, true).getEncoded());
embeddedSignature = Base64.getEncoder().encodeToString(repack(cmsSignedData, false).getEncoded());
signature = detachedSignature; // for compatibility reasons
} catch (IOException | CMSException e) {
signature = null;
log.error("Failed to repack CMS to get detached signature.");
log.error("Failed to repack CMS.");
}

// Get signer information and verify signature
Expand All @@ -256,20 +276,21 @@ private void afterPropertiesSet() {
}

/**
* Recreates a CMS without encapsulated Data.
* Recreates a CMS w/o encapsulated Data.
*
* @param input input CMS Message
* @return CMS message without encapsulated data.
* @param input input CMS Message
* @param detached whether it should be a detached signature or not
* @return CMS message.
* @throws CMSException if repacking fails.
*/
private CMSSignedData repackToDetachedCms(CMSSignedData input) throws CMSException {
private CMSSignedData repack(CMSSignedData input, boolean detached) throws CMSException {
CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator();
cmsGenerator.addCertificates(input.getCertificates());
cmsGenerator.addSigners(input.getSignerInfos());
cmsGenerator.addAttributeCertificates(input.getAttributeCertificates());
cmsGenerator.addCRLs(input.getCRLs());

return cmsGenerator.generate(input.getSignedContent(), false);
return cmsGenerator.generate(input.getSignedContent(), !detached);
}

public enum ParserState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ void parserShouldParseByteArray() throws IOException, CertificateEncodingExcepti
Assertions.assertArrayEquals(payload, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand Down Expand Up @@ -107,7 +109,9 @@ void parserShouldParseByteArrayWithDetachedPayloadAsString() throws IOException,
Assertions.assertArrayEquals(payload, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand All @@ -119,7 +123,9 @@ void parserShouldParseString() throws IOException, CertificateEncodingException
Assertions.assertArrayEquals(payload, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand All @@ -132,7 +138,9 @@ void parserShouldParseStringWithDetachedPayload() throws IOException, Certificat
Assertions.assertArrayEquals(payload, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand Down Expand Up @@ -246,7 +254,7 @@ void parserShouldDetectInvalidSignerInfoAmount() throws Exception {
Assertions.assertFalse(parser.isSignatureVerified());
}

private void checkSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
private void checkDetachedSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
SignedByteArrayMessageParser parser = new SignedByteArrayMessageParser(
signature, Base64.getEncoder().encodeToString(payload));

Expand All @@ -256,5 +264,15 @@ private void checkSignatureFromParser(String signature) throws CertificateEncodi
Assertions.assertTrue(parser.isSignatureVerified());
Assertions.assertEquals(signature, parser.getSignature());
}

private void checkEmbeddedSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
SignedByteArrayMessageParser parser = new SignedByteArrayMessageParser(signature);

Assertions.assertEquals(SignedStringMessageParser.ParserState.SUCCESS, parser.getParserState());
Assertions.assertArrayEquals(payload, parser.getPayload());
Assertions.assertEquals(new X509CertificateHolder(signingCertificate.getEncoded()), parser.getSigningCertificate());
Assertions.assertTrue(parser.isSignatureVerified());
Assertions.assertEquals(signature, parser.getEmbeddedSignature());
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ void parserShouldParseByteArray() throws IOException, CertificateEncodingExcepti
Assertions.assertArrayEquals(payloadCertificate.getEncoded(), parser.getPayload().getEncoded());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand Down Expand Up @@ -105,7 +107,9 @@ void parserShouldParseByteArrayWithDetachedPayloadAsString() throws IOException,
Assertions.assertArrayEquals(payloadCertificate.getEncoded(), parser.getPayload().getEncoded());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand All @@ -117,7 +121,9 @@ void parserShouldParseString() throws IOException, CertificateEncodingException
Assertions.assertArrayEquals(payloadCertificate.getEncoded(), parser.getPayload().getEncoded());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand All @@ -130,7 +136,9 @@ void parserShouldParseStringWithDetachedPayload() throws IOException, Certificat
Assertions.assertArrayEquals(payloadCertificate.getEncoded(), parser.getPayload().getEncoded());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand Down Expand Up @@ -275,7 +283,7 @@ void parserShouldDetectInvalidSignerInfoAmount() throws Exception {
Assertions.assertFalse(parser.isSignatureVerified());
}

private void checkSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
private void checkDetachedSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
SignedCertificateMessageParser parser = new SignedCertificateMessageParser(
signature, Base64.getEncoder().encodeToString(payloadCertificate.getEncoded()));

Expand All @@ -285,5 +293,15 @@ private void checkSignatureFromParser(String signature) throws CertificateEncodi
Assertions.assertTrue(parser.isSignatureVerified());
Assertions.assertEquals(signature, parser.getSignature());
}

private void checkEmbeddedSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
SignedCertificateMessageParser parser = new SignedCertificateMessageParser(signature);

Assertions.assertEquals(SignedStringMessageParser.ParserState.SUCCESS, parser.getParserState());
Assertions.assertEquals(new X509CertificateHolder(payloadCertificate.getEncoded()), parser.getPayload());
Assertions.assertEquals(new X509CertificateHolder(signingCertificate.getEncoded()), parser.getSigningCertificate());
Assertions.assertTrue(parser.isSignatureVerified());
Assertions.assertEquals(signature, parser.getEmbeddedSignature());
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ void parserShouldParseByteArray() throws IOException, CertificateEncodingExcepti
Assertions.assertEquals(payloadString, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand Down Expand Up @@ -103,7 +105,9 @@ void parserShouldParseByteArrayWithDetachedPayloadAsString() throws IOException,
Assertions.assertEquals(payloadString, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand All @@ -115,7 +119,9 @@ void parserShouldParseString() throws IOException, CertificateEncodingException
Assertions.assertEquals(payloadString, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand All @@ -128,7 +134,9 @@ void parserShouldParseStringWithDetachedPayload() throws IOException, Certificat
Assertions.assertEquals(payloadString, parser.getPayload());
Assertions.assertArrayEquals(signingCertificate.getEncoded(), parser.getSigningCertificate().getEncoded());
Assertions.assertTrue(parser.isSignatureVerified());
checkSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getSignature());
checkDetachedSignatureFromParser(parser.getDetachedSignature());
checkEmbeddedSignatureFromParser(parser.getEmbeddedSignature());
}

@Test
Expand Down Expand Up @@ -242,7 +250,7 @@ void parserShouldDetectInvalidSignerInfoAmount() throws Exception {
Assertions.assertFalse(parser.isSignatureVerified());
}

private void checkSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
private void checkDetachedSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
SignedStringMessageParser parser = new SignedStringMessageParser(
signature, Base64.getEncoder().encodeToString(payloadString.getBytes(StandardCharsets.UTF_8)));

Expand All @@ -251,6 +259,17 @@ private void checkSignatureFromParser(String signature) throws CertificateEncodi
Assertions.assertEquals(new X509CertificateHolder(signingCertificate.getEncoded()), parser.getSigningCertificate());
Assertions.assertTrue(parser.isSignatureVerified());
Assertions.assertEquals(signature, parser.getSignature());
Assertions.assertEquals(signature, parser.getDetachedSignature());
}

private void checkEmbeddedSignatureFromParser(String signature) throws CertificateEncodingException, IOException {
SignedStringMessageParser parser = new SignedStringMessageParser(signature);

Assertions.assertEquals(SignedStringMessageParser.ParserState.SUCCESS, parser.getParserState());
Assertions.assertEquals(payloadString, parser.getPayload());
Assertions.assertEquals(new X509CertificateHolder(signingCertificate.getEncoded()), parser.getSigningCertificate());
Assertions.assertTrue(parser.isSignatureVerified());
Assertions.assertEquals(signature, parser.getEmbeddedSignature());
}
}

0 comments on commit f6ef97e

Please sign in to comment.