Когда я использую URL-адрес службы TimeStamp и помещаю его в качестве атрибута в сигнатуру CAdES-T. Я использовал следующие услуги:
http://psis.catcert.net/psis/catcert/tsp (ответ идет с токеном)
http://timestamp.comodoca.com (ответ приходит без токена)
У меня вопрос, должен ли я обработать подписанный файл другим способом, чтобы использовать метку времени?
public byte[] addTimestamp(final byte[] pkcs7, final String hashAlgorithm, final Calendar time) throws NoSuchAlgorithmException, AOException, IOException, TSPException, NoSuchProviderException {**
final String digestAlgorithm = AOSignConstants.getDigestAlgorithmName(hashAlgorithm);
CMSSignedData signedData;
try {
signedData = new CMSSignedData(pkcs7);
}
catch (final Exception e) {
throw new IllegalArgumentException("The input data is not a CMS SignedData: " + e);
}
final SignerInformationStore origSignerInfoStore = signedData.getSignerInfos();
final List<SignerInformation> vNewSigners = new ArrayList<>();
final Collection<?> ovSigners = origSignerInfoStore.getSigners();
for (final Object name : ovSigners) {
final SignerInformation si = (SignerInformation) name;
final byte[] tsToken = getTimeStampToken(
MessageDigest.getInstance(digestAlgorithm).digest(si.getSignature()),
digestAlgorithm,
time
);
final ASN1Primitive derObj;
try (
final ASN1InputStream is = new ASN1InputStream(new ByteArrayInputStream(tsToken));
) {
derObj = is.readObject();
}
final DERSet derSet = new DERSet(derObj);
final Attribute unsignAtt = new Attribute(new ASN1ObjectIdentifier(SIGNATURE_TIMESTAMP_TOKEN_OID), derSet);
final Hashtable<ASN1ObjectIdentifier, Attribute> ht = new Hashtable<>();
ht.put(new ASN1ObjectIdentifier(SIGNATURE_TIMESTAMP_TOKEN_OID), unsignAtt);
final AttributeTable unsignedAtts = new AttributeTable(ht);
vNewSigners.add(SignerInformation.replaceUnsignedAttributes(si, unsignedAtts));
}
return CMSSignedData.replaceSigners(signedData, new SignerInformationStore(vNewSigners)).getEncoded();
}
public byte[] getTimeStampToken(final byte[] imprint, final String hashAlgorithm, final Calendar time) throws AOException, IOException {**
final TimeStampRequest request = this.tsqGenerator.generate(
new ASN1ObjectIdentifier(hashAlgorithm != null ? AOAlgorithmID.getOID(hashAlgorithm) : X509ObjectIdentifiers.id_SHA1.getId()),
imprint,
BigInteger.valueOf(time != null ? time.getTimeInMillis() : System.currentTimeMillis())
);
final byte[] requestBytes = request.getEncoded();
final byte[] rawResponse = getTSAResponse(requestBytes);
TimeStampResponse response = null;
try {
response = new TimeStampResponse(rawResponse);
}
catch (final Exception e) {
LOGGER.severe("TSA response: " + response.getStatusString());
throw new AOException("Error getting the response from the TSA: " + e, e);
}
//Validate the attributes of the response (RFC 3161 PKIStatus)
try {
response.validate(request);
}
catch (final Exception e) {
throw new AOException("Error validating the response of the TSA: " + e, e);
}
final PKIFailureInfo failure = response.getFailInfo();
final int value = failure == null ? 0 : failure.intValue();
if (value != 0) {
throw new AOException("Invalid response from the TSA ('" + this.tsaURL + "') with the code " + value);
}
//We extract the time stamp token (removing the status information from the communications)
final TimeStampToken tsToken = response.getTimeStampToken();
if (tsToken == null) {
throw new AOException("The response of the TSA ('" + this.tsaURL + "') is not a valid time stamp: " + response.getStatusString());
}
return tsToken.getEncoded();
}
private byte[] getTSAResponse(final byte[] request) throws IOException {
if (this.tsaURL.getScheme().equals("socket")) {
return getTSAResponseSocket(request);
}
if (this.tsaURL.getScheme().equals("http")) {
return getTSAResponseHttp(request);
}
if (this.tsaURL.getScheme().equals("https")) {
return getTSAResponseHttps(request);
}
throw new UnsupportedOperationException("Connection protocol with TSA not supported: " + this.tsaURL.getScheme());
}