Skip to content

Instantly share code, notes, and snippets.

@davidvesely
Created November 13, 2015 11:58
Show Gist options
  • Select an option

  • Save davidvesely/fed58351ee1b98c37cbc to your computer and use it in GitHub Desktop.

Select an option

Save davidvesely/fed58351ee1b98c37cbc to your computer and use it in GitHub Desktop.
Подписване на заяка към сървис без ръчно въвеждане на ПИН код в SmartCard устройство със сертификат
using Net.Pkcs11Interop.Common;
using Net.Pkcs11Interop.HighLevelAPI;
using Net.Pkcs11Interop.PDF;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace NssiReport.Test
{
public static class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press key to continue with the request to NSSI");
Console.ReadKey();
X509Certificate2 cert = null;
var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindBySerialNumber, Settings.Default.SerialNumber, false);
cert = certificates[0];
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;
CspParameters cspp = new CspParameters();
cspp.KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName;
cspp.ProviderName = rsa.CspKeyContainerInfo.ProviderName;
// cspp.ProviderName = "Microsoft Smart Card Key Storage Provider";
cspp.ProviderType = rsa.CspKeyContainerInfo.ProviderType;
//cspp.Flags = CspProviderFlags.NoPrompt;
cspp.KeyPassword = CreatePasswordKey(Settings.Default.PinCode);
RSACryptoServiceProvider rsa2 = new RSACryptoServiceProvider(cspp);
rsa.PersistKeyInCsp = true;
short report = Settings.Default.ReportType;
string egn = Settings.Default.EGN;
//string res = GetReport(egn, report, cert);
try
{
NssiDataService.ServiceSoapClient client = new NssiDataService.ServiceSoapClient();
client.ClientCredentials.ClientCertificate.Certificate = cert;
var result = client.GetData("Easycredit1", report, "", 2013, 2015, 1, 1, egn);
if (result != null)
{
using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create("result.xml"))
{
result.WriteTo(writer);
Console.WriteLine(result.ToString());
}
}
else
{
Console.WriteLine("No result");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadKey();
throw;
}
}
private static SecureString CreatePasswordKey(string pin)
{
var pasword = new SecureString();
foreach (var c in pin)
{
pasword.AppendChar(c);
}
return pasword;
}
#region Legacy calls
private static string GetReport(string egn, short report, X509Certificate2 certificate)
{
string result;
var request = GetNewReportRequest(egn, report, certificate);
using (var webResponse = request.GetResponse())
using (var streamReader = new StreamReader(webResponse.GetResponseStream(), UTF8Encoding.UTF8))
{
result = streamReader.ReadToEnd();
}
return result;
}
public static HttpWebRequest GetNewReportRequest(string socialSecurityNumber, short noiReportType, X509Certificate2 cert)
{
//Create request
var request = (HttpWebRequest)WebRequest.Create("https://bwsapplications.nssi.bg/getdata.asmx");
request.Headers.Add("SOAPAction", "https://bwsapplications.nssi.bg/GetData");
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
//Set ServicePointManager
ServicePointManager.ServerCertificateValidationCallback =
(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) => true;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
//Add Envelope
var soapEnvelopeXml = GetReportSoapEnvelope(socialSecurityNumber, noiReportType);
using (var stream = request.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
//Add Certificate
if (cert != null)
{
request.ClientCertificates.Add(cert);
}
return request;
}
public static XmlDocument GetReportSoapEnvelope(string socialSecurityNumber, short reportType)
{
var soapEnvelope = new XmlDocument();
var envelopeString = @"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<GetData xmlns=""https://bwsapplications.nssi.bg"">
<ExternalUserName>Easycredit1</ExternalUserName>
<RepNo>" + reportType + @"</RepNo>
<bulstat></bulstat>
<FromYear>2015</FromYear>
<ToYear>2015</ToYear>
<FromMonth>6</FromMonth>
<ToMonth>11</ToMonth>
<EGN>" + socialSecurityNumber.Trim() + @"0</EGN>
</GetData>
</soap:Body>
</soap:Envelope>";
soapEnvelope.LoadXml(envelopeString);
return soapEnvelope;
}
#endregion
private static void TokenExplorer()
{
using (Pkcs11Explorer pkcs11Explorer = new Pkcs11Explorer("bit4ipki_x64.dll"))
{
string tokenSerial = "1020000000050957";
string tokenLabel = null;
string pin = "78963";
// Find requested token
Token foundToken = null;
List<Token> tokens = pkcs11Explorer.GetTokens();
foreach (Token token in tokens)
{
if (!string.IsNullOrEmpty(tokenLabel))
if (0 != String.Compare(tokenLabel, token.Label, StringComparison.InvariantCultureIgnoreCase))
continue;
if (!string.IsNullOrEmpty(tokenSerial))
if (0 != String.Compare(tokenSerial, token.SerialNumber, StringComparison.InvariantCultureIgnoreCase))
continue;
foundToken = token;
break;
}
if (foundToken == null)
throw new TokenNotFoundException(string.Format("Token with serial \"{0}\" and label \"{1}\" was not found", tokenSerial, tokenLabel));
// Get private keys and certificates stored in requested token
List<PrivateKey> privateKeys = null;
List<Certificate> certificates = null;
pkcs11Explorer.GetTokenObjects(foundToken, true, pin, out privateKeys, out certificates);
// Print private keys
int j = 1;
foreach (PrivateKey privateKey in privateKeys)
{
Console.WriteLine();
Console.WriteLine("Private key no." + j);
Console.WriteLine(" ID (CKA_ID): " + privateKey.Id);
Console.WriteLine(" Label (CKA_LABEL): " + privateKey.Label);
// Print public part of RSA key
if ((privateKey.PublicKey != null) && (privateKey.PublicKey is RsaKeyParameters))
{
RsaKeyParameters rsa = privateKey.PublicKey as RsaKeyParameters;
Console.WriteLine(" RSA exponent: " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned()));
Console.WriteLine(" RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned()));
}
j++;
}
// Print certificates
int k = 1;
foreach (Certificate certificate in certificates)
{
X509Certificate2 x509Cert = CertUtils.ToDotNetObject(certificate.Data);
Console.WriteLine();
Console.WriteLine("Certificate no." + k);
Console.WriteLine(" ID (CKA_ID): " + certificate.Id);
Console.WriteLine(" Label (CKA_LABEL): " + certificate.Label);
Console.WriteLine(" Serial number: " + x509Cert.SerialNumber);
Console.WriteLine(" Subject DN: " + x509Cert.Subject);
Console.WriteLine(" Issuer DN: " + x509Cert.Issuer);
Console.WriteLine(" Not before: " + x509Cert.NotBefore);
Console.WriteLine(" Not after: " + x509Cert.NotAfter);
// Print certified public RSA key
if ((certificate.PublicKey != null) && (certificate.PublicKey is RsaKeyParameters))
{
RsaKeyParameters rsa = certificate.PublicKey as RsaKeyParameters;
Console.WriteLine(" RSA exponent: " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned()));
Console.WriteLine(" RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned()));
}
k++;
}
}
}
private void OldTry()
{
X509Certificate2 certificate = null;
var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindBySerialNumber, "00D61D016B3381AC0A", false);
Console.WriteLine("Certificates count: {0}", certificates.Count);
certificate = certificates[0];
var data = certificate.Export(X509ContentType.SerializedCert, "78963");
RSACryptoServiceProvider csp = null;
if (certificate.HasPrivateKey)
csp = (RSACryptoServiceProvider)certificate.PrivateKey;
using (Pkcs11 pkcs = new Pkcs11("bit4ipki_x64.dll", false))
{
// Find first slot with token present
Slot slot = GetUsableSlot(pkcs);
// Open RW session
using (Session session = slot.OpenSession(false))
{
// Login as normal user
session.Login(CKU.CKU_USER, Settings.Default.PinCode);
session.Logout();
}
}
X509Certificate2 cert = null;
using (Pkcs11RsaSignature pkcs11RsaSignature =
new Pkcs11RsaSignature("bit4ipki_x64.dll", "1020000000050957", null, "78963",
"6961E845-B33C-4E56-9504-FAF59D24D516", null, Net.Pkcs11Interop.PDF.HashAlgorithm.SHA1))
{
byte[] signingCertificate = pkcs11RsaSignature.GetSigningCertificate();
cert = CertUtils.ToDotNetObject(signingCertificate);
}
}
private static Slot GetUsableSlot(Pkcs11 pkcs11)
{
// Get list of available slots with token present
List<Slot> slots = pkcs11.GetSlotList(true);
// First slot with token present is OK...
Slot matchingSlot = slots[0];
// ...unless there are matching criteria specified in Settings class
if (Settings.TokenSerial != null || Settings.TokenLabel != null)
{
matchingSlot = null;
foreach (Slot slot in slots)
{
TokenInfo tokenInfo = null;
try
{
tokenInfo = slot.GetTokenInfo();
}
catch (Pkcs11Exception ex)
{
if (ex.RV != CKR.CKR_TOKEN_NOT_RECOGNIZED && ex.RV != CKR.CKR_TOKEN_NOT_PRESENT)
throw;
}
if (tokenInfo == null)
continue;
if (!string.IsNullOrEmpty(Settings.TokenSerial))
if (0 != string.Compare(Settings.TokenSerial, tokenInfo.SerialNumber, StringComparison.Ordinal))
continue;
if (!string.IsNullOrEmpty(Settings.TokenLabel))
if (0 != string.Compare(Settings.TokenLabel, tokenInfo.Label, StringComparison.Ordinal))
continue;
matchingSlot = slot;
break;
}
}
return matchingSlot;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment