Erroring out creating an ECDSA Key pair with pkcs11interop - pkcs#11

I am connecting to Gemalto HSM which supports secp256r1. I have the following code to create an ECDSA key pair using Pkcs11interop. I am getting the paramsBytes using BouncyCastle NistNamedCurves and X962Parameters.
The HSM keeps comming back with CKR_ATTRIBUTE_TYPE_INVALID. I am new to ECDSA so I may have missed something. Any ideas?
X9ECParameters x9Ec = NistNamedCurves.GetByName("P-256");
X962Parameters x962 = new X962Parameters(x9Ec);
byte[] paramsBytes = x962.GetDerEncoded();
// The CKA_ID attribute is intended as a means of distinguishing multiple key pairs held by the same subject
byte[] ckaId = session.GenerateRandom(20);
// Prepare attribute template of new public key
List<ObjectAttribute> publicKeyAttributes = new List<ObjectAttribute>();
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ECDSA_PARAMS, paramsBytes));
// Prepare attribute template of new private key
List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>();
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyName));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ECDSA_PARAMS, paramsBytes));
// Generate key pair
Mechanism mechanism = new Mechanism(CKM.CKM_ECDSA_KEY_PAIR_GEN);
ObjectHandle publicKeyHandle = null;
ObjectHandle privateKeyHandle = null;
session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle,
out privateKeyHandle);

Found out what was going on. The HSM did not like the
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ECDSA_PARAMS, paramsBytes));
on the private key. PKCS states that the ECDSA params need to be on the public key and can't be on the private key and this implementation enforced that.

In CKA_ECDSA_PARAMS you can insert a byte[] which is specific for any curve name. a list of available names and related byte[] are presented here at SSL GitHub project.
Another thing, add (CKA.TOKEN, true) as other attributes for private key.

Related

Declare certificate purposes in Android <23

In android api 22 I can use only this function to create keys and certificate:
Calendar notBefore = Calendar.getInstance();
Calendar notAfter = Calendar.getInstance();
notAfter.add(Calendar.YEAR, 2);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getApplicationContext())
.setAlias(KEY_ALIAS_CSR)
.setKeySize(2048)
.setSubject(new X500Principal(
"CN=Your Company ," +
" O=Your Organization" +
" C=Your Coountry"))
.setSerialNumber(BigInteger.ONE)
.setStartDate(notBefore.getTime())
.setEndDate(notAfter.getTime())
.build();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
generator.initialize(spec);
generator.generateKeyPair();
I there possibility to set Purpose_Sign of this certificate?
In Api > 23 is easy:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
"key1",
KeyProperties.PURPOSE_SIGN)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.build());
Solved!
String principal = String.format(CN_PATTERN, cn);
ContentSigner signer = new JCESigner((PrivateKey) keyStore.getKey(KEY_ALIAS_TLS, null), DEFAULT_SIGNATURE_ALGORITHM);
PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(
new X500Name(principal), keyStore.getCertificate(KEY_ALIAS_TLS).getPublicKey());
ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
**extensionsGenerator.addExtension(Extension.basicConstraints, true, new BasicConstraints(
true));
extensionsGenerator.addExtension(Extension.keyUsage, true, new KeyUsage(
KeyUsage.digitalSignature | KeyUsage.nonRepudiation | KeyUsage.keyEncipherment
));
extensionsGenerator.addExtension(Extension.extendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth));**
csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest,
extensionsGenerator.generate());
PKCS10CertificationRequest csr = csrBuilder.build(signer);

How do I use the ComponentSpace library to programmatically update cached X509 certificate files when I update SAMLController.Configurations

