Last active
January 17, 2019 07:17
-
-
Save Glamdring/08b033db4a564e2e093c210f82cacf6c to your computer and use it in GitHub Desktop.
A local TSA
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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