Skip to content

Instantly share code, notes, and snippets.

@Glamdring
Last active January 17, 2019 07:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Glamdring/08b033db4a564e2e093c210f82cacf6c to your computer and use it in GitHub Desktop.
Save Glamdring/08b033db4a564e2e093c210f82cacf6c to your computer and use it in GitHub Desktop.
A local TSA
@Service
public class TimestampService {
private static final Logger logger = LoggerFactory.getLogger(TimestampService.class);
public static final AlgorithmIdentifier sha512oid = getSha512Oid();
private SecureRandom random = new SecureRandom();
@Value("${timestamp.keystore.path}")
private Resource keystorePath;
@Value("${timestamp.keystore.pass}")
private String keystorePass;
@Value("${timestamp.keystore.alias}")
private String keystoreAlias;
private KeyStore keystore;
private X509CertificateHolder certificateHolder;
private SignerInfoGeneratorBuilder signerInfoGenBuilder;
private static AlgorithmIdentifier getSha512Oid() {
DigestAlgorithmIdentifierFinder algorithmFinder = new DefaultDigestAlgorithmIdentifierFinder();
return algorithmFinder.find("SHA-512");
}
@PostConstruct
public void init() throws Exception {
keystore = KeyStore.getInstance("JKS");
try (InputStream in = keystorePath.getInputStream()) {
keystore.load(in, keystorePass.toCharArray());
}
X509Certificate cert = (X509Certificate) keystore.getCertificate(keystoreAlias);
signerInfoGenBuilder = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
final ESSCertIDv2 essCertidV2 = new ESSCertIDv2(sha512oid, DigestUtils.sha512(cert.getEncoded()),
new IssuerSerial(new X500Name(cert.getSubjectX500Principal().getName()), cert.getSerialNumber()));
signerInfoGenBuilder.setSignedAttributeGenerator(new CMSAttributeTableGenerator() {
@SuppressWarnings("rawtypes")
public AttributeTable getAttributes(Map parameters)
throws CMSAttributeTableGenerationException
{
CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator();
AttributeTable table = attrGen.getAttributes(parameters);
table = table.add(PKCSObjectIdentifiers.id_aa_signingCertificateV2, new SigningCertificateV2(essCertidV2));
return table;
}
});
certificateHolder = new X509CertificateHolder(cert.getEncoded());
}
public TimeStampToken timestamp(TimeStampReq request) {
TimeStampRequest tsRequest = new TimeStampRequest(request.getEncoded());
return createGenerator().generate(tsRequest, BigInteger.valueOf(random.nextInt(Integer.MAX_VALUE)), new Date());
}
/**
* Some classes here are not thread-safe, therefore we need to instantiate the whole thing for each local timestamping request
*/
private TimeStampTokenGenerator createGenerator() throws GeneralSecurityException,
OperatorCreationException, IOException, TSPException {
BcRSAContentSignerBuilder signerBuilder = new BcRSAContentSignerBuilder(new AlgorithmIdentifier(PKCSObjectIdentifiers.sha512WithRSAEncryption), sha512oid);
SignerInfoGenerator generator;
generator = signerInfoGenBuilder.build(signerBuilder.build(PrivateKeyFactory
.createKey(keystore.getKey(keystoreAlias, keystorePass.toCharArray()).getEncoded())),
certificateHolder);
TimeStampTokenGenerator tokenGenerator = new TimeStampTokenGenerator(generator, new BcDigestCalculatorProvider().get(sha512oid), new ASN1ObjectIdentifier("1.3.6.1.4.1.3029.54.11940.54"));
tokenGenerator.addCertificates(new CollectionStore<X509CertificateHolder>(Collections.singleton(certificateHolder)));
return tokenGenerator;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment