...
Полученный примитив можно использовать везде, где требуется объект с интерфейсом DigestCalculator. В своем приложении вы можете использовать готовые реализованные примитивы из нашего SDK и дополнять их.
Пример использования примитива для реализации множественной подписи:
Code Block | ||||
---|---|---|---|---|
| ||||
package ru.rutoken.samples.pkcs11.bouncycastle;
import com.sun.jna.NativeLong;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.cmp.PKIStatus;
import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
import org.bouncycastle.asn1.tsp.TimeStampResp;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.tsp.TSPException;
import org.bouncycastle.tsp.TimeStampRequest;
import org.bouncycastle.tsp.TimeStampRequestGenerator;
import org.bouncycastle.tsp.TimeStampResponse;
import ru.rutoken.pkcs11jna.CK_ATTRIBUTE;
import ru.rutoken.pkcs11jna.Pkcs11;
import ru.rutoken.pkcs11jna.Pkcs11Constants;
import ru.rutoken.samples.Constants;
import ru.rutoken.samples.pkcs11.RtPkcs11Library;
import ru.rutoken.samples.pkcs11.Util;
import ru.rutoken.samples.pkcs11.bouncycastle.CmsSignVerifyAttachedGOSTR3410_2012_256;
import ru.rutoken.samples.pkcs11.bouncycastle.cmsoperations.GostCmsOperations;
import ru.rutoken.samples.pkcs11.bouncycastle.bcprimitives.GostContentSigner;
import ru.rutoken.samples.pkcs11.bouncycastle.pkcs11operations.Pkcs11GostSigner;
import ru.rutoken.samples.pkcs11.bouncycastle.pkcs11operations.Pkcs11Operations;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.*;
public class CmsAddSigner {
public static void main(String[] args) {
try {
Security.addProvider(new BouncyCastleProvider());
// загружаем имеющийся файл с CMS
CMSSignedData cms = Util.readCmsFromFile("pkcs11/cms.pem");
Util.printString("Original CMS signature in PEM is:", Util.cmsToPem(cms.getEncoded()));
// добавляем подпись в существующую CMS -- получаем новый CMS
cms = addSignerToCms(cms);
Util.printString("CMS with added signature in PEM is:", Util.cmsToPem(cms.getEncoded()));
System.out.println("Sample has been completed successfully.");
} catch (Exception e) {
System.out.println("Sample has failed:");
e.printStackTrace();
}
}
// шаблон сертификата на токене нового подписанта
private static final CK_ATTRIBUTE[] certificateTemplate3410_2012_256;
static {
certificateTemplate3410_2012_256 = (CK_ATTRIBUTE[]) (new CK_ATTRIBUTE()).toArray(3);
certificateTemplate3410_2012_256[0].setAttr(new NativeLong(
Pkcs11Constants.CKA_CLASS), new NativeLong(Pkcs11Constants.CKO_CERTIFICATE)); // Class - certificate
certificateTemplate3410_2012_256[1].setAttr(new NativeLong(
Pkcs11Constants.CKA_CERTIFICATE_TYPE), new NativeLong(Pkcs11Constants.CKC_X_509)); // Certificate type - X.509
certificateTemplate3410_2012_256[2].setAttr(new NativeLong(
Pkcs11Constants.CKA_CERTIFICATE_CATEGORY), new NativeLong(Constants.CK_CERTIFICATE_CATEGORY_TOKEN_USER)); // Certificate category - token user
}
private static CMSSignedData addSignerToCms(CMSSignedData cms)
throws CMSException, Exception {
CMSSignedData newCms = null;
// получаем интерфейс PKCS#11 библиотеки
Pkcs11 pkcs11 = RtPkcs11Library.getPkcs11Interface();
NativeLong session = new NativeLong(Pkcs11Constants.CK_INVALID_HANDLE);
try {
// Инициализируем библиотеку и авторизовываемся на первом токене
Pkcs11Operations.initializePkcs11AndLoginToFirstToken(pkcs11, session);
System.out.println("Finding signer certificate");
// получаем тело сертификата
byte[] signerCertificateValue = Pkcs11Operations.getFirstCertificateValue(pkcs11, session, certificateTemplate3410_2012_256);
Util.printString("Certificate value in PEM:", Util.certificateToPem(signerCertificateValue));
// получаем идентификатор закрытого ключа
NativeLong signerPrivateKey = Pkcs11Operations.getPrivateKeyByCertificateValue(pkcs11, session, signerCertificateValue);
// оборачиваем тело сертификата в интерфейс Bouncy Castle
System.out.println("Creating attached CMS signature via Bouncy Castle");
X509CertificateHolder certificate = new X509CertificateHolder(signerCertificateValue);
// получаем данные для подписи
CMSTypedData signedContent = cms.getSignedContent();
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// заново подписываем эти данные
gen.addCertificate(certificate);
GostContentSigner gostContentSigner = new GostContentSigner(Pkcs11GostSigner.SignAlgorithm.GOSTR3410_2012_256, session.longValue(), signerPrivateKey.longValue());
gen.addSignerInfoGenerator(new SignerInfoGeneratorBuilder(gostContentSigner.getDigestCalculatorProvider()).build(gostContentSigner, certificate));
CMSSignedData newCms = gen.generate(signedContent, false);
} finally {
Pkcs11Operations.logoutAndFinalizePkcs11Library(pkcs11, session);
}
if (newCms == null) {
return null;
}
// получаем структуру, хранящую информацию о новой подписи
Collection<SignerInformation> newSigners = newCms.getSignerInfos().getSigners();
// объединяем SignerInformation
if (newSigners != null) {
Collection<SignerInformation> signerInfos = cms.getSignerInfos().getSigners();
signerInfos.addAll(newSigners);
cms = CMSSignedData.replaceSigners(cms, new SignerInformationStore(signerInfos));
} else {
throw new CMSException("Can't merge CMS signatures");
}
// получаем структуру, хранящую информацию об сертификате нового подписана
Collection<X509CertificateHolder> newCertificates = newCms.getCertificates().getMatches(null);
// объединяем Certificates
if (newCertificate != null) {
Collection<X509CertificateHolder> certificates = cms.getCertificates().getMatches(null);
certificates.addAll(newCertificates);
cms = CMSSignedData.replaceCertificatesAndCRLs(cms, new CollectionStore(certificates), null, null);
} else {
throw new CMSException("Can't merge CMS certificates");
}
return cms;
}
}
|