Good day All,
I am using ComponentSpace as a Service Provider to establish SAML2 Single Sign On to my for my clients. The clients use their own identity providers to authenticate and gain access to my MVC5 web application. The issue I am having is that when a client wants to update their X509 certificate files I update the physical files dynamically, but I have to do an IIS reset to get the new certificate files to be used. How can I avoid having to do an IIS reset and get ComponentSpace to use the new X509 certificate files when authenticating. An example of my code is below.
var samlConfiguration = new
ComponentSpace.SAML2.Configuration.SAMLConfiguration();
var ssoUrl = "https://www.ssoUrl/Consumer";
var ssoName ="https://www.ssoName";
var localServiceProviderConfiguration = new LocalServiceProviderConfiguration()
{
Name = ssoName,
AssertionConsumerServiceUrl = ssoUrl
};
samlConfiguration.LocalServiceProviderConfiguration = localServiceProviderConfiguration ;
var certNamePrimary = ConfigurationManager.AppSettings["Certificate_Path"] + "cert-A.cer";
var certNameSecondary = ConfigurationManager.AppSettings["Certificate_Path"] + "cert-B.cer";
var partnerIdentityProviderConfiguration = new
ComponentSpace.SAML2.Configuration.PartnerIdentityProviderConfiguration()
{
Name = clientConfig.PartnerIdPName,
SingleSignOnServiceUrl = clientConfig.IdPSingleSignOnServiceURL,
SignAuthnRequest = false,
WantSAMLResponseSigned = false,
WantAssertionEncrypted = false,
WantAssertionSigned = true,
PartnerCertificateFile = certNamePrimary ,
SecondaryPartnerCertificateFile = certNameSecondary
};
samlConfiguration.PartnerIdentityProviderConfigurations.AddPartnerIdentityProvider(partnerIdentityProviderConfiguration );
if (ComponentSpace.SAML2.SAMLController.Configurations.Keys.Contains(ssoUrl))
{
ComponentSpace.SAML2.SAMLController.Configurations.Remove(ssoUrl);
ComponentSpace.SAML2.SAMLController.Configurations.Add(ssoUrl, samlConfiguration);
}
else
ComponentSpace.SAML2.SAMLController.Configurations.Add(ssoUrl, samlConfiguration);
ComponentSpace.SAML2.SAMLController.ConfigurationID = ssoUrl;
SAMLServiceProvider.InitiateSSO(Response, null, "http://company.com/adfs/services/trust");

Unable to connect to MongoDB server using x509 certificate authentication from c#

I have configured MongoDB server as given in document https://docs.mongodb.com/manual/core/security-x.509/
and I connected using mongo shell it is working fine.
Next I tried to connect to same server form c# driver, but Time out exception raised.
Below is my code
var cert = new X509Certificate2(#"C:\Program Files\MongoDB\Server\3.2\ssl\client.pfx", "secretkey");
var sslcrd = MongoCredential.CreateMongoX509Credential("CN=Client1,O=School,ST=Some-State,C=IN");
settings.SslSettings = new SslSettings() ;
settings.UseSsl = true;
settings.SslSettings.ClientCertificates = new List<X509Certificate>()
{
cert
};
settings.SslSettings.EnabledSslProtocols = SslProtocols.Default;
settings.SslSettings.ClientCertificateSelectionCallback =
(sender, host, certificates, certificate, issuers) => settings.SslSettings.ClientCertificates.ToList()[0];
settings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
settings.SslSettings.CheckCertificateRevocation = false;
settings.VerifySslCertificate = false;
settings.Credentials = new[] { sslcrd };
MongoClient client = new MongoClient(settings);
var db = client.ListDatabases().ToList();
I went through MongoDB server logs and I am able to see below error
2017-04-10T11:18:21.559+0530 I NETWORK [initandlisten] connection
accepted from
127.0.0.1:53901 #64 (1 connection now open) 2017-04-10T11:18:21.559+0530 E NETWORK [conn64] no SSL certificate
provided by peer; connection rejected 2017-04-10T11:18:21.560+0530 I
NETWORK [conn64] end connection 127.0.0.1:53901 (0 connections now
open)
I am using c# MongoDB.Driver version 2.3.0
and MongoDB package is of version 3.2.
If you have solution for the above please do reply.
Set the value of allowConnectionsWithoutCertificates to false. Also, you need to combine the certificate and the key file.
In despite of this thread be a little bit old, I faced this exactly same issue today and found a solution at MongoDB.com site (Setup Connection Security code example), so,sharing the solution here for future searchs.
Basically the settings should be created from a connection string and follow the next steps straightforward:
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.IO;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
static async Task MainAsync()
{
var connectionString = "mongodb+srv://<your-server.mongodb.net>/?authSource=%24external&authMechanism=MONGODB-X509&retryWrites=true&w=majority";
var settings = MongoClientSettings.FromConnectionString(connectionString);
settings.ServerApi = new ServerApi(ServerApiVersion.V1);
// You will need to convert your Atlas-provided PEM containing the cert/private keys into a PFX
// use openssl and the following line to create a PFX from your PEM:
// openssl pkcs12 -export -in <x509>.pem -inkey <x509>.pem -out <x509>.pfx
// and provide a password, which should match the second argument you pass to X509Certificate2
var cert = new X509Certificate2("<path_to_pfx>", "<pfx_passphrase>");
settings.SslSettings = new SslSettings
{
ClientCertificates = new List<X509Certificate>(){ cert }
};
var client = new MongoClient(settings);
var database = client.GetDatabase("testDB");
var collection = database.GetCollection<BsonDocument>("testCol");
var docCount = collection.CountDocuments("{}");
Console.WriteLine(docCount);
}
}

