CKR_TEMPLATE_INCOMPLETE for X509 certificate C_CreateObject - pkcs#11

I get a TEMPLETE_INCOMPLETE while creating a X509 cert object.
FILL_ATTR(cert_templ[0], CKA_TOKEN, &_true, sizeof(_true));
FILL_ATTR(cert_templ[1], CKA_VALUE, contents, contents_len);
FILL_ATTR(cert_templ[2], CKA_CLASS, &clazz, sizeof(clazz));
FILL_ATTR(cert_templ[3], CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
FILL_ATTR(cert_templ[4], CKA_PRIVATE, &_false, sizeof(_false));
What am I missing here ?

This is the minimal attribute template for certificate object creation that works for me in Pkcs11Admin application:
var certificateAttributes = new List<ObjectAttribute>()
{
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_CERTIFICATE),
new ObjectAttribute(CKA.CKA_TOKEN, true),
new ObjectAttribute(CKA.CKA_PRIVATE, false),
new ObjectAttribute(CKA.CKA_MODIFIABLE, true),
new ObjectAttribute(CKA.CKA_LABEL, privKeyAttributes[0].GetValueAsString()),
new ObjectAttribute(CKA.CKA_CERTIFICATE_TYPE, CKC.CKC_X_509),
new ObjectAttribute(CKA.CKA_SUBJECT, x509Certificate.SubjectDN.GetDerEncoded()),
new ObjectAttribute(CKA.CKA_ID, privKeyAttributes[1].GetValueAsByteArray()),
new ObjectAttribute(CKA.CKA_ISSUER, x509Certificate.IssuerDN.GetDerEncoded()),
new ObjectAttribute(CKA.CKA_SERIAL_NUMBER, new DerInteger(x509Certificate.SerialNumber).GetDerEncoded()),
new ObjectAttribute(CKA.CKA_VALUE, x509Certificate.GetEncoded())
};
It's written in C# but I'm sure you'll be able to read and understand it.
Note that you will most likely need to parse the certificate in order to get correct values of CKA_SUBJECT, CKA_ISSUER and CKA_SERIAL_NUMBER attributes.
Note also that CKA_LABEL and CKA_ID attributes are usually set to the same values as are set on corresponding private key object. This way certificate object gets "paired" with the private key object.

Related

PKCS#11Interop.X509Store unable to find Private Key

Pkcs11X509Certificate is unable to find the private key in some tokens.
Pkcs11X509Certificate.GetRSAPrivateKey() yields null. Then, when I run SignedXml.ComputeSignature(), I get the following error:
System.Security.Cryptography.CryptographicException: 'Signing key is not loaded.'
Adding the code below (proof of concept) to the Pkcs11X509Certificate.FindKey works.
Basically I removed CKA.CKA_LABEL from the search template attributes and it finds the certificate Private Key.
// Contrary to what PKCS#11 specification suggests, subject of the private key is not readable even after login.
// So if we cannot find private key with subject, we will search for private keys without subject.
if (keyHandle == null)
{
searchTemplate = new List<IObjectAttribute>()
{
session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, keyClass),
session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true),
session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId),
//session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, ckaLabel),
};
foreach (IObjectHandle foundObjectHandle in session.FindAllObjects(searchTemplate))
{
keyHandle = foundObjectHandle;
break;
}
}

C# .NET Framework 4.7.2 in VS 2019 - keep out my clientID and client secret / gitignore / Key Vault

I am a new to #C, therefore excuse my question, which will be probably very easy to you. I am trying to get my clientID, clientSecret and tenantID out of the main source control, but I am not sure at all how to do that. I have seen some methods for .NET Core with Connected Services in Visual Studio, but this is not really available for .NET Framework 4.7.2. I am not confident in setting the config file neither. I have created a resource group on Azure Portal, but I am not sure how to get this key vault working.
The code below represents a working code acquiring a token, the issue I have is to hide those hardcoded strings.
Many thanks for your answer
private static string GetToken()
{
string clientID = "xxxad43f-c825-491f-9130-8cc4da1d1111";
string clientSecret = "dRbIT5Wn4#u=55L#fLnYRNuDYrFD#111";
string tenantID = "4ae48b41-0137-4599-8661-fc641fe77111";
var app = ConfidentialClientApplicationBuilder
.Create(clientID)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantID}/oauth2/v2.0/token"))
.Build();
var ApiID = "api://dddd-api";
var scopes = new[] { ApiID + "/.default" };
var result = app.AcquireTokenForClient(scopes).ExecuteAsync().Result;
if (result == null)
throw new Exception("Could not acquire token");
return result.AccessToken;
}
You can set the value as environment variables and use Environment.GetEnvironmentVariable("<variable name>") to get them.
string clientID = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
string clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
string tenantID = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");

