Пересборка справочника: выбирать подписанта по действующему ключу (чинит ложный E070004C)

crestor выбирал сертификат подписанта ПСП по имени владельца. Если у владельца
в справочнике несколько сертификатов (перевыпуск ключа — у клиента так бывает),
crestor брал первый по имени и мог попасть на старый с истёкшим сроком закрытого
ключа → E070004C «Ключ ЭП/закрытый ключ шифрования уже истёк», хотя на носителе
свежий действующий ключ.

bj-validata-rebuild-gdbm: при E070004C перебирает leaf-сертификаты с НЕ истёкшим
сроком закрытого ключа (свежие первыми, до 25) и указывает подписанта явно
(-signer -dercer). Правильный (чей закрытый ключ на носителе) даёт Результат: OK,
остальные — ошибку, идём дальше. Проверено на живой флешке клиента: справочник
пересобрался (cf9a5713), signer выбран верный.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
fontvielle
2026-10-21 13:14:24 +03:00
parent 83bf3f5b49
commit ed2d0ce4e5
2 changed files with 44 additions and 16 deletions
+32 -4
View File
@@ -86,10 +86,38 @@ CERTARGS=""; for c in "$WORK"/1leaf_*.der "$WORK"/2ca_*.der; do [ -f "$c" ] && C
CRLARGS=""; for c in "$WORK"/3crl_*.der; do [ -f "$c" ] && CRLARGS="$CRLARGS -dercrl $c"; done
[ -n "$CERTARGS" ] || { echo "{\"ok\":false,\"error\":\"сертификаты не извлечены ($EX)\"}"; exit 1; }
# 2) пересобрать gdbm во временной папке (ключ подписи стора — с носителя)
OUT=$(LD_LIBRARY_PATH="$VDLIB" "$ZPKI" -minimal -tools -crestor \
-uripse "pse://signed//$WORK/local.pse" -uriloc "file://$WORK/local.gdbm" \
$CERTARGS $CRLARGS 2>&1)
# 2) пересобрать gdbm во временной папке. ПСП подписывается ключом с НОСИТЕЛЯ.
# crestor по умолчанию выбирает сертификат подписанта ПО ИМЕНИ владельца. Если у
# владельца в справочнике несколько сертификатов (перевыпуск ключа — у клиента так
# бывает), crestor берёт первый по имени и может попасть на СТАРЫЙ с истёкшим сроком
# закрытого ключа → E070004C, хотя на носителе свежий действующий ключ. Тогда
# перебираем сертификаты с НЕ истёкшим сроком закрытого ключа (свежие — первыми) и
# указываем подписанта явно (-signer). Правильный (чей закрытый ключ на носителе)
# даёт «Результат: OK», остальные — ошибку, и мы идём дальше.
run_crestor() { # $1 — DER-файл сертификата подписанта (необязательно)
local sgn=""; [ -n "${1:-}" ] && sgn="-signer -dercer $1"
LD_LIBRARY_PATH="$VDLIB" "$ZPKI" -minimal -tools -crestor \
-uripse "pse://signed//$WORK/local.pse" -uriloc "file://$WORK/local.gdbm" \
$sgn $CERTARGS $CRLARGS 2>&1
}
OUT=$(run_crestor "")
if echo "$OUT" | grep -qiE 'E070004C|срок действия ключа ЭП'; then
NOW=$(date -u +%s)
CANDS=$(for c in "$WORK"/1leaf_*.der; do
[ -f "$c" ] || continue
pk=$(openssl x509 -inform DER -in "$c" -noout -text 2>/dev/null | awk '/Private Key Usage Period/{f=1} f&&/Not After/{sub(/.*Not After: /,"");print;exit}')
[ -n "$pk" ] || continue
ex=$(date -u -d "$pk" +%s 2>/dev/null) || continue
[ "$ex" -gt "$NOW" ] || continue
nb=$(openssl x509 -inform DER -in "$c" -noout -startdate 2>/dev/null | sed 's/notBefore=//')
nbs=$(date -u -d "$nb" +%s 2>/dev/null || echo 0)
printf '%s %s\n' "$nbs" "$c"
done | sort -rn | awk '{print $2}' | head -25)
for c in $CANDS; do
OUT=$(run_crestor "$c")
if echo "$OUT" | grep -qi 'Результат: OK'; then echo "signer: $(basename "$c")" >&2; break; fi
done
fi
if ! echo "$OUT" | grep -qi 'Результат: OK'; then
ERR=$(echo "$OUT" | grep -iE 'ошибк|Результат' | head -1 | tr -d '"')
echo "{\"ok\":false,\"error\":\"crestor: $ERR\"}"; exit 1