BouncyCastle - signature algorithm in TBS cert not same as outer cert

I'm trying validate the certificate path and signature using bouncy castle APIs.
And i'm getting the following exception. I have verified that the signature algorithm 'SHA256WithRSAEncryption' is same in my certificates and the issuer certificate.
Any help would be much appreciated.
Exception in thread "main" org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature.
at org.bouncycastle.jce.provider.RFC3280CertPathUtilities.processCertA(Unknown Source)
at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(Unknown Source)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:250)
Caused by: java.security.cert.CertificateException: signature algorithm in TBS cert not same as outer cert
at org.bouncycastle.jce.provider.X509CertificateObject.checkSignature(Unknown Source)
at org.bouncycastle.jce.provider.X509CertificateObject.verify(Unknown Source)
at org.bouncycastle.jce.provider.CertPathValidatorUtilities.verifyX509Certificate(Unknown Source)
... 6 more
signing:
public byte[] sign(byte[] data) throws GeneralSecurityException, CMSException, IOException {
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
generator.addSigner(pk, (X509Certificate) cert,
CMSSignedDataGenerator.DIGEST_SHA1); //Also tried DIGEST_SHA256
generator.addCertificatesAndCRLs(getCertStore());
CMSProcessable content = new CMSProcessableByteArray(data);
CMSSignedData signedData = generator.generate(content, true, "BC");
return signedData.getEncoded();
}
Verification :
CollectionCertStoreParameters params = new CollectionCertStoreParameters(list);
CertStore store = CertStore.getInstance("Collection", params, "BC");
//create certificate path
CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC");
List<X509Certificate> certChain = new ArrayList<X509Certificate>();
//Create the certificate chain
for( int i = 0; i < list.size(); i++)
certChain.add(list.get(i));
//Create the chain of certificates
CertPath certPath = fact.generateCertPath(certChain);
Set<TrustAnchor> trust = Collections.singleton(new TrustAnchor(rootX509cert, null));
//Get the certificate path validator
CertPathValidator validator = CertPathValidator.getInstance("PKIX", "BC");
PKIXParameters param = new PKIXParameters(trust);
param.setRevocationEnabled(false);
param.addCertStore(store);
param.setDate(new Date());
param.addCertPathChecker(new PathChecker());
//Validate the certificate path
validator.validate(certPath, param);
I am not sure this is a problem of your CMS structure or your cert path validation. I think one of your certificates is erroneous.
The exception states that in a X509Certificate (my guess is your signer certificate or in its chain) the value of Certificate signatureAlgorithm is not the same as TBSCertificate signature.
See https://www.rfc-editor.org/rfc/rfc5280#section-4.1:
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier, <--
signatureValue BIT STRING }
TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier, <--
issuer Name,
...

ASP.NET Authentication over 3 sites on same domain

I need a Form authentication over 3 Sites (login.mydomain.com, www.mydomain.com and admin.mydomain.com). Users are from a MSSQL-DB, but I don't think that's a problem.
I've set up my web.config as described here: http://msdn.microsoft.com/en-us/library/eb0zx8fc.aspx , but it doesn't work.
My code for the login:
string RoleString = string.Empty;
RoleString = user.Gruppe.Bezeichnung;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Username, DateTime.Now, DateTime.Now.AddMinutes(2), false, user.Gruppe.name, FormsAuthentication.FormsCookiePath);
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
cookie.Name = "UserCookie";
cookie.Domain = ".mydomain.com";
Response.Cookies.Add(cookie);
Response.Redirect("http://www.mydomain.com/Default.aspx");
What could be the problem? I tried with machine key in webconfig, but that gave me an error with the Viewstate of the MAC...