Попытка подписать 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.