Попытка подписать PDF с помощью смарт-карты

Я пытаюсь подписать PDF с помощью смарт-карты. Я использую следующий код:

public class SC {
    public static final String SRC = "src/test.pdf";
    public static final String DEST = "src/test_smartCard.pdf";

    public void sign(String src, String dest,
            Certificate[] chain, PrivateKey pk,
            String digestAlgorithm, String provider, CryptoStandard subfilter,
            String reason, String location,
            Collection<CrlClient> crlList,
            OcspClient ocspClient,
            TSAClient tsaClient,
            int estimatedSize)
                    throws GeneralSecurityException, IOException, DocumentException {
        // Creating the reader and the stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        // Creating the appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason(reason);
        appearance.setLocation(location);
        appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
        // Creating the signature
        ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
    }

    public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {
        LoggerFactory.getInstance().setLogger(new SysoLogger());

        BouncyCastleProvider providerBC = new BouncyCastleProvider();
        Security.addProvider(providerBC);
        SunMSCAPI providerMSCAPI = new SunMSCAPI();
        Security.addProvider(providerMSCAPI);
        KeyStore ks = KeyStore.getInstance("Windows-MY");
        ks.load(null, null);
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey)ks.getKey(alias, null);
        Certificate[] chain = ks.getCertificateChain(alias);
        //OcspClient ocspClient = new OcspClientBouncyCastle();
        TSAClient tsaClient = null;

        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = (X509Certificate)chain[i];
            String tsaUrl = CertificateUtil.getTSAURL(cert);
            if (tsaUrl != null) {
                tsaClient = new TSAClientBouncyCastle(tsaUrl);
                break;
            }
        }

        List<CrlClient> crlList = new ArrayList<CrlClient>();
        crlList.add(new CrlClientOnline(chain));
        SC app = new SC();
        app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerMSCAPI.getName(), CryptoStandard.CMS, "Test", "London",
                null, null, tsaClient, 0);
    }
}

Я немного запутался с этим внешним процессом подписания. У меня установлено устройство чтения карт, вставлена ​​моя карта, поскольку я вижу, что я использую хранилище ключей Windows-MY... поэтому я могу вызывать сертификаты на карте из этого хранилища ключей, пока карта вставлена. Когда я проверяю сертификаты через Internet Explorer, я вижу свои сертификаты, которые я получил бесплатно из Интернета, и те, которые есть на карте. Я не могу экспортировать их со смарт-карты с закрытым ключом, я знаю, что в этом вся суть смарт-карты, поэтому этот процесс будет выполняться извне.

Моя проблема заключается в том, что с кодом, который я написал, я получаю документ, подписанный сертификатом, который я уже сделал, а не сертификатами с карты, как мне подписать его сертификатом с карты, еще одна вещь заключается в том, что У меня никогда не спрашивают PIN-код моей смарт-карты.

Кто-нибудь может мне помочь, я очень стараюсь заняться этой цифровой подписью, я знаю, что следующая вещь делает это с PKCS11 и DLL-файл, но я еще не там. Спасибо

добавлено:

Спасибо за ответ, Роберт. Ты был прав. Я перечислил псевдонимы в хранилище ключей WINDOWS-MY и фактически подписал документ первым псевдонимом, который был указан в списке, и это была моя пара сертификат / ключ без использования смарт-карты. Очевидно, что это не то, что я хочу сделать, как бы я подписал его другим сертификатом / ключом, в моем случае - тем, который принадлежит смарт-карте. еще раз спасибо

1 ответ

Решение

Сертификат / ключ для подписи PDF выбирается по псевдониму.

В вашем коде вы используете первый доступный псевдоним:

String alias = (String)ks.aliases().nextElement();

Похоже, этот псевдоним принадлежит паре сертификат / ключ не для смарт-карты. Вы должны перечислить список доступных псевдонимов (и назначенные сертификаты) и посмотреть, принадлежит ли он к вашему сертификату смарт-карты. Если смарт-карта не отображается в этом списке, вам необходимо получить доступ к своей смарт-карте через PKCS#11. Обратите внимание, что PKCS # 11 часто 32-битные - в этом случае вы также должны использовать 32-битную JRE.

Другие вопросы по тегам