iTextSharp 5.5.6:使用 SwissSign USB 令牌的签名无效
iTextSharp 5.5.6: Signature invalid with SwissSign USB token
我阅读了 Bruno Lowagie 的白皮书:PDF 文档的数字签名。
我按照示例进行操作,并且能够使用 MSCAPI 使用我的 SwissSign USB 令牌对 PDF 进行签名。这行代码可以解决问题:
MakeSignature.SignDetached(外观、pks、链、crlList、ocspClient、tsaClient、估计大小、子过滤器);
我还通过 SwissSign TSA URL 的 TSA 客户端:tsa(dot)swisssign(dot)net
当我在 Acrobat Reader DC 2015 中打开签名的 PDF 时,出现错误:
签名无效。
此签名中包含的格式或信息有误
签名者身份尚未验证
签名时间以签名者电脑上的时钟为准。
使用 SwissSign 工具签署 PDF 时一切正常:签名有效。
我已将 PDF 放在这里:
invalid PDF - signed with iTextSharp 5.5.6
valid PDF - signed with SwissSign tool
我尝试了不同的哈希算法组合,但没有成功。我错过了什么?
感谢任何帮助。
此致,
菲尔
完整代码如下:
private void _sign_Click(object sender, RoutedEventArgs e)
{
X509Store x509Store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
x509Store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = x509Store.Certificates;
IList<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
X509Certificate2 pk = null;
if (certificates.Count > 0)
{
for (int i = 0; i < certificates.Count; i++)
{
if (certificates[i].FriendlyName == "Philipp Egger (Qualified Signature) .....") // Phil Egger Signature Certificate
{
pk = certificates[i];
break;
}
}
X509Chain x509chain = new X509Chain();
x509chain.Build(pk);
foreach (X509ChainElement x509ChainElement in x509chain.ChainElements)
{
chain.Add(Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
}
}
x509Store.Close();
if (pk != null)
{
#region connect usb token
///////////////////
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)pk.PrivateKey;
CspParameters cspp = new CspParameters();
cspp.KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName;
cspp.ProviderName = rsa.CspKeyContainerInfo.ProviderName;
cspp.ProviderType = rsa.CspKeyContainerInfo.ProviderType;
cspp.Flags = CspProviderFlags.NoPrompt;
System.Security.SecureString pwstr = new System.Security.SecureString();
pwstr.AppendChar('x');
pwstr.AppendChar('x');
pwstr.AppendChar('x');
cspp.KeyPassword = pwstr;
RSACryptoServiceProvider rsa2 = new RSACryptoServiceProvider(cspp);
rsa2.PersistKeyInCsp = true;
// PIN is cached from now on and popup won't appear
///////////////////////
#endregion
IOcspClient ocspClient = new OcspClientBouncyCastle();
ITSAClient tsaClient = null;
for (int i = 0; i < chain.Count; i++)
{
Org.BouncyCastle.X509.X509Certificate cert = chain[i];
String tsaUrl = CertificateUtil.GetTSAURL(cert);
if (tsaUrl != null)
{
tsaClient = new TSAClientBouncyCastle(tsaUrl);
break;
}
}
if (tsaClient == null)
{
tsaClient = new TSAClientBouncyCastle("http://tsa.swisssign.net");
//tsaClient = new MyTSAClientBouncyCastle("http://tsa.swisssign.net"); // set user-agent
}
IList<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(new CrlClientOnline(chain));
string pathSource = @"C:\Temp\test_to_sign.pdf";
string pathTarget3 = @"C:\Temp\test_to_sign-signed3.pdf";
// this.SignNew(pathSource, pathTarget1, chain, pk, DigestAlgorithms.SHA1, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget2, chain, pk, DigestAlgorithms.SHA1, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
this.SignNew(pathSource, pathTarget3, chain, pk, DigestAlgorithms.SHA256, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget4, chain, pk, DigestAlgorithms.SHA256, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget5, chain, pk, DigestAlgorithms.SHA384, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget6, chain, pk, DigestAlgorithms.SHA384, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget7, chain, pk, DigestAlgorithms.SHA512, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget8, chain, pk, DigestAlgorithms.SHA512, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
this._txt.Text = "Signed successfully.";
}
else
{
this._txt.Text = "Certificate not found.";
}
}
public void SignNew(String src, String dest,
ICollection<Org.BouncyCastle.X509.X509Certificate> chain, X509Certificate2 pk,
String digestAlgorithm, CryptoStandard subfilter,
String reason, String location,
ICollection<ICrlClient> crlList,
IOcspClient ocspClient,
ITSAClient tsaClient,
int estimatedSize)
{
// Creating the reader and the stamper
PdfReader reader = null;
PdfStamper stamper = null;
FileStream os = null;
try
{
reader = new PdfReader(src);
os = new FileStream(dest, FileMode.Create);
stamper = PdfStamper.CreateSignature(reader, os, '[=10=]');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(36, 748, 144, 780), 1, "Signature1");
// Creating the signature
IExternalSignature pks = new X509Certificate2Signature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
catch (Exception e)
{
this._txt.Text = e.Message;
}
finally
{
if (reader != null)
reader.Close();
if (stamper != null)
stamper.Close();
if (os != null)
os.Close();
}
}
问题在于,显然是 SwissSign CSP(加密服务提供商;在 Windows 系统存储和硬件设备之间提供桥梁的层)在使用 MSCAPI 时选择了错误的私钥。
似乎没有解决方法来在 MSCAPI 中选择正确的私钥。
因此,我决定使用 PKCS11 和 NCryptroki 库。这里的代码:
using Cryptware.NCryptoki;
using iTextSharp.text;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace _07SignWithPKCS11DLL
{
class Program
{
static void Main(string[] args)
{
LoggerFactory.GetInstance().SetLogger(new SysoLogger());
// Creates a Cryptoki object related to the specific PKCS#11 native library
Cryptoki cryptoki = new Cryptoki("cvP11.dll");
cryptoki.Initialize();
// Reads the set of slots containing a token
SlotList slots = cryptoki.Slots;
if (slots.Count == 0)
{
Console.WriteLine("No slot available");
Console.ReadLine();
return;
}
// Gets the first slot available
Slot slot = slots[0];
if (!slot.IsTokenPresent)
{
Console.WriteLine("No token inserted in the slot: " + slots[0].Info.Description);
Console.ReadLine();
return;
}
// Gets the first token available
Token token = slot.Token;
// Opens a read serial session
Session session = token.OpenSession(Session.CKF_SERIAL_SESSION, null, null);
// Executes the login passing the user PIN
int nRes = session.Login(Session.CKU_USER, "secret");
if (nRes != 0)
{
Console.WriteLine("Wrong PIN");
return;
}
CSignWithPKCS11SC.Smartcardsign(session, "PhilippEggerQualifiedSignature", "SwissSign_nonRep ");
/*
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509));
CryptokiCollection objects = session.Objects.Find(template, 10);
// If the private keys is found continue
if (objects.Count > 0)
{
foreach (Object obj in objects)
{
Cryptware.NCryptoki.X509Certificate cert = (Cryptware.NCryptoki.X509Certificate)obj;
Console.WriteLine(cert.Label + " - " + cert.ID);
}
}
*/
// Logouts and closes the session
session.Logout();
session.Close();
cryptoki.Finalize(IntPtr.Zero);
Console.ReadLine();
}
}
class CryptokiPrivateKeySignature : IExternalSignature
{
private readonly Cryptware.NCryptoki.Session session;
RSAPrivateKey privateKey;
public CryptokiPrivateKeySignature(Session session, String alias)
{
this.session = session;
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
// "SwissSign_nonRep "
// "SwissSign_digSig "
template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias));
/*
CryptokiCollection objects = session.Objects.Find(template, 10);
if (objects.Count > 0)
{
foreach (Object obj in objects)
{
RSAPrivateKey cert = (RSAPrivateKey)obj;
Console.WriteLine(cert.Label);
}
}
*/
privateKey = (RSAPrivateKey)session.Objects.Find(template);
}
public String GetHashAlgorithm()
{
return "SHA1";
}
public String GetEncryptionAlgorithm()
{
return "RSA";
}
public byte[] Sign(byte[] message)
{
session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey);
return session.Sign(message);
}
}
class CSignWithPKCS11SC
{
public const String SRC = @"C:\Temp\test_to_sign.pdf";
public const String DEST = @"C:\Temp\test_to_sign-pkcs11.pdf";
//public const String DLL = "c:/windows/system32/beidpkcs11.dll";
public const String DLL = "c:/windows/system32/cvP11.dll";
public void Sign(String src, String dest, ICollection<Org.BouncyCastle.X509.X509Certificate> chain, Session session, String alias,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
// Creating the reader and the stamper
PdfReader reader = null;
PdfStamper stamper = null;
FileStream os = null;
try
{
reader = new PdfReader(src);
os = new FileStream(dest, FileMode.Create);
stamper = PdfStamper.CreateSignature(reader, os, '[=10=]');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
IExternalSignature pks = new CryptokiPrivateKeySignature(session, alias);
MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
finally
{
if (reader != null)
reader.Close();
if (stamper != null)
stamper.Close();
if (os != null)
os.Close();
}
}
public static void Smartcardsign(Session session, String alias, String aliasPrivateKey)
{
// Searchs for an RSA certificate object
// Sets the template with its attributes
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias));
Cryptware.NCryptoki.X509Certificate nCert = (Cryptware.NCryptoki.X509Certificate)session.Objects.Find(template);
if (nCert != null)
{
X509Certificate2 cert = Utils.ConvertCertificate(nCert);
ICollection<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
X509Chain x509chain = new X509Chain();
x509chain.Build(cert);
foreach (X509ChainElement x509ChainElement in x509chain.ChainElements)
{
chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
}
IOcspClient ocspClient = new OcspClientBouncyCastle();
List<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(new CrlClientOnline(chain));
TSAClientBouncyCastle tsaClient = new TSAClientBouncyCastle("http://tsa.swisssign.net");
CSignWithPKCS11SC app = new CSignWithPKCS11SC();
Console.WriteLine("Logged in? " + session.IsLoggedIn);
app.Sign(SRC, DEST, chain, session, aliasPrivateKey, DigestAlgorithms.SHA256, CryptoStandard.CMS,
"Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
}
else
{
Console.WriteLine("Certificate not found: " + alias);
}
}
}
}
我阅读了 Bruno Lowagie 的白皮书:PDF 文档的数字签名。
我按照示例进行操作,并且能够使用 MSCAPI 使用我的 SwissSign USB 令牌对 PDF 进行签名。这行代码可以解决问题:
MakeSignature.SignDetached(外观、pks、链、crlList、ocspClient、tsaClient、估计大小、子过滤器);
我还通过 SwissSign TSA URL 的 TSA 客户端:tsa(dot)swisssign(dot)net
当我在 Acrobat Reader DC 2015 中打开签名的 PDF 时,出现错误:
签名无效。
此签名中包含的格式或信息有误
签名者身份尚未验证
签名时间以签名者电脑上的时钟为准。
使用 SwissSign 工具签署 PDF 时一切正常:签名有效。
我已将 PDF 放在这里:
invalid PDF - signed with iTextSharp 5.5.6
valid PDF - signed with SwissSign tool
我尝试了不同的哈希算法组合,但没有成功。我错过了什么?
感谢任何帮助。
此致,
菲尔
完整代码如下:
private void _sign_Click(object sender, RoutedEventArgs e)
{
X509Store x509Store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
x509Store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = x509Store.Certificates;
IList<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
X509Certificate2 pk = null;
if (certificates.Count > 0)
{
for (int i = 0; i < certificates.Count; i++)
{
if (certificates[i].FriendlyName == "Philipp Egger (Qualified Signature) .....") // Phil Egger Signature Certificate
{
pk = certificates[i];
break;
}
}
X509Chain x509chain = new X509Chain();
x509chain.Build(pk);
foreach (X509ChainElement x509ChainElement in x509chain.ChainElements)
{
chain.Add(Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
}
}
x509Store.Close();
if (pk != null)
{
#region connect usb token
///////////////////
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)pk.PrivateKey;
CspParameters cspp = new CspParameters();
cspp.KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName;
cspp.ProviderName = rsa.CspKeyContainerInfo.ProviderName;
cspp.ProviderType = rsa.CspKeyContainerInfo.ProviderType;
cspp.Flags = CspProviderFlags.NoPrompt;
System.Security.SecureString pwstr = new System.Security.SecureString();
pwstr.AppendChar('x');
pwstr.AppendChar('x');
pwstr.AppendChar('x');
cspp.KeyPassword = pwstr;
RSACryptoServiceProvider rsa2 = new RSACryptoServiceProvider(cspp);
rsa2.PersistKeyInCsp = true;
// PIN is cached from now on and popup won't appear
///////////////////////
#endregion
IOcspClient ocspClient = new OcspClientBouncyCastle();
ITSAClient tsaClient = null;
for (int i = 0; i < chain.Count; i++)
{
Org.BouncyCastle.X509.X509Certificate cert = chain[i];
String tsaUrl = CertificateUtil.GetTSAURL(cert);
if (tsaUrl != null)
{
tsaClient = new TSAClientBouncyCastle(tsaUrl);
break;
}
}
if (tsaClient == null)
{
tsaClient = new TSAClientBouncyCastle("http://tsa.swisssign.net");
//tsaClient = new MyTSAClientBouncyCastle("http://tsa.swisssign.net"); // set user-agent
}
IList<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(new CrlClientOnline(chain));
string pathSource = @"C:\Temp\test_to_sign.pdf";
string pathTarget3 = @"C:\Temp\test_to_sign-signed3.pdf";
// this.SignNew(pathSource, pathTarget1, chain, pk, DigestAlgorithms.SHA1, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget2, chain, pk, DigestAlgorithms.SHA1, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
this.SignNew(pathSource, pathTarget3, chain, pk, DigestAlgorithms.SHA256, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget4, chain, pk, DigestAlgorithms.SHA256, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget5, chain, pk, DigestAlgorithms.SHA384, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget6, chain, pk, DigestAlgorithms.SHA384, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget7, chain, pk, DigestAlgorithms.SHA512, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
// this.SignNew(pathSource, pathTarget8, chain, pk, DigestAlgorithms.SHA512, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
this._txt.Text = "Signed successfully.";
}
else
{
this._txt.Text = "Certificate not found.";
}
}
public void SignNew(String src, String dest,
ICollection<Org.BouncyCastle.X509.X509Certificate> chain, X509Certificate2 pk,
String digestAlgorithm, CryptoStandard subfilter,
String reason, String location,
ICollection<ICrlClient> crlList,
IOcspClient ocspClient,
ITSAClient tsaClient,
int estimatedSize)
{
// Creating the reader and the stamper
PdfReader reader = null;
PdfStamper stamper = null;
FileStream os = null;
try
{
reader = new PdfReader(src);
os = new FileStream(dest, FileMode.Create);
stamper = PdfStamper.CreateSignature(reader, os, '[=10=]');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(36, 748, 144, 780), 1, "Signature1");
// Creating the signature
IExternalSignature pks = new X509Certificate2Signature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
catch (Exception e)
{
this._txt.Text = e.Message;
}
finally
{
if (reader != null)
reader.Close();
if (stamper != null)
stamper.Close();
if (os != null)
os.Close();
}
}
问题在于,显然是 SwissSign CSP(加密服务提供商;在 Windows 系统存储和硬件设备之间提供桥梁的层)在使用 MSCAPI 时选择了错误的私钥。
似乎没有解决方法来在 MSCAPI 中选择正确的私钥。
因此,我决定使用 PKCS11 和 NCryptroki 库。这里的代码:
using Cryptware.NCryptoki;
using iTextSharp.text;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace _07SignWithPKCS11DLL
{
class Program
{
static void Main(string[] args)
{
LoggerFactory.GetInstance().SetLogger(new SysoLogger());
// Creates a Cryptoki object related to the specific PKCS#11 native library
Cryptoki cryptoki = new Cryptoki("cvP11.dll");
cryptoki.Initialize();
// Reads the set of slots containing a token
SlotList slots = cryptoki.Slots;
if (slots.Count == 0)
{
Console.WriteLine("No slot available");
Console.ReadLine();
return;
}
// Gets the first slot available
Slot slot = slots[0];
if (!slot.IsTokenPresent)
{
Console.WriteLine("No token inserted in the slot: " + slots[0].Info.Description);
Console.ReadLine();
return;
}
// Gets the first token available
Token token = slot.Token;
// Opens a read serial session
Session session = token.OpenSession(Session.CKF_SERIAL_SESSION, null, null);
// Executes the login passing the user PIN
int nRes = session.Login(Session.CKU_USER, "secret");
if (nRes != 0)
{
Console.WriteLine("Wrong PIN");
return;
}
CSignWithPKCS11SC.Smartcardsign(session, "PhilippEggerQualifiedSignature", "SwissSign_nonRep ");
/*
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509));
CryptokiCollection objects = session.Objects.Find(template, 10);
// If the private keys is found continue
if (objects.Count > 0)
{
foreach (Object obj in objects)
{
Cryptware.NCryptoki.X509Certificate cert = (Cryptware.NCryptoki.X509Certificate)obj;
Console.WriteLine(cert.Label + " - " + cert.ID);
}
}
*/
// Logouts and closes the session
session.Logout();
session.Close();
cryptoki.Finalize(IntPtr.Zero);
Console.ReadLine();
}
}
class CryptokiPrivateKeySignature : IExternalSignature
{
private readonly Cryptware.NCryptoki.Session session;
RSAPrivateKey privateKey;
public CryptokiPrivateKeySignature(Session session, String alias)
{
this.session = session;
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
// "SwissSign_nonRep "
// "SwissSign_digSig "
template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias));
/*
CryptokiCollection objects = session.Objects.Find(template, 10);
if (objects.Count > 0)
{
foreach (Object obj in objects)
{
RSAPrivateKey cert = (RSAPrivateKey)obj;
Console.WriteLine(cert.Label);
}
}
*/
privateKey = (RSAPrivateKey)session.Objects.Find(template);
}
public String GetHashAlgorithm()
{
return "SHA1";
}
public String GetEncryptionAlgorithm()
{
return "RSA";
}
public byte[] Sign(byte[] message)
{
session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey);
return session.Sign(message);
}
}
class CSignWithPKCS11SC
{
public const String SRC = @"C:\Temp\test_to_sign.pdf";
public const String DEST = @"C:\Temp\test_to_sign-pkcs11.pdf";
//public const String DLL = "c:/windows/system32/beidpkcs11.dll";
public const String DLL = "c:/windows/system32/cvP11.dll";
public void Sign(String src, String dest, ICollection<Org.BouncyCastle.X509.X509Certificate> chain, Session session, String alias,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
// Creating the reader and the stamper
PdfReader reader = null;
PdfStamper stamper = null;
FileStream os = null;
try
{
reader = new PdfReader(src);
os = new FileStream(dest, FileMode.Create);
stamper = PdfStamper.CreateSignature(reader, os, '[=10=]');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
IExternalSignature pks = new CryptokiPrivateKeySignature(session, alias);
MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
finally
{
if (reader != null)
reader.Close();
if (stamper != null)
stamper.Close();
if (os != null)
os.Close();
}
}
public static void Smartcardsign(Session session, String alias, String aliasPrivateKey)
{
// Searchs for an RSA certificate object
// Sets the template with its attributes
CryptokiCollection template = new CryptokiCollection();
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509));
template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias));
Cryptware.NCryptoki.X509Certificate nCert = (Cryptware.NCryptoki.X509Certificate)session.Objects.Find(template);
if (nCert != null)
{
X509Certificate2 cert = Utils.ConvertCertificate(nCert);
ICollection<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
X509Chain x509chain = new X509Chain();
x509chain.Build(cert);
foreach (X509ChainElement x509ChainElement in x509chain.ChainElements)
{
chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
}
IOcspClient ocspClient = new OcspClientBouncyCastle();
List<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(new CrlClientOnline(chain));
TSAClientBouncyCastle tsaClient = new TSAClientBouncyCastle("http://tsa.swisssign.net");
CSignWithPKCS11SC app = new CSignWithPKCS11SC();
Console.WriteLine("Logged in? " + session.IsLoggedIn);
app.Sign(SRC, DEST, chain, session, aliasPrivateKey, DigestAlgorithms.SHA256, CryptoStandard.CMS,
"Test", "Rheinau", crlList, ocspClient, tsaClient, 0);
}
else
{
Console.WriteLine("Certificate not found: " + alias);
}
}
}
}