/** * sends TS Request and receives an answer in following definition * * <p>The TimeStampResp ASN.1 type definition: * * <pre> * * TimeStampResp ::= SEQUENCE { * status PKIStatusInfo, * timeStampToken TimeStampToken OPTIONAL ] * * PKIStatusInfo ::= SEQUENCE { * status PKIStatus, * statusString PKIFreeText OPTIONAL, * failInfo PKIFailureInfo OPTIONAL } * * PKIStatus ::= INTEGER { * granted (0), * -- when the PKIStatus contains the value zero a TimeStampToken, as * -- requested, is present. * grantedWithMods (1), * -- when the PKIStatus contains the value one a TimeStampToken, * -- with modifications, is present. * rejection (2), * waiting (3), * revocationWarning (4), * -- this message contains a warning that a revocation is * -- imminent * revocationNotification (5) * -- notification that a revocation has occurred } * * PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String * -- text encoded as UTF-8 String (note: each UTF8String SHOULD * -- include an RFC 1766 language tag to indicate the language * -- of the contained text) * * PKIFailureInfo ::= BIT STRING { * badAlg (0), * -- unrecognized or unsupported Algorithm Identifier * badRequest (2), * -- transaction not permitted or supported * badDataFormat (5), * -- the data submitted has the wrong format * timeNotAvailable (14), * -- the TSA's time source is not available * unacceptedPolicy (15), * -- the requested TSA policy is not supported by the TSA * unacceptedExtension (16), * -- the requested extension is not supported by the TSA * addInfoNotAvailable (17) * -- the additional information requested could not be understood * -- or is not available * systemFailure (25) * -- the request cannot be handled due to system failure } * * TimeStampToken ::= ContentInfo * -- contentType is id-signedData * -- content is SignedData * -- eContentType within SignedData is id-ct-TSTInfo * -- eContent within SignedData is TSTInfo * * </pre> * * @param tsq TimeStamp Request to be sent to TSA * @param server complete URL of the TSA server * @return TimeStamp Response created from TSA's response */ private TimeStampResponse getTSResponse(TimeStampRequest tsq, String server) throws IOException, TSPException { logger.trace("entering getTSResponse() method"); logger.entry(tsq, server); final byte[] request = tsq.getEncoded(); // open valid connection HttpURLConnection con; try { URL url = new URL(server); con = (HttpURLConnection) url.openConnection(); } catch (IOException e) { logger.error("TSA server couldn't be contacted"); throw e; } con.setDoOutput(true); con.setDoInput(true); con.setRequestProperty("Content-type", "application/timestamp-query"); // con.setRequestProperty("Content-length", String.valueOf(request.length)); logger.info("TSA server was successfully contacted"); // send request OutputStream out; try { out = con.getOutputStream(); out.write(request); out.flush(); } catch (IOException e) { logger.error("Failed to send the TS request."); throw e; } logger.debug("TS request sent"); // receive response InputStream in; TimeStampResp resp; TimeStampResponse response; try { // verify connection status if (con.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new IOException( "Received HTTP error: " + con.getResponseCode() + " - " + con.getResponseMessage()); } else { logger.debug("Response Code: {}", con.getResponseCode()); } // accept the answer in = con.getInputStream(); resp = TimeStampResp.getInstance(new ASN1InputStream(in).readObject()); response = new TimeStampResponse(resp); // verify the answer response.validate(tsq); } catch (TSPException | IOException e) { logger.error("Cannot interpret incoming data."); throw e; } logger.debug("Status: {}", response.getStatusString()); // null means OK return logger.exit(response); }
public TimeStampToken generate(TimeStampRequest request, BigInteger serialNumber, Date genTime) throws TSPException { if (signerInfoGen == null) { throw new IllegalStateException( "can only use this method with SignerInfoGenerator constructor"); } ASN1ObjectIdentifier digestAlgOID = new ASN1ObjectIdentifier(request.getMessageImprintAlgOID()); AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, new DERNull()); MessageImprint messageImprint = new MessageImprint(algID, request.getMessageImprintDigest()); Accuracy accuracy = null; if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0) { DERInteger seconds = null; if (accuracySeconds > 0) { seconds = new DERInteger(accuracySeconds); } DERInteger millis = null; if (accuracyMillis > 0) { millis = new DERInteger(accuracyMillis); } DERInteger micros = null; if (accuracyMicros > 0) { micros = new DERInteger(accuracyMicros); } accuracy = new Accuracy(seconds, millis, micros); } DERBoolean derOrdering = null; if (ordering) { derOrdering = new DERBoolean(ordering); } DERInteger nonce = null; if (request.getNonce() != null) { nonce = new DERInteger(request.getNonce()); } ASN1ObjectIdentifier tsaPolicy = new ASN1ObjectIdentifier(tsaPolicyOID); if (request.getReqPolicy() != null) { tsaPolicy = new ASN1ObjectIdentifier(request.getReqPolicy()); } TSTInfo tstInfo = new TSTInfo( tsaPolicy, messageImprint, new DERInteger(serialNumber), new DERGeneralizedTime(genTime), accuracy, derOrdering, nonce, tsa, request.getExtensions()); try { CMSSignedDataGenerator signedDataGenerator = new CMSSignedDataGenerator(); if (request.getCertReq()) { // TODO: do we need to check certs non-empty? signedDataGenerator.addCertificates(new CollectionStore(certs)); signedDataGenerator.addCRLs(new CollectionStore(crls)); signedDataGenerator.addAttributeCertificates(new CollectionStore(attrCerts)); } else { signedDataGenerator.addCRLs(new CollectionStore(crls)); } signedDataGenerator.addSignerInfoGenerator(signerInfoGen); byte[] derEncodedTSTInfo = tstInfo.getEncoded(ASN1Encodable.DER); CMSSignedData signedData = signedDataGenerator.generate( new CMSProcessableByteArray(PKCSObjectIdentifiers.id_ct_TSTInfo, derEncodedTSTInfo), true); return new TimeStampToken(signedData); } catch (CMSException cmsEx) { throw new TSPException("Error generating time-stamp token", cmsEx); } catch (IOException e) { throw new TSPException("Exception encoding info", e); } }
/** * Generate a TimeStampToken for the passed in request and serialNumber marking it with the passed * in genTime. * * @param request the originating request. * @param serialNumber serial number for the TimeStampToken * @param genTime token generation time. * @param additionalExtensions extra extensions to be added to the response token. * @return a TimeStampToken * @throws TSPException */ public TimeStampToken generate( TimeStampRequest request, BigInteger serialNumber, Date genTime, Extensions additionalExtensions) throws TSPException { ASN1ObjectIdentifier digestAlgOID = request.getMessageImprintAlgOID(); AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DERNull.INSTANCE); MessageImprint messageImprint = new MessageImprint(algID, request.getMessageImprintDigest()); Accuracy accuracy = null; if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0) { ASN1Integer seconds = null; if (accuracySeconds > 0) { seconds = new ASN1Integer(accuracySeconds); } ASN1Integer millis = null; if (accuracyMillis > 0) { millis = new ASN1Integer(accuracyMillis); } ASN1Integer micros = null; if (accuracyMicros > 0) { micros = new ASN1Integer(accuracyMicros); } accuracy = new Accuracy(seconds, millis, micros); } ASN1Boolean derOrdering = null; if (ordering) { derOrdering = ASN1Boolean.getInstance(ordering); } ASN1Integer nonce = null; if (request.getNonce() != null) { nonce = new ASN1Integer(request.getNonce()); } ASN1ObjectIdentifier tsaPolicy = tsaPolicyOID; if (request.getReqPolicy() != null) { tsaPolicy = request.getReqPolicy(); } Extensions respExtensions = request.getExtensions(); if (additionalExtensions != null) { ExtensionsGenerator extGen = new ExtensionsGenerator(); if (respExtensions != null) { for (Enumeration en = respExtensions.oids(); en.hasMoreElements(); ) { extGen.addExtension( respExtensions.getExtension(ASN1ObjectIdentifier.getInstance(en.nextElement()))); } } for (Enumeration en = additionalExtensions.oids(); en.hasMoreElements(); ) { extGen.addExtension( additionalExtensions.getExtension(ASN1ObjectIdentifier.getInstance(en.nextElement()))); } respExtensions = extGen.generate(); } TSTInfo tstInfo = new TSTInfo( tsaPolicy, messageImprint, new ASN1Integer(serialNumber), new ASN1GeneralizedTime(genTime), accuracy, derOrdering, nonce, tsa, respExtensions); try { CMSSignedDataGenerator signedDataGenerator = new CMSSignedDataGenerator(); if (request.getCertReq()) { // TODO: do we need to check certs non-empty? signedDataGenerator.addCertificates(new CollectionStore(certs)); signedDataGenerator.addAttributeCertificates(new CollectionStore(attrCerts)); } signedDataGenerator.addCRLs(new CollectionStore(crls)); if (!otherRevoc.isEmpty()) { for (Iterator it = otherRevoc.keySet().iterator(); it.hasNext(); ) { ASN1ObjectIdentifier format = (ASN1ObjectIdentifier) it.next(); signedDataGenerator.addOtherRevocationInfo( format, new CollectionStore((Collection) otherRevoc.get(format))); } } signedDataGenerator.addSignerInfoGenerator(signerInfoGen); byte[] derEncodedTSTInfo = tstInfo.getEncoded(ASN1Encoding.DER); CMSSignedData signedData = signedDataGenerator.generate( new CMSProcessableByteArray(PKCSObjectIdentifiers.id_ct_TSTInfo, derEncodedTSTInfo), true); return new TimeStampToken(signedData); } catch (CMSException cmsEx) { throw new TSPException("Error generating time-stamp token", cmsEx); } catch (IOException e) { throw new TSPException("Exception encoding info", e); } }