Missing Claims via JWT Web Token

I have the following code that creates a JWT token in a webapi core application.
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub, userInfo.Username!=null?userInfo.Username:string.Empty),
new Claim(JwtRegisteredClaimNames.Email, userInfo.Email!=null?userInfo.Email:string.Empty),
new Claim(JwtRegisteredClaimNames.Jti, userInfo.AccountId!=null?userInfo.AccountId.ToString():Guid.Empty.ToString()),
new Claim(JwtRegisteredClaimNames.NameId, userInfo.UserId!=null?userInfo.UserId.ToString():Guid.Empty.ToString()),
new Claim(JwtRegisteredClaimNames.UniqueName, userInfo.ClientId!=null?userInfo.ClientId.ToString():Guid.Empty.ToString())
};
var token = new JwtSecurityToken(_config["Jwt:Issuer"],
_config["Jwt:Issuer"],
claims,
null,
expires: DateTime.Now.AddMinutes(20),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
However when I try to get the claims back after the client has called a webapi end point, I only have the following claims. As you can see the "JTI" claim is fine, but the "UniqueName" claim is missing.
[0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: }
[1]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: }
[2]: {jti: f7c5af77-d0c4-4026-9b33-2fe9fbf5ee28}
[3]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: 00000000-0000-0000-0000-000000000000}
[4]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: b34a1b42-df24-42a3-93d7-68e88523602f}
[5]: {exp: 1581973428}
[6]: {iss: Test.com}
[7]: {aud: Test.com}
What do I need to do to get the claim to appear?
Just to note that the claim that I set as JwtRegisteredClaimNames.UniqueName does appear in the claims but not under that name. Its value is set under the item
[4]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: b34a1b42-df24-42a3-93d7-68e88523602f}
However this is not brought back when use the following as it is null
identity.FindFirst(JwtRegisteredClaimNames.UniqueName).Value;
However this is not brought back when use the following as it is null
identity.FindFirst(JwtRegisteredClaimNames.UniqueName).Value;
To fix the above issue, you can try to clear the inbound claim type map using following code snippet in Startup.cs
System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
Test Result
Set testing value for JwtRegisteredClaimNames.UniqueName
//just for testing purpose
new Claim(JwtRegisteredClaimNames.UniqueName, "b34a1b42-df24-42a3-93d7-68e88523602f")
Can get expected value using identity.FindFirst(JwtRegisteredClaimNames.UniqueName).Value

How to generate password policy based password in OIM 11gr2ps2

I am creating a event handler to modify user password using OIM UserManager API. But now I need to consider password policy and then generate new password that is compatible with the password policy defined in OIM.
Can you please point to some APIs and Methods which can help here?
import oracle.idm.common.ipf.api.password.RandomPasswordGenerator;
import oracle.idm.common.ipf.api.password.RandomPasswordGeneratorImpl;
The classes above actually gives handle on the randomly generated password that I was looking for. The code below shows the implementation for the same.
PasswordPolicyInfo passwordPolicyInfo = ((PasswordMgmtService)Platform.getService(PasswordMgmtService.class)).getApplicablePasswordPolicy(entityId, Boolean.valueOf(false));
RandomPasswordGenerator randomPasswordGenerator = new RandomPasswordGeneratorImpl();
OimPasswordPolicy policy = new OimPasswordPolicy(Utils.getIpfPasswordPolicyInfoVO(passwordPolicyInfo));
policy.setId(passwordPolicyInfo.getId());
policy.setName(passwordPolicyInfo.getName());
char[] generatedPassword = randomPasswordGenerator.generatePassword(policy, null);
Alternatively by using below OIM API's,you can generate password and also validate it against any policy in OIM:
import oracle.iam.passwordmgmt.api.PasswordMgmtService;
import oracle.iam.passwordmgmt.domain.generator.RandomPasswordGeneratorImpl;
Here is the snippet:
RandomPasswordGeneratorImpl randomPasswordGenerator = new RandomPasswordGeneratorImpl();
UserRepository userRepository = new DBUserRepository();
UserInfo usrInfo = userRepository.getUserAndManagerInfo(usrLogin);
String generatedPassword = new String(randomPasswordGenerator.generatePassword(Utils.getUser(usrInfo)));
PasswordMgmtService passMgmt = Platform.getService(PasswordMgmtService.class);
ValidationResult result = passMgmt.validatePasswordAgainstPolicy(generatedPassword.toCharArray(), Utils.getUser(usrInfo), Locale.getDefault());
You can use PasswordMgmtService api provided by OIM.
You can use below method in you password generation logic in your event handler code.
PasswordPolicyDescription getApplicablePasswordPolicyDescription(java.lang.String userID)
In the PasswordPolicyDescription object you have all properties which were configured while creating Password Policy.

SAML token size and REST

We are implementing STS (claim based authentication) for the the REST based services. One of the reasons amongst many when we decide to create REST services (with JSON) was the small footprint over the wire. With STS, the SAML token with just a few claims the SAML size becomes few K bytes. For most of the REST calls where we are not returning list of objects, the response size is low 100s bytes and for those calls this token seems too much of overhead. How do you dealt with this in your projects?
... Or JWT (JSon Web Token). ACS supports these too.
Check this article: JSON Web Token Handler for the Microsoft .NET Framework 4.5
Here is a usage example of this library with .Net 4.5 that issues and validates a JWT signed with symmetric key based HMAC SHA256.
string jwtIssuer = "MyIssuer";
string jwtAudience = "MyAudience";
// Generate symmetric key for HMAC-SHA256 signature
RNGCryptoServiceProvider cryptoProvider = new RNGCryptoServiceProvider();
byte[] keyForHmacSha256 = new byte[64];
cryptoProvider.GetNonZeroBytes(keyForHmacSha256);
///////////////////////////////////////////////////////////////////
// Create signing credentials for the signed JWT.
// This object is used to cryptographically sign the JWT by the issuer.
SigningCredentials sc = new SigningCredentials(
new InMemorySymmetricSecurityKey(keyForHmacSha256),
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
"http://www.w3.org/2001/04/xmlenc#sha256");
///////////////////////////////////////////////////////////////////
// Create token validation parameters for the signed JWT
// This object will be used to verify the cryptographic signature of the received JWT
TokenValidationParameters validationParams =
new TokenValidationParameters()
{
AllowedAudience = s_jwtAudience,
ValidIssuer = s_jwtIssuer,
ValidateExpiration = true,
ValidateNotBefore = true,
ValidateIssuer = true,
ValidateSignature = true,
SigningToken = new BinarySecretSecurityToken(keyForHmacSha256),
};
///////////////////////////////////////////////////////////////////
// Create JWT handler
// This object is used to write/sign/decode/validate JWTs
JWTSecurityTokenHandler jwtHandler = new JWTSecurityTokenHandler();
// Create a simple JWT claim set
IList<Claim> payloadClaims = new List<Claim>() { new Claim("clm1", "clm1 value"), };
// Create a JWT with signing credentials and lifetime of 12 hours
JWTSecurityToken jwt =
new JWTSecurityToken(jwtIssuer, jwtAudience, payloadClaims, sc, DateTime.UtcNow, DateTime.UtcNow.AddHours(12.0));
// Serialize the JWT
// This is how our JWT looks on the wire: <Base64UrlEncoded header>.<Base64UrlEncoded body>.<signature>
string jwtOnTheWire = jwtHandler.WriteToken(jwt);
// Validate the token signature (we provide the shared symmetric key in `validationParams`)
// This will throw if the signature does not validate
jwtHandler.ValidateToken(jwtOnTheWire, validationParams);
// Parse JWT from the Base64UrlEncoded wire form (<Base64UrlEncoded header>.<Base64UrlEncoded body>.<signature>)
JWTSecurityToken parsedJwt = jwtHandler.ReadToken(jwtOnTheWire) as JWTSecurityToken;
You can use SAML tokens with REST endpoints, but more often you will find people using Simple Web Tokens (SWT) instead. Smaller, simpler, etc.
ACS (Access Control Service in Windows Azure PLatform) implements this, for example.