Signatures.java

1
/*-
2
 * #%L
3
 * io.earcam.utilitarian.security
4
 * %%
5
 * Copyright (C) 2017 earcam
6
 * %%
7
 * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8
 *
9
 * You <b>must</b> choose to accept, in full - any individual or combination of
10
 * the following licenses:
11
 * <ul>
12
 * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13
 * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14
 * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15
 * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16
 * </ul>
17
 * #L%
18
 */
19
package io.earcam.utilitarian.security;
20
21
import java.io.IOException;
22
import java.security.GeneralSecurityException;
23
import java.security.cert.Certificate;
24
import java.security.cert.X509Certificate;
25
import java.util.ArrayList;
26
import java.util.Arrays;
27
import java.util.Collection;
28
import java.util.List;
29
30
import org.bouncycastle.cert.X509CertificateHolder;
31
import org.bouncycastle.cert.jcajce.JcaCertStore;
32
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
33
import org.bouncycastle.cms.CMSException;
34
import org.bouncycastle.cms.CMSProcessableByteArray;
35
import org.bouncycastle.cms.CMSSignedData;
36
import org.bouncycastle.cms.CMSSignedDataGenerator;
37
import org.bouncycastle.cms.CMSSignedDataParser;
38
import org.bouncycastle.cms.CMSTypedData;
39
import org.bouncycastle.cms.SignerInfoGenerator;
40
import org.bouncycastle.cms.SignerInformation;
41
import org.bouncycastle.cms.SignerInformationStore;
42
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
43
import org.bouncycastle.jce.provider.BouncyCastleProvider;
44
import org.bouncycastle.operator.ContentSigner;
45
import org.bouncycastle.operator.DigestCalculatorProvider;
46
import org.bouncycastle.operator.OperatorCreationException;
47
import org.bouncycastle.operator.OperatorException;
48
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
49
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
50
import org.bouncycastle.util.Store;
51
52
import io.earcam.unexceptional.Exceptional;
53
import io.earcam.unexceptional.UncheckedSecurityException;
54
55
public final class Signatures {
56
57
	private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();
58
59
60
	private Signatures()
61
	{}
62
63
64
	public static byte[] sign(byte[] contents, OpenedKeyStore keyStore, String signatureAlgorithm)
65
	{
66
		try {
67
			CMSSignedDataGenerator gen = createSignedDataGenerator(keyStore, signatureAlgorithm);
68
69
			CMSTypedData cmsData = new CMSProcessableByteArray(contents);
70
			CMSSignedData signedData = gen.generate(cmsData);
71 1 1. sign : mutated return of Object value for io/earcam/utilitarian/security/Signatures::sign to ( if (x != null) null else throw new RuntimeException ) → KILLED
			return signedData.getEncoded();
72
		} catch(CMSException | OperatorException | IllegalArgumentException | IOException | GeneralSecurityException e) {
73
			throw new UncheckedSecurityException(new GeneralSecurityException(e));
74
		}
75
	}
76
77
78
	private static CMSSignedDataGenerator createSignedDataGenerator(OpenedKeyStore openedKeyStore, String signatureAlgorithm)
79
			throws GeneralSecurityException, OperatorException, CMSException
80
	{
81
		List<Certificate> certChain = Arrays.asList(openedKeyStore.getCertificateChain());
82
		JcaCertStore certStore = new JcaCertStore(certChain);
83
		Certificate cert = openedKeyStore.getCertificate();
84
		ContentSigner signer = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(PROVIDER).build(openedKeyStore.privateKey());
85
		CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
86
		DigestCalculatorProvider dcp = new JcaDigestCalculatorProviderBuilder().setProvider(PROVIDER).build();
87
		SignerInfoGenerator sig = new JcaSignerInfoGeneratorBuilder(dcp).build(signer, (X509Certificate) cert);
88 1 1. createSignedDataGenerator : removed call to org/bouncycastle/cms/CMSSignedDataGenerator::addSignerInfoGenerator → KILLED
		generator.addSignerInfoGenerator(sig);
89 1 1. createSignedDataGenerator : removed call to org/bouncycastle/cms/CMSSignedDataGenerator::addCertificates → KILLED
		generator.addCertificates(certStore);
90 1 1. createSignedDataGenerator : mutated return of Object value for io/earcam/utilitarian/security/Signatures::createSignedDataGenerator to ( if (x != null) null else throw new RuntimeException ) → KILLED
		return generator;
91
	}
92
93
94
	public static List<X509Certificate> certificatesFromSignature(byte[] encapSigData)
95
	{
96
		try {
97
			CMSSignedDataParser parser = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(PROVIDER).build(), encapSigData);
98
99
			@SuppressWarnings("unchecked")
100
			Store<X509CertificateHolder> certStore = parser.getCertificates();
101
			SignerInformationStore signers = parser.getSignerInfos();
102
103
			List<X509Certificate> certificates = new ArrayList<>();
104
105
			JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(PROVIDER);
106
107
			for(SignerInformation signer : signers.getSigners()) {
108
				@SuppressWarnings("unchecked")
109
				Collection<X509CertificateHolder> holders = certStore.getMatches(signer.getSID());
110
111
				for(X509CertificateHolder holder : holders) {
112
					X509Certificate certificate = Exceptional.apply(converter::getCertificate, holder);
113
					certificates.add(certificate);
114
				}
115
			}
116 1 1. certificatesFromSignature : mutated return of Object value for io/earcam/utilitarian/security/Signatures::certificatesFromSignature to ( if (x != null) null else throw new RuntimeException ) → KILLED
			return certificates;
117
		} catch(CMSException | OperatorCreationException e) {
118
			throw new UncheckedSecurityException(new GeneralSecurityException(e));
119
		}
120
	}
121
122
}

Mutations

71

1.1
Location : sign
Killed by : io.earcam.utilitarian.security.SignaturesTest.symmetric()
mutated return of Object value for io/earcam/utilitarian/security/Signatures::sign to ( if (x != null) null else throw new RuntimeException ) → KILLED

88

1.1
Location : createSignedDataGenerator
Killed by : io.earcam.utilitarian.security.SignaturesTest.symmetric()
removed call to org/bouncycastle/cms/CMSSignedDataGenerator::addSignerInfoGenerator → KILLED

89

1.1
Location : createSignedDataGenerator
Killed by : io.earcam.utilitarian.security.SignaturesTest.symmetric()
removed call to org/bouncycastle/cms/CMSSignedDataGenerator::addCertificates → KILLED

90

1.1
Location : createSignedDataGenerator
Killed by : io.earcam.utilitarian.security.SignaturesTest.symmetric()
mutated return of Object value for io/earcam/utilitarian/security/Signatures::createSignedDataGenerator to ( if (x != null) null else throw new RuntimeException ) → KILLED

116

1.1
Location : certificatesFromSignature
Killed by : io.earcam.utilitarian.security.SignaturesTest.symmetric()
mutated return of Object value for io/earcam/utilitarian/security/Signatures::certificatesFromSignature to ( if (x != null) null else throw new RuntimeException ) → KILLED

Active mutators

Tests examined


Report generated by PIT 1.4.3