Access to private keys of keychain on Mac OS X - macos

I'm implementing an application for Windows/Mac OS X on C# that digitally signs files with a certificate. To do that I'm using BouncyCastle and iText libraries. On windows works perfectly without any special code. I can read the stored certificates on the machine using this code.
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 certificate in store.Certificates)
{
if (certificate.HasPrivateKey && certificate.NotAfter >= DateTime.Now)
{
// USE CERTIFICATE
}
}
The problem that I'm facing is the access to the certificates stored in the Keychain. Because I can get the information of the certificates, but not their private keys. I suppose that there should be a way to access that information (after a confirmation from the user to allow the access), but I can't see how.
My current implementation to get the information of the certificates is:
var query = new SecRecord(SecKind.Certificate)
{
MatchValidOnDate = DatetimeToNSDate(DateTime.Now),
CanSign = true,
};
var certList = Security.SecKeyChain.QueryAsRecord(query, 100, out var result);
foreach(var cert in certLis)
{
SecCertificate tempCertificate = new SecCertificate(cert);
X509Certificate2 certificateObj = tempCertificate.ToX509Certificate2();
}
This certificateObj is a valid X509 certificate but its privateKey is null.

Related

VSTO - How get the result of user accept of untrusted IMAP SSL certificate

I am working on a plugin for Outlook. When an untrusted certificate for IMAP is used, Outlook asks for confirmation in order to continue working with the server. How can I get information about whether the certificate has been confirmed by user or not in VSTO? Maybe Outlook stores it somewhere in the VSTO entities or maybe in the registry? Helps me please.
I means this "Security warning" window
VSTO (nor Outlook) doesn't provide anything for that. You can use standard .net mechanisms, for example, take a look at the How to validate a SSL certificate with C# thread.
If you're trying to validate that an HTTPS certificate is valid, HttpWebRequest can do that for you.
To make HttpWebRequest check the revocation status you need to set the global ServicePointManager.CheckCertificateRevocationList = true before calling GetResponse().
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
request.ServerCertificateValidationCallback = ValidationCallback;
private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// Since you want to be more strict than the default, reject it if anything went wrong.
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
// If the chain didn't suppress any type of error, and revocation
// was checked, then it's okay.
if (chain.ChainPolicy.VerificationFlags == X509VerificationFlags.None &&
chain.ChainPolicy.RevocationMode == X509RevocationMode.Online)
{
return true;
}
X509Chain newChain = new X509Chain();
// change any other ChainPolicy options you want.
X509ChainElementCollection chainElements = chain.ChainElements;
// Skip the leaf cert and stop short of the root cert.
for (int i = 1; i < chainElements.Count - 1; i++)
{
newChain.ChainPolicy.ExtraStore.Add(chainElements[i].Certificate);
}
// Use chainElements[0].Certificate since it's the right cert already
// in X509Certificate2 form, preventing a cast or the sometimes-dangerous
// X509Certificate2(X509Certificate) constructor.
// If the chain build successfully it matches all our policy requests,
// if it fails, it either failed to build (which is unlikely, since we already had one)
// or it failed policy (like it's revoked).
return newChain.Build(chainElements[0].Certificate);
}

Failed to add Certificate/Key into Xamarin iOS keychain

I am trying to use SecKeyChain to add my certs and private keys into iOS keychain. I tried SecKeyChain.Add() and SecKeyChain.AddIdentity(), but first one return me SecStatusCode "Param", and another one throws "System.InvalidOperationException: Param". Can someone help me to solve this problem? It's hard to find detailed documentation for those methods from Xamarin Website.
using(NSData crt = NSData.FromFile("client1.p12"))
{
X509Certificate2 certificate = new X509Certificate2(crt.ToArray(), password);
var identity = SecIdentity.Import(certificate.Export(X509ContentType.Pkcs12, password), password);
var record = new SecRecord(SecKind.Certificate);
record.Label = "client1_crt";
record.SetValueRef(identity.Certificate);
SecStatusCode secStatus = SecKeyChain.Add(record);
SecKeyChain.AddIdentity(identity)
}
I also tried this way:
using (NSData crt = NSData.FromFile("client1-crt.der")
{
SecStatusCode secStatus = SecKeyChain.Add(new SecRecord(SecKind.Certificate)
{
ApplicationLabel = "client1_crt",
KeySizeInBits = 512,
KeyClass = SecKeyClass.Public,
ValueData = NSData.FromString(crt)
});
}
But secStatus still shows "Param".
Problem solved. Turns out we need to enable keychain in Entitlements.plist file. detail Detail steps:
https://forums.xamarin.com/discussion/comment/330146#Comment_330146

Security token validation between Identity Server 4 and 3

I am trying to use a IdS4 server on .Net Core 2.0 with an IdS3 webforms client on .Net45.
As I login via the client I get this exception on the client browser.
[SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier: 'SecurityKeyIdentifier
(
IsReadOnly = False,
Count = 2,
Clause[0] = X509ThumbprintKeyIdentifierClause(Hash = 0x6B7ACC520305BFDB4F7252DAEB2177CC091FAAE1),
Clause[1] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause
)
',
token: '{"alg":"RS256","kid":"6B7ACC520305BFDB4F7252DAEB2177CC091FAAE1","typ":"JWT",
"x5t":"a3rMUgMFv9tPclLa6yF3zAkfquE"}.{"nbf":1517303703,"exp":1517304003,
"iss":"http://localhost:5000","aud":"webforms","nonce":"636529004845229500.Mjg4YmMxMGEtZjk2MC00YWY5LWJiNTQtYmU0Njg0MDIwYTFhNzczN2Q1ZGMtN2YxYy00NGJmLWJhNzItNTM1ZDc0OTMyNzBj",
"iat":1517303703,"c_hash":"6Sty4gdTWGo4nEo0V_VSVQ","sid":"17936a127b0267d2588646052c4447c6",
"sub":"6498d093-8dc3-4d69-988e-3914d564f4d0","auth_time":1517303700,
"idp":"local","amr":["pwd"]}'.]
I first got this exception without Clause[0] and thought it was because the two samples I was using have different certificates embedded within them.
My attempt to fix this involved creating a new certificate following this guide.
In IdS4 Startup I have
services.AddIdentityServer()
.AddSigningCredential(GetSigningCredential())
and
private X509Certificate2 GetSigningCredential()
{
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindBySerialNumber, "3506fe4f69dc22b340e9c2af500d4659", false);
store.Close();
return certs[0];
}
With the clients secret set to the X509 thumbprint.
This seems to be working. On the IdS3 client I cannot find a way to validate the security token, I assume this would be done by validating the certificate?
If anybody could help me understand my issue better that would be great, I cannot find any useful documentation or examples relating to my case so pretty much anything would be helpful.
Thanks in advance.
Turns out I was trying to validate in the wrong places. All i had to do was point to the certificate in the clients Startup.cs.
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Configuration = new OpenIdConnectConfiguration()
{
// Other Stuff...
SigningTokens = { new X509SecurityToken(GetX509Certificate2()) },
// More Stuff...
Where GetX509Certificate2() is:
private X509Certificate2 GetX509Certificate2()
{
var store = new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
return cert = store.Certificates.Find(X509FindType.FindByThumbprint, "**thumbprint**", false)[0];
}

Java: Luna HSM Verify Sign using Public Key

Using Java API, I am trying to access Public key stored in Luna HSM. Even though I am able to print the corresponding public key label name, but when I am trying to get the public key, I am not able to get the reference to that public key. Here is the code snippet:
KeyStore ks = KeyStore.getInstance("Luna");
ks.load(null, null);
lunaProvider = ks.getProvider();
publicKey = (PublicKey) ks.getKey(alipayImpl.getHsmKeyStorePublicEntryName(), null);
// ****************************************************************************
// ** If the private keystore is not found, return original barcode string. **
// ****************************************************************************
if (publicKey == null) {
throw new Exception("Unable to acquire the Public Key " + alipayImpl.getHsmKeyStorePublicEntryName() + ", Hash will not be verified.");
}
// ***********************************************************
// ** Create a Signature Object and sign the encrypted text **
// ***********************************************************
Signature signatureObject = Signature.getInstance(alipayImpl.getAlipaySignAlgorithm(), lunaProvider);
signatureObject.initVerify(publicKey);
signatureObject.update(signedMessage
.getBytes(AlipayConstants.INPUT_CHARSET_VALUE));
isValidSign = signatureObject.verify(Base64.decode(hash));
I am logging to HSM properly. While Accessing Private Key, I didnt have any issues. Is there any restriction on Luna HSM that access to public key is given only through Certificates?
Thanks in advance.
The correct answer is >
LunaKey lk= LunaKey.LocateKeyByAlias("publicKeyName");
But it is advisable to make the key persistent before querying HSM.
Did you try something like this :
final KeyStore keyStore = KeyStore.getInstance("Luna");
keyStore.load(null, null);
final Certificate certificate = keyStore.getCertificate(alias);
if (certificate == null) {
throw new IllegalArgumentException(String.format("Certificate '%s' does not exists", alias));
}
final PublicKey publicKey = certificate.getPublicKey();
// TODO Working with the public key...
In Java keystore there is no PublicKeyEntry and that's the reason why you're not able to access your public key.
https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.Entry.html
Java's KeyStore.KeyEntry interface has three implementing classes.
PrivateKeyEntry
SecretKeyEntry
TrustedCertificateEntry.
Java expects you to get retrieve a public key out of your certificate. Sebastien Vanmechelen has given you the perfect example on how to do that.
If by any chance, your Luna HSM partition does not have a X509 certificate then using LunaKey is the only alternative.

Importing a Private Key to Keychain returns EINVAL error

I am trying to import RSA private keys into the keychain using my application. The first time I import a key using SecKeychainImport() the operation is successful, a subsequent import gives me an EINVAL (100022) error.
This does not happen if I quit and relaunch the app between two imports. I am including the source code below.
CFArrayRef array = (CFArrayRef)[NSMutableArray array];
SecExternalFormat format = kSecFormatUnknown;
//We are always storing a private key…
SecExternalItemType type = kSecItemTypePrivateKey;
SecKeyImportExportParameters params;
SecKeychainRef keychain;
SecKeychainCopyDefault(&keychain);
memset(&params, 0, sizeof(params));
params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
params.flags = kSecKeyNoAccessControl;
params.keyUsage = CSSM_KEYUSE_ANY;
params.keyAttributes = CSSM_KEYATTR_EXTRACTABLE;
err = SecKeychainItemImport((CFDataRef)data,
(CFStringRef)#"pem",
&format,
&type,
0,
NULL,
keychain,
&array);
if(err == noErr)
{
//Change the kSecKeyPrintName attribute of the keychain item.
}
else
{
//Handle the error by displaying appropriate alert.
}
Am I missing anything obvious?
Try setting the CSSM_KEYATTR_PERMANENT bit in params.keyAttribute. On Lion, I can import multiple PEM-armoured RSA private keys (generated with openssl genrsa) into a keychain if I explicitly set this attribute. If I don't, I get errSecItemNotFound (-25300) when importing the very first key.
(Don't forget to remove kSecKeyNoAccessControl before deploying this code in production. Also, if you generate the key yourself, consider using SecKeyGenerate/SecKeyGenerateSymmetric instead.)

Resources