-
-
Save Manouchehri/fd754e402d98430243455713efada710 to your computer and use it in GitHub Desktop.
https://rfc3161.ai.moda | |
https://rfc3161.ai.moda/adobe | |
https://rfc3161.ai.moda/microsoft | |
https://rfc3161.ai.moda/apple | |
https://rfc3161.ai.moda/any | |
http://rfc3161.ai.moda | |
http://timestamp.digicert.com | |
http://timestamp.globalsign.com/tsa/r6advanced1 | |
http://rfc3161timestamp.globalsign.com/advanced | |
http://timestamp.sectigo.com | |
http://timestamp.apple.com/ts01 | |
http://tsa.mesign.com | |
http://time.certum.pl | |
https://freetsa.org | |
http://tsa.startssl.com/rfc3161 | |
http://dse200.ncipher.com/TSS/HttpTspServer | |
http://zeitstempel.dfn.de | |
https://ca.signfiles.com/tsa/get.aspx | |
http://services.globaltrustfinder.com/adss/tsa | |
https://tsp.iaik.tugraz.at/tsp/TspRequest | |
http://timestamp.entrust.net/TSS/RFC3161sha2TS | |
http://timestamp.acs.microsoft.com |
The https://rfc3161.ai.moda/[*] load balancer sounds really great. Unfortunately we are not able to use it as our custom (time)stamping service needs to have list of all used TSA CAs root certificates to consider them trusted.
Would it be possible to have a list with links to root certificates of all active CAs used for https://rfc3161.ai.moda/[*] so we could download them?
maybe it will be useful to someone:
#!/bin/bash
#
# tests TSA servers
#
# copyright: public domain / MIT
#
# 1. creates a random hash and nonce
# 2. creates a .tsq file and sends it to the server
# 3. collects certificates from response and saves to .p7b file
# 4. saves validity of certificates from the chain
# 5. saves http address from which any missing certificates can be downloaded
#
# RUN:
# ./tsa_batch.sh
#
hashedMessage_rand () {
echo "$(openssl rand -hex 64)" | cut -c1-64
}
# md5 cut -c1-32
# sha1 cut -c1-40
# sha224 cut -c1-56
# sha256 cut -c1-64
# sha384 cut -c1-96
# sha512 cut -c1-128
#hashedMessage="00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
# change:
# parameter.1 = FORMAT:HEX,OCTETSTRING:$(hashedMessage_rand)
# to:
# parameter.1 = FORMAT:HEX,OCTETSTRING:${hashedMessage}
# sha1/sha256/sha384/sha512
algorithmIdentifier="sha256"
# ~128 bits entropy
nonce_32 () {
echo "$(shuf -i 1-7 -n 1)$(openssl rand -hex 20)" | cut -c1-32
}
asn1parse_timestamp_request () {
cat <<-EOF
asn1 = SEQUENCE:TimeStampReq
[ TimeStampReq ]
parameter.0 = INTEGER:1
parameter.1 = SEQUENCE:messageImprint
#parameter.2 = OID:1.2.3.4
parameter.3 = INTEGER:0x$(nonce_32)
parameter.4 = BOOLEAN:TRUE
[ messageImprint ]
parameter.0 = SEQUENCE:hashAlgorithm
parameter.1 = FORMAT:HEX,OCTETSTRING:$(hashedMessage_rand)
[ hashAlgorithm ]
parameter.0 = OID:${algorithmIdentifier}
parameter.1 = NULL
EOF
}
generate_tsr () {
cat <(echo "$(asn1parse_timestamp_request)") | openssl asn1parse -genconf /dev/stdin -noout -out "${ts_name}_timestamp_query.tsq" && \
openssl ts -query -config /dev/null -text -in "${ts_name}_timestamp_query.tsq" > "${ts_name}_timestamp_query.tsq.txt" && \
curl ${tsr_server} -H 'Content-Type: application/timestamp-query' -s -S --data-binary "@${ts_name}_timestamp_query.tsq" -o "${ts_name}_timestamp_response.tsr" && \
openssl ts -reply -config /dev/null -text -in "${ts_name}_timestamp_response.tsr" > "${ts_name}_timestamp_response.tsr.txt" && \
openssl ts -reply -config /dev/null -token_out -in "${ts_name}_timestamp_response.tsr" | openssl pkcs7 -inform DER -print_certs -text | grep -C1 "Not After" > "${ts_name}_chain_validity.txt" && \
openssl ts -reply -config /dev/null -token_out -in "${ts_name}_timestamp_response.tsr" | openssl pkcs7 -inform DER -print_certs | awk '/^-----BEGIN CERTIFICATE-----/{n++;s=1}s{print}/^-----END CERTIFICATE-----/{s=0}' | openssl crl2pkcs7 -inform PEM -outform DER -nocrl -certfile /dev/stdin -out "${ts_name}_chain.p7b" && \
echo "====" >> "${ts_name}_chain_validity.txt" && \
openssl ts -reply -config /dev/null -token_out -in "${ts_name}_timestamp_response.tsr" | openssl pkcs7 -inform DER -print_certs -text | grep -C0 "CA Issuers" >> "${ts_name}_chain_validity.txt"
echo "DONE :: ${tsr_server}"
echo "-------"
#dumpasn1 -apz "${ts_name}_timestamp_response.tsr" | awk '{ sub(/[ \t]+$/, ""); print }' > "${ts_name}_timestamp_response.tsr.dumpasn1.txt"
}
# https://gist.github.com/Manouchehri/fd754e402d98430243455713efada710
ts_name="digicert"
tsr_server="http://timestamp.digicert.com"
generate_tsr
ts_name="globalsign"
tsr_server="http://aatl-timestamp.globalsign.com/tsa/aohfewat2389535fnasgnlg5m23"
generate_tsr
ts_name="sectigo"
tsr_server="https://timestamp.sectigo.com"
generate_tsr
ts_name="sectigo_2"
tsr_server="https://timestamp.sectigo.com/qualified"
generate_tsr
ts_name="entrust"
tsr_server="http://timestamp.entrust.net/TSS/RFC3161sha2TS"
generate_tsr
ts_name="swisssign"
tsr_server="http://tsa.swisssign.net"
generate_tsr
ts_name="quovadisglobal"
tsr_server="http://ts.quovadisglobal.com/ch"
generate_tsr
ts_name="quovadisglobal_2"
tsr_server="http://ts.quovadisglobal.com/eu"
generate_tsr
ts_name="ssl_com"
tsr_server="http://ts.ssl.com"
generate_tsr
ts_name="identrust"
tsr_server="http://timestamp.identrust.com"
generate_tsr
ts_name="belgium"
tsr_server="http://tsa.belgium.be/connect"
generate_tsr
ts_name="cartaodecidadao"
tsr_server="http://ts.cartaodecidadao.pt/tsa/server"
generate_tsr
ts_name="accv_es"
tsr_server="http://tss.accv.es:8318/tsa"
generate_tsr
ts_name="baltstamp"
tsr_server="http://tsa.baltstamp.lt"
generate_tsr
ts_name="aped_gr"
tsr_server="https://timestamp.aped.gov.gr/qtss"
generate_tsr
ts_name="sep_bg"
tsr_server="http://tsa.sep.bg"
generate_tsr
ts_name="izenpe"
tsr_server="http://tsa.izenpe.com"
generate_tsr
ts_name="certum"
tsr_server="http://time.certum.pl"
generate_tsr
ts_name="symantec"
tsr_server="http://sha256timestamp.ws.symantec.com/sha256/timestamp"
generate_tsr
ts_name="globalsign"
tsr_server="http://rfc3161timestamp.globalsign.com/advanced"
generate_tsr
ts_name="globalsign_2"
tsr_server="http://timestamp.globalsign.com/tsa/r6advanced1"
generate_tsr
ts_name="apple"
tsr_server="http://timestamp.apple.com/ts01"
generate_tsr
ts_name="trustwave"
tsr_server="http://timestamp.ssl.trustwave.com"
generate_tsr
ts_name="freetsa"
tsr_server="https://freetsa.org/tsr"
generate_tsr
ts_name="zeitstempel"
tsr_server="http://zeitstempel.dfn.de"
generate_tsr
ts_name="catcert_cat"
tsr_server="http://psis.catcert.cat/psis/catcert/tsp"
generate_tsr
ts_name="codegic"
tsr_server="http://pki.codegic.com/codegic-service/timestamp"
generate_tsr
#ts_name="mesign"
#tsr_server="https://tsa.mesign.com"
#generate_tsr
ts_name="wotrus"
tsr_server="https://tsa.wotrus.com"
generate_tsr
ts_name="lex_persona"
tsr_server="http://tsa.lex-persona.com/tsa"
generate_tsr
ts_name="cesnet"
tsr_server="https://tsa.cesnet.cz:5817/tsa"
generate_tsr
ts_name="cesnet_2"
tsr_server="https://tsa.cesnet.cz:3162/tsa"
generate_tsr
ts_name="signfiles"
tsr_server="http://ca.signfiles.com/TSAServer.aspx"
generate_tsr
#ts_name="signfiles_2"
#tsr_server="https://ca.signfiles.com/tsa/get.aspx"
#generate_tsr
ts_name="aloahacoin"
tsr_server="http://aloahacoin.chain-provider.com/tsa.aspx"
generate_tsr
ts_name="sinpe_cr"
tsr_server="http://tsa.sinpe.fi.cr/tsaHttp/"
generate_tsr
ts_name="mahidol_th"
tsr_server="https://tsa.mahidol.ac.th/tsa/get.aspx"
generate_tsr
ts_name="cra_ge"
tsr_server="http://tsa.cra.ge/signserver/tsa?workerName=qtsa"
generate_tsr
ts_name="gob_hn"
tsr_server="http://tss.cnbs.gob.hn/TSS/HttpTspServer"
generate_tsr
ts_name="mconnect"
tsr_server="https://time.mconnect.mc"
generate_tsr
ts_name="tugraz_at"
tsr_server="https://tsp.iaik.tugraz.at/tsp/TspRequest"
generate_tsr
#ts_name="safecreative"
#tsr_server="http://tsa.safecreative.org"
#generate_tsr
#ts_name="comodoca"
#tsr_server="http://timestamp.comodoca.com/rfc3161"
#generate_tsr
ts_name="nowina_lu"
tsr_server="http://dss.nowina.lu/pki-factory/tsa/good-tsa"
generate_tsr
#
# other
#
# Digidoc4_Client
#ts_name="sk_ee"
#tsr_server="http://tsa.sk.ee/"
#generate_tsr
# EOF
If you choose one between the Adobe: European Union Trusted Lists, and Adobe Approved Trust List, which is more widely accepted? I'm assuming the EU has a higher level of trust and works everywhere?
Symantec's timestamp server appears to be defunct. See this.
We switched to the Azure Code Signing timestamp server: http://timestamp.acs.microsoft.com
Would it be possible to have a list with links to root certificates of all active CAs used for https://rfc3161.ai.moda/[*] so we could download them?
I've exposed https://rfc3161.ai.moda/servers.json for now, does that work or still not quite?
We switched to the Azure Code Signing timestamp server: http://timestamp.acs.microsoft.com
Thanks, I've added that one for Windows signing on https://rfc3161.ai.moda!
Would it be possible to have a list with links to root certificates of all active CAs used for https://rfc3161.ai.moda/[*] so we could download them?
I've exposed https://rfc3161.ai.moda/servers.json for now, does that work or still not quite?
I mean list of URLs to all CAs root certificates so we can download them and put to trusted list.
I can find one for ssl.com for example: https://www.ssl.com/how-to/install-ssl-com-ca-root-certificates/#ftoc-heading-4
But where can I find CA root certificate for TSA http://timestamp.acs.microsoft.com
The thing is we cannot make proper TSA request without having it's CA root certificate in local trusted list.
When the TSA can be done with any server from the list https://rfc3161.ai.moda/servers.json (thanks, that's quite nice), we need to have all root certificates in one place.
Hello! What can these servers be used for? Are they suitable for productive systems?
I am currently looking for a solution to sign log entries with some kind of trusted timestamp.
@Pique7 You can use them for anything, many folks are using https://rfc3161.ai.moda
in production. We serve a few million requests per month now I think, with higher uptime than the majority of any single RFC3161 server (since we have automatic failovers).
How can i verify the timestamp? I get a response from a random server. But i also would like to verify this response locally. But for that i need CA and intermediate files i think. Could u also expose those/add them to the server list? I assume your backend has them in order to verify the response. Bonus for a example command :)
@chimmmpie I have made a script that extracts the .cer / .crt from a timestamping service
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
# Check that we have the name of the TSA service as a first arg and the URL as a second arg
if [ "$#" -ne 2 ]; then
echo "Illegal number of parameters"
echo "Usage: $0 <TSA_URL> <TSA_NAME>"
exit 1
fi
TSA_URL=$1
TSA_NAME=$2
echo "==> We are trying to get the TSA certificate from the following service : $TSA_NAME ($TSA_URL)"
echo "==> Sending a signature request..."
openssl rand 256 | openssl ts -query -data - -cert -sha256 | curl -s -S --data-binary @- "$TSA_URL" --header "Content-Type: application/timestamp-query" -o - -v > "$TSA_NAME.reply.tsr"
echo "==> Verifying the response..."
openssl ts -reply -text -in "$TSA_NAME.reply.tsr" || (echo "==> Verification failed :" && cat "$TSA_NAME.reply.tsr" && rm "$TSA_NAME.reply.tsr" && exit 1)
echo "==> Extracting the token..."
openssl ts -reply -in "$TSA_NAME.reply.tsr" -token_out -out "$TSA_NAME.token.tk"
echo "==> Extracting the TSA certificate..."
openssl pkcs7 -inform DER -in "$TSA_NAME.token.tk" -print_certs -outform PEM -out "$TSA_NAME.cer"
echo "==> Extracting the TSA certificate as a .crt..."
openssl x509 -inform PEM -in "$TSA_NAME.cer" -out "$TSA_NAME.crt"
rm "$TSA_NAME.reply.tsr" "$TSA_NAME.token.tk"
Call it like ./request_crt.sh http://timestamp.acs.microsoft.com/ microsoft
to get everything in microsoft.crt
I have made a script that extracts the .cer / .crt from a timestamping service
Thanks, that is great!
Would it be possible to make version of the script that downloads all certs for servers provided by https://rfc3161.ai.moda/servers.json?
@chimmmpie I have made a script that extracts the .cer / .crt from a timestamping service
That looks interesting. But it would suggest to me that the cert is already in the response? Or does anyone think that some of the openssl commands will fetch it in the background?
The -cert
part in openssl ts -query -data - -cert -sha256
asks the TSA to return its cert as well
@Pique7 You can use them for anything, many folks are using
https://rfc3161.ai.moda
in production. We serve a few million requests per month now I think, with higher uptime than the majority of any single RFC3161 server (since we have automatic failovers).
Thanks for your reply. Now I have another question:
The TSA certificate of my current test response has a validity of 10 years. I thinks that's a lot. But what can I do when the TSA certificate expires? Sorry if this question is too stupid or off-topic/misplaced.
The signature should still be considered valid (in my opinion), since it was signed within the original lifetime of the CA. It just can’t (or rather shouldn’t) be used for new signatures.
You shouldn’t have to do anything. All of the upstream servers for rfc3161.ai.moda should rollover to using a new certificates long before the current ones expire.
I you want to see the CA that was used in the response for your request, you can use asn1parse. Example:
openssl rand 512 | openssl ts -query -data - -cert -sha512 | curl -s -S --data-binary @- https://rfc3161.ai.moda -o - -v | openssl asn1parse -in /dev/stdin -inform DER -dump
Thanks for tip.
But once again: we are not able to generate a time stamp unless we have CA root certificate in the local "trusted" list.
Would it be possible to provide a list (URLs) of all available timestamping CA root certificates?
@vasekkral Sure. Note, these certificates do change over time.
#!/usr/bin/env bash
# Available cryptographic hash algorithms for timestamp requests
# These algorithms are tried sequentially until a successful response is received
hash_algorithms=(
"sha512" "blake2b512" "blake2s256" "md4" "md5" "md5-sha1" "mdc2" "ripemd"
"ripemd160" "rmd160" "sha1" "sha224" "sha256" "sha3-224" "sha3-256"
"sha3-384" "sha3-512" "sha384" "sha512-224" "sha512-256" "shake128"
"shake256" "sm3" "ssl3-md5" "ssl3-sha1" "whirlpool"
)
# Attempts to obtain a timestamp token from a TSA server using specified parameters
# Returns 0 on success, 1 on failure
try_timestamp_request() {
local url="$1" # TSA server endpoint
local hash_algo="$2" # Cryptographic hash algorithm
local tmp_query="$3" # Path to store the timestamp request
local tmp_reply="$4" # Path to store the server's response
local tmp_token="$5" # Path to store the extracted timestamp token
# Process flow:
# 1. Generate random data as input
# 2. Create a timestamp query using the specified hash algorithm
# 3. Send the query to the TSA server
# 4. Extract the timestamp token from the response
if openssl rand 512 | \
openssl ts -query -data - -cert -"$hash_algo" > "$tmp_query" 2>/dev/null && \
curl -H "Content-Type: application/timestamp-query" \
-H "Accept: application/timestamp-reply" \
-s -S --data-binary @"$tmp_query" "$url" -o "$tmp_reply" && \
openssl ts -reply -in "$tmp_reply" -token_out -out "$tmp_token" 2>/dev/null; then
return 0 # All operations completed successfully
else
return 1 # One or more operations failed
fi
}
# Main processing loop: Retrieve and process TSA server information
curl -s https://rfc3161.ai.moda/servers.json | \
jq -r '.[] | {name: .name, url: .url} | @json' | \
while read -r line; do
# Extract server details from JSON response
name=$(echo "$line" | jq -r '.name') # Server's friendly name
url=$(echo "$line" | jq -r '.url') # Server's API endpoint
# Create filesystem-safe server name by removing special characters
safe_name=$(echo "$name" | tr -c '[:alnum:]' '_' | tr -s '_' | sed 's/^_//;s/_$//')
# Create temporary storage for request/response data
tmp_query=$(mktemp)
tmp_reply=$(mktemp)
tmp_token=$(mktemp)
success=false # Tracks if any attempt succeeded
successful_hash="" # Records which hash algorithm worked
# Try each hash algorithm until successful
for hash_algo in "${hash_algorithms[@]}"; do
echo "Trying $hash_algo for $name..."
if try_timestamp_request "$url" "$hash_algo" "$tmp_query" "$tmp_reply" "$tmp_token"; then
success=true
successful_hash="$hash_algo"
break
fi
done
if [ "$success" = true ]; then
# Extract and save the CA certificate from the successful response
if openssl pkcs7 -inform DER -in "$tmp_token" -print_certs -outform PEM -out "${safe_name}.pem" 2>/dev/null; then
echo "Successfully extracted CA certificate for: $name (using $successful_hash)"
echo "$name,$url,$successful_hash" >> successful_servers.log
else
echo "$url" >> failed_ca_certs.log
echo "Failed to extract CA certificate for: $name"
fi
else
echo "$url" >> failed_ca_certs.log
echo "Failed to get timestamp response from: $name (tried all hash algorithms)"
fi
# Cleanup temporary files to prevent disk space issues
rm -f "$tmp_query" "$tmp_reply" "$tmp_token"
done
This will dump the full certificate chain for all of the CAs. e.g. this is what my folder looks like after running the script:
APED.pem Entrust.pem QuoVadis_China.pem
Adacom.pem FreeTSA.pem QuoVadis_EU.pem
Aloaha.pem GlobalSign.pem SDA_GOV_GE.pem
Apple.pem IdenTrust.pem SEP_Bulgaria.pem
Azure.pem Instituto_dos_Registos_e_do_Notariado_I_P.pem SSL_com.pem
BalTstamp.pem Izenpe.pem Sectigo.pem
Belgium_Federal_Goverment.pem Lex_Persona.pem SwissSign.pem
CNBS.pem Mahidol_University.pem Swiss_Goverment.pem
CatCert.pem MeSign.pem TSA_SINPE.pem
Certum.pem Netlock.pem successful_servers.log
Digicert.pem QuoVadis.pem
@Manouchehri great, thanks a lot, works perfectly. Now we can call our "time stamper" util with your load balancer.
I created a simple time stamp query http(s) client and sent a simple query to the servers mentioned in your list. Here are the simplified results:
Probably some of these URLs need a path (e.g. freetsa.org should be http(s)://freetsa.org/tsr).
http://timestamp.globalsign.com/tsa/r6advanced1: OK
http://timestamp.digicert.com: OK
http://timestamp.acs.microsoft.com: OK
http://time.certum.pl: OK
http://rfc3161timestamp.globalsign.com/advanced: OK
http://zeitstempel.dfn.de: fail
http://tsa.startssl.com/rfc3161: fail
http://tsa.mesign.com: fail
http://timestamp.sectigo.com: fail
http://timestamp.entrust.net/TSS/RFC3161sha2TS: fail
http://timestamp.apple.com/ts01: fail
https://tsp.iaik.tugraz.at/tsp/TspRequest: fail
https://rfc3161.ai.moda/microsoft: fail
https://rfc3161.ai.moda: fail
https://rfc3161.ai.moda/apple: fail
https://rfc3161.ai.moda/any: fail
https://rfc3161.ai.moda/adobe: fail
https://freetsa.org: fail
http://services.globaltrustfinder.com/adss/tsa: fail
https://ca.signfiles.com/tsa/get.aspx: fail
http://rfc3161.ai.moda: fail
http://dse200.ncipher.com/TSS/HttpTspServer: fail
@HeikoSchlittermann Could you please explain how your client works? Those results seem very wrong to me.
The following have stopped working for years:
http://tsa.startssl.com/rfc3161
http://services.globaltrustfinder.com/adss/tsa
http://dse200.ncipher.com/TSS/HttpTspServer
The following, as mentioned, had the URL wrong:
https://freetsa.org it should be: https://freetsa.org/tsr
The rest is working properly.
So something is wrong with thou simple time stamp client.
That would be really great as I am wondering what are the differences too!