openssl and pure bash way
Even if Stéphane Chazelas's answer, work fine and is efficient, I would like to post this bash script who will give near same result, but don't use awk
:
#!/bin/bash
exec {sslout}<> <(:)
cnt=1
while read -u $certs line; do
[ "$line" ] && case $line in
*BEGIN*)
exec {ssl}> >(openssl x509 -noout -subject >&${sslout})
echo $line 1>&$ssl
;;
*END*)
echo $line 1>&$ssl
exec {ssl}>&-
read -u $sslout subject
printf "%03d %s\n" $((cnt++)) "${subject#subject=}"
;;
*)
echo $line 1>&$ssl
;;
esac;
done {certs}< /etc/ssl/certs/ca-certificates.crt
exec {certs}>&- {sslout}>&-
One step further
Searching for certs in all dirs mentionned by SHW's answer, sorting by hashes and count
#!/bin/bash
exec {sslout}<> <(:)
cnt=0
hashed=()
while read -u $certs line; do
[ "$line" ] && case $line in
*BEGIN*)
exec {ssl}> >(openssl x509 -noout -hash -subject >&${sslout})
echo $line 1>&$ssl
;;
*END*)
echo $line 1>&$ssl
exec {ssl}>&-
read -u $sslout hash
read -u $sslout subject
((cnt++))
hashed[16#$hash]+="${subject#subject=}"$'\t'
;;
*)
echo $line 1>&$ssl
;;
esac
done {certs}< <(find /etc/ssl/certs /usr/{local/,}share/ca-certificates \
-type f -exec cat {} +)
exec {certs}>&- {sslout}>&-
echo "$cnt certs read, ${#hashed[@]} different hashes."
for i in ${!hashed[@]};do
IFS=$'\t' read -a subj <<<"${hashed[i]}"
printf "%8x %s\n" $i "$subj"
((${#subj}>1)) && printf " %s\n" "${subj[@]:1}"
done
may output something like:
256 certs read, 128 different hashes.
3179a64 C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden EV Root CA
C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden EV Root CA
62cdee6 OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
64e0aa9 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 G3
C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 G3
...