OpenPGP decryption in C# with X.509 Certificate .pfx file private key - c#

Friends,
We procured class 3 certificate both .pfx and .cer certificates from Certificate Authority. And shared .cer(public key) to our partner.
Encryption (Java)
Our Partner encrypted the message (with our public key) using Java bouncy castle openpgp standard and shared the encrypted message like below,
-----BEGIN PGP MESSAGE-----
Version: x
v2hQEMAzFXJ94q1Nm8AQf/Tld0/3dAvgFKPQVBS8bmbXChXeApeReo1ydNS+......
-----END PGP MESSAGE-----
Decryption: (C#)
We need to decrypt the message with our .pfx file.
I have gone through below articles,
http://burnignorance.com/c-coding-tips/pgp-encryption-decryption-in-c/
It seems new PGPKeyPair is being generated and used for encryption and decryption.
But in my case, i have .pfx file
How do we extract the pgpprivate key from .pfx file use for decryption?
Could you share some thoughts on how we can do this. Advance thanks for all your time on this.
13/12/2020
I had imported the X509Certificate .pfx into store like below and trying to convert the pgpprivate key,
string certPath = #"C:\Users\test.pfx";
string certPass = "apples";
// Create a collection object and populate it using the PFX file
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(certPath, certPass, X509KeyStorageFlags.PersistKeySet);
X509Certificate2 certificate = collection[0];
AsymmetricAlgorithm x509PrivateKey = certificate.PrivateKey;
PgpPrivateKey pK = x509PrivateKey; //Here i am gettting the invalid conversion error.
I am trying to use the X.509 certificate Private key as PGPrivatekey in decryption. But while assigning the private key to pgpprivatekey, getting the invalid cast exception.
Is there any way to achive this?
Regards,
Stalin

You can try using BouncyCastle API to read pfx file using PKCS12 class file, then convert the key to PgpSecretKey.
read document on -- > pkcs12.GetKey()
and PgpSecretKey class.
public static void GetPriveKey(String pfxFile, String pfxPassword)
{
//Load PKCS12 file
Pkcs12Store pkcs12 = new Pkcs12Store(new FileStream(pfxFile, FileMode.Open, FileAccess.Read), pfxPassword.ToArray());
string keyAlias = null;
foreach (string name in pkcs12.Aliases)
{
if (pkcs12.IsKeyEntry(name))
{
keyAlias = name;
break;
}
}
//
AsymmetricKeyParameter Privatekey = pkcs12.GetKey(keyAlias).Key;
X509CertificateEntry[] ce = pkcs12.GetCertificateChain(keyAlias);
AsymmetricKeyParameter PublicKey= ce[0].Certificate.GetPublicKey();
PgpSecretKey mySecretKey = new PgpSecretKey(PgpSignature.DefaultCertification,
PublicKeyAlgorithmTag.RsaGeneral,
PublicKey,
Privatekey,
DateTime.UtcNow,
keyAlias,
SymmetricKeyAlgorithmTag.Cast5,
pfxPassword.ToCharArray(),
true,
null,
null,
new SecureRandom());
}

Related

.NET Core 3.1 - RSA.ImportRSAPrivateKey raises a CryptographicException

I'm training to asymmetric encryption with RSA. I created a key pair with ssh-keygen, and I managed to encrypt some data with my public key.
But when I try to decrypt this data with my private key, this exception is raised :
System.Security.Cryptography.CryptographicException : 'ASN1 corrupted data.'
Here is my PEM file containing my private key :
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,E79376C1ECFD82F05A871D9245BFC958
iEL9aNdWIC3TckveRH2ADdHrnCAQeyg0GUFx0obx1sHOCDdiCIb2u46vFUQ8QP6H
vHHgA9Kf4lY8Jq6Qkv/Iyhh9WcWTR2nNjbN7Ndlb343MyjeNdlXdVrHsfR8Q98ul
06FiKZdnS640PzxAUvibbmkLVus8g3V14qZqeDTqN1rbOCAk2Kxfy5V4kd6M7wCm
fqABkYpp+2EYf4Z4YcJbLDXEEIg7HD/AI1gPpE5nRQoSib/9bm87j98VnG5dOYAJ
38ZMTvJjIImQveOUeSNyR/re71V+YUy0N/zvqMrlp4pDFsDb6infZga0jPFzGXGy
5S3XYXSs9iPReFHQnhWr/L3dRx9TpfZJcl4BJ6D8j9wxrWRcharGNNgCK/kV9FJw
BpwFu01jNESDHV3dyWTcOAzQit4pDkr0A9EK4N1vfWaLLO8vqyGtqlvtU5sD2rYQ
JvrMEsUsAYXJcBDUX2cksNEen+7s338cBGg4NdE+xAUeKv5EysYIKgojPJi6WQ39
FAgkr1TfWaffO/TgfL/DwC1wyHXleNyDQ87unyxRIRu/wWnqJaQQG8Z0BilIbDp8
KrKfkHW9CWaPCbldOzHJ5UDZmA5+AvfoaATRw/vW1Wg0GYkuNqqHzV7tNFKcnUG1
DmIaSI+Y55cngqeOStFfgRTehbXK84w3PzR3lnpuxG4rtOjDV8RfZSozaSValqju
ZWRYEbKn7Za2XZWJT4kkDa5O4nJUMbihBOUL+FWc6dmDIaZY/nUKJAm2pxmd0R1s
9PcXhqLEnBTvGh1CrOdhiqkHQ5A5OtIp/FrPhUltjsy129NC5/dPZaN9v4TgNYQu
zNd8vSlVXuimB+2OoXu3fNE75ywxmrs4H8M4y3u87GQWFdYwQFFnv2fyCzV8iqvy
ybQR599v5qL2IKvHdw68q9PDmasd4jSTAoFP/g6QQKMCaQuMUbrtlHzvPvNnCgk1
AChbFeuLK57c2rwVwTx0YEATcKz27/V5af0E2x6sLDoqQv5SBkREuuWyA6DsSO/S
vX1WR/hZWk2PVi24N/AG8T/sIfyBeTPw7Yx3RuT5MWLdR6haSEKkGGrGuxr1HnoF
lt3JruZczavGpAn5Q8DSVKb78Q8kqI/gdLYNIuq5Yy7Mz1ldocN0N2CarUGWgU7e
+z0TM2CWkTBE7Q0CU4Na5QusvaLYDgH4LW4WY9BNN86C4uKQFjJHz6gZoI3zx8/L
RxN2bGyd0H83k4xuQXml2RnnPPB6L5JwJxxme5ecWpMdp5c6xyXX1ZPKkkGuRbFs
OxeQqNNfPEExqtC2U/Jn5B1HYJqCYCeKlUNdqUoZv5vT8x9UDoE5vKtP3DtTckeB
+6n7S2viNWzV2qid8moh9DfWGMlF4i1y91pdcNJx+M01OfLOB1EPlD0MoTvkfU6s
x0VQh5t4wCbcJ7kcIrp2siPbBg4RPV8MNKtaBhTvFf+nH1TAEsUMjdi7FrnfBn3b
4o4BqC+ibQHC/+SkGAxRakdJjM5XcXO1BZp4zLYSBQyXGu7kp8ohOvHx65vtwvls
XCdbtnJs/iAORxAgLnuVPzLUfTd6bLlszOsyIvC8+j587GX5YFW+h4s+bicZMwCm
-----END RSA PRIVATE KEY-----
And here is the code sample using this private key :
static string RSA_Decrypt(byte[] value)
{
byte[] deciphered;
using (var reader = File.OpenText(#"C:\Users\???\.ssh\id_rsa"))
{
// Extracting the payload
string privateKeyFile = reader.ReadToEnd();
var exp = privateKeyFile.Split("\n\n");
var privateKey = exp[1].Split("\n-----")[0];
// using the payload to decrypt my data
using(var rsa = RSA.Create())
{
rsa.ImportRSAPrivateKey(Convert.FromBase64String(privateKey), out _); //CryptographicException
deciphered = rsa.Decrypt(value, RSAEncryptionPadding.Pkcs1);
}
}
return Encoding.Default.GetString(deciphered);
}
What am I doing wrong?
The posted private key is a PEM encoded PKCS#1 key that is encrypted.
RSA.ImportRSAPrivateKey() can only import unencrypted keys of this format that are furthermore DER encoded. The DER encoding results from the PEM encoding by removing the header and footer and Base64 decoding the rest.
As far as I know, an encrypted PKCS#1 key cannot be imported with .NET Core 3.1 on-board means. But an import is possible with BouncyCastle and its Org.BouncyCastle.OpenSsl.PemReader class, see e.g. here.
Unlike the PKCS#1 format, a DER encoded private key in PKCS#8 format can be imported with .NET Core 3.1 out of the box (RSA.ImportPkcs8PrivateKey()), even if it is encrypted (RSA.ImportEncryptedPkcs8PrivateKey()).
Keys of this format can be generated e.g. with openssl genpkey. With OpenSSL it is also possible to convert between the formats.
Thanks Topaco, that's exactly what I needed! I used BouncyCastle to decrypt my private key, and now it's working perfectly! I don't know why RSA class does not have any method to do it...
So here is my code now :
static string RSA_Decrypt(byte[] value)
{
string deciphered;
using (var reader = File.OpenText(#"C:\Users\???\.ssh\id_rsa"))
{
string privateKeyFile = reader.ReadToEnd();
var keyReader = new StringReader(privateKeyFile);
var decryptEngine = new Pkcs1Encoding(new RsaEngine());
object pemReader = new PemReader(keyReader, new PasswordFinder("azerty")).ReadObject();
var keyPair = (AsymmetricCipherKeyPair)pemReader;
decryptEngine.Init(false, keyPair.Private);
deciphered = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(value, 0, value.Length));
}
return deciphered;
}
PS : Yeah, my private key password is "azerty" ^^ I wasn't inspired when I created my key pair ^^

Why does self signed PFX X509Certificate2 private key raise a NotSupportedException?

I created a self signed PFX X509Certificate2 (using this answer) but for some reason, the private key of the certificate is throwing a NotSupportedException despiste a true HasPrivateKey property.
string password = "MyPassword";
ECDsa ecdsa = ECDsa.Create();
CertificateRequest certificateRequest = new CertificateRequest("cn=foobar", ecdsa, HashAlgorithmName.SHA256);
X509Certificate2 cert = certificateRequest.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(5));
File.WriteAllBytes("e:\\mycert.pfx", cert.Export(X509ContentType.Pfx, password));
//I tried to load the with every flag without success...
X509Certificate2 loadedCert = new X509Certificate2("e:\\mycert.pfx", password);
if (loadedCert.HasPrivateKey)
{
//loadedCert.HasPrivateKey is true but loadedCert.PrivateKey raise a NotSupportedException...
using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)loadedCert.PrivateKey)
{
byte[] encryptedBytes = rsa.Encrypt(Encoding.UTF8.GetBytes("Hello"), false);
byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, false);
string result = Encoding.UTF8.GetString(decryptedBytes);
}
}
Some have mentioned that calling the Export of the certificate would fix the private key but it didn't work for me. I'm probably missing something but I can't figure what it could be. Is there a missing parameter somewhere?
You are creating ECDSA key pair, while X509Certificate2.PrivateKey supports only DSA and RSA private keys that are stored in legacy cryptographic service provider (CSP). ECDSA is always stored in key storage provider (KSP) which is not supported by this property. Instead, you must use GetECDsaPrivateKey extension method: GetECDsaPrivateKey(X509Certificate2)
there are two types of algorithms for public-key cryptography(RSA and ECC). the problem is you are creating an ECC (I.E ECDsa) and then you are trying to get it as an RSA private key. which is definitely not correct. what you should do here is to use one algorithm on both sides so.
2. if you only want to Encrypt and then Decrypt piece of data, why using X509Certificate2, use AES instead. which is meant for this purpose.

How can I (properly) verify a file using RSA and SHA256 with .NET?

I was following this great tutorial on digitally signing/verifying data with .NET. I modified that example code to use SHA256 and hit the "Invalid algorithm specified" exception, which led me to this SO question about signing data with SHA256 in .NET 4.0.
One of the answers from that post helped me figure out how to properly generate the digital signature by explicitly loading a SHA256-capable crypto provider without relying on an exportable private key (see the code towards the bottom of the following method where the RSACryptoServiceProvider is constructed):
static string mKeyContainerName;
static byte[] SignText(string text, string publicCertPath)
{
// Access Personal (MY) certificate store of current user
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
// Load the certificate we'll use to verify the signature from a file.
X509Certificate2 publicCert = new X509Certificate2(publicCertPath);
publicCert.Verify();
string publicHash = publicCert.GetCertHashString();
// Find the certificate we'll use to sign
X509Certificate2 privateCert = null;
foreach(X509Certificate2 cert in store.Certificates)
{
if(cert.GetCertHashString() == publicHash)
{
// We found it. Get its associated private key
privateCert = cert;
break;
}
}
store.Close();
if(privateCert == null)
{
throw new Exception("No valid private cert was found");
}
// Hash the string
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
SHA256Managed sha256 = new SHA256Managed();
byte[] hash = sha256.ComputeHash(data);
// The basic crypto provider only supports SHA-1.
// Force Enhanced RSA and AES Cryptographic Provider which supports SHA-256.
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)privateCert.PrivateKey;
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
mKeyContainerName = csp.CspKeyContainerInfo.KeyContainerName;
var cspparams = new CspParameters
(
enhCsp.ProviderType, enhCsp.ProviderName, mKeyContainerName
);
csp = new RSACryptoServiceProvider(cspparams);
// Sign the hash
return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
}
It may be worth noting that I am using a self-signed cert from makecert.exe. According to another answer in that same post, these problems wouldn't occur if I included the proper -sp or -sy flags in makercert.exe. However, even after specifying either of these flags (currently using -sy 24) I still have to perform the workaround.
This implementation differs slightly from the accepted answer in that post (again, as our private key is not exportable). But that answer does indicate that the verification can be done without explicitly loading a SHA256-capable crypto provider. Thus, I should have been able to do this before returning in the method above:
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)privateCert.PrivateKey;
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
mKeyContainerName = csp.CspKeyContainerInfo.KeyContainerName;
var cspparams = new CspParameters
(
enhCsp.ProviderType, enhCsp.ProviderName, mKeyContainerName
);
csp = new RSACryptoServiceProvider(cspparams);
// Sign the hash
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
if (!csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature))
throw new CryptographicException();
return signature;
However, this won't verify (BTW, I've tried both SignData/VerifyData and SignHash/VerifyHash). The only way I can get it to verify is if I again explicitly load a SHA256-capable crypto provider. Unfortunately, the KeyContainerName member of the CspKeyContainerInfo constructed from a public certificate is always null. Thus, the only way I can get the data to verify is if I cache (or hard-code) the private key's KeyContainerName. Hence the reason for the mKeyContainerName field in the above method and snippet below:
// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
cspparams = new CspParameters
(
enhCsp.ProviderType, enhCsp.ProviderName, mKeyContainerName
);
csp = new RSACryptoServiceProvider(cspparams);
if (!csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature))
throw new CryptographicException();
This does verify, but I don't like having to hard-code the private key's KeyContainerName. The private key won't be available on the machine that is doing the verification.
Does anyone know of a better way to accomplish this? Thanks!
I stumbled on my own answer quite by accident. Turns out using a self-signed cert created with makecert.exe is the culprit here. If I use a cert created with OpenSSL or a commercial cert, I no longer have to explicitly load a SHA256-capable crypto provider. Thus I don't have to hard code the container name in the CspParameters object used to instantiate the RSACryptoServiceProvider. This signing code now works as expected:
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)privateCert.PrivateKey;
// Sign the hash
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
The same is true on the verify side:
// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
I never found out what was different about the cert generated by makecert.exe, but it was not important for me as we are signing with a commercial cert now.

CryptographicException "Key not valid for use in specified state." while trying to export RSAParameters of a X509 private key

I am staring at this for quite a while and thanks to the MSDN documentation I cannot really figure out what's going. Basically I am loading a PFX file from the disc into a X509Certificate2 and trying to encrypt a string using the public key and decrypt using the private key.
Why am I puzzled: the encryption/decryption works when I pass the reference to the RSACryptoServiceProvider itself:
byte[] ed1 = EncryptRSA("foo1", x.PublicKey.Key as RSACryptoServiceProvider);
string foo1 = DecryptRSA(ed1, x.PrivateKey as RSACryptoServiceProvider);
But if the export and pass around the RSAParameter:
byte[] ed = EncryptRSA("foo", (x.PublicKey.Key as RSACryptoServiceProvider).ExportParameters(false));
string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider).ExportParameters(true));
...it throws a "Key not valid for use in specified state." exception while trying to export the private key to RSAParameter. Please note that the cert the PFX is generated from is marked exportable (i.e. I used the pe flag while creating the cert). Any idea what is causing the exception?
static void Main(string[] args)
{
X509Certificate2 x = new X509Certificate2(#"C:\temp\certs\1\test.pfx", "test");
x.FriendlyName = "My test Cert";
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
try
{
store.Add(x);
}
finally
{
store.Close();
}
byte[] ed1 = EncryptRSA("foo1", x.PublicKey.Key as RSACryptoServiceProvider);
string foo1 = DecryptRSA(ed1, x.PrivateKey as RSACryptoServiceProvider);
byte[] ed = EncryptRSA("foo", (x.PublicKey.Key as RSACryptoServiceProvider).ExportParameters(false));
string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider).ExportParameters(true));
}
private static byte[] EncryptRSA(string data, RSAParameters rsaParameters)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
byte[] plainData = bytConvertor.GetBytes(data);
RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
publicKey.ImportParameters(rsaParameters);
return publicKey.Encrypt(plainData, true);
}
private static string DecryptRSA(byte[] data, RSAParameters rsaParameters)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
RSACryptoServiceProvider privateKey = new RSACryptoServiceProvider();
privateKey.ImportParameters(rsaParameters);
byte[] deData = privateKey.Decrypt(data, true);
return bytConvertor.GetString(deData);
}
private static byte[] EncryptRSA(string data, RSACryptoServiceProvider publicKey)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
byte[] plainData = bytConvertor.GetBytes(data);
return publicKey.Encrypt(plainData, true);
}
private static string DecryptRSA(byte[] data, RSACryptoServiceProvider privateKey)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
byte[] deData = privateKey.Decrypt(data, true);
return bytConvertor.GetString(deData);
}
Just to clarify in the code above the bold part is throwing:
string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider)**.ExportParameters(true)**);
I believe that the issue may be that the key is not marked as exportable. There is another constructor for X509Certificate2 that takes an X509KeyStorageFlags enum. Try replacing the line:
X509Certificate2 x = new X509Certificate2(#"C:\temp\certs\1\test.pfx", "test");
With this:
X509Certificate2 x = new X509Certificate2(#"C:\temp\certs\1\test.pfx", "test", X509KeyStorageFlags.Exportable);
For the issue I encountered a code change was not an option as the same library was installed and working elsewhere.
Iridium's answer lead me to look making the key exportable and I was able to this as part of the MMC Certificate Import Wizard.
Hope this helps someone else. Thanks heaps
I've met some similar issue, and X509KeyStorageFlags.Exportable solved my problem.
I'm not exactly an expert in these things, but I did a quick google, and found this:
http://social.msdn.microsoft.com/Forums/en/clr/thread/4e3ada0a-bcaf-4c67-bdef-a6b15f5bfdce
"if you have more than 245 bytes in your byte array that you pass to your RSACryptoServiceProvider.Encrypt(byte[] rgb, bool fOAEP) method then it will throw an exception."
For others that end up here through Google, but don't use any X509Certificate2, if you call ToXmlString on RSACryptoServiceProvider but you've only loaded a public key, you will get this message as well. The fix is this (note the last line):
var rsaAlg = new RSACryptoServiceProvider();
rsaAlg.ImportParameters(rsaParameters);
var xml = rsaAlg.ToXmlString(!rsaAlg.PublicOnly);
AFAIK this should work and you're likely hitting a bug/some limitations. Here's some questions that may help you figure out where's the issue.
How did you create the PKCS#12 (PFX) file ? I've seen some keys that CryptoAPI does not like (uncommon RSA parameters). Can you use another tool (just to be sure) ?
Can you export the PrivateKey instance to XML, e.g. ToXmlString(true), then load (import) it back this way ?
Old versions of the framework had some issues when importing a key that was a different size than the current instance (default to 1024 bits). What's the size of your RSA public key in your certificate ?
Also note that this is not how you should encrypt data using RSA. The size of the raw encryption is limited wrt the public key being used. Looping over this limit would only give you really bad performance.
The trick is to use a symmetric algorithm (like AES) with a totally random key and then encrypt this key (wrap) using the RSA public key. You can find C# code to do so in my old blog entry on the subject.
Old post, but maybe can help someone.
If you are using a self signed certificate and make the login with a different user, you have to delete the old certificate from storage and then recreate it. I've had the same issue with opc ua software

How to get private key from PKCS#12 (.p12) file using C#

Im trying to sign some data using PKCS#12 certificate ,however i have problem with obtaining private key from PKCS#12 (.p12) file.
public byte[] sign(string text)
{
string password = "1111";
X509Certificate2 cert = new X509Certificate2("c:\\certificate.p12",password);
byte[] certData = cert.Export(X509ContentType.Pfx,password);
X509Certificate2 newCert = new X509Certificate2(certData, password);
RSACryptoServiceProvider crypt = (RSACryptoServiceProvider)newCert.PrivateKey;
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);
return crypt.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
}
The problem is that newCert.PrivateKey is null but if i am using .pfx certicitae in similar way it works.
public byte[] sign(string text)
{
string password = "1234";
X509Certificate2 cert = new X509Certificate2("c:\\certificate.pfx", password);
RSACryptoServiceProvider crypt = (RSACryptoServiceProvider)cert.PrivateKey;
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1.ComputeHash(data);
return crypt.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
}
So the question is how to get that private key from .p12 file ?
I had a similar problem which I posted here, although it is not the same thing for you, the problem may be also permissions.
My suggestions are, first, you have to make sure (which I suppose you already did) that the private key is exportable and you have permissions to the file.
Next, try exporting the content type as X509ContentType.Pkcs12 instead of X509ContentType.Pfx
Finally, if it is possible, why don't you try importing it to the certstore. I believe that's more secure. The steps are in the link above.
Have a look at this question. It looks very similar.
In the docs, it says that .export() doesn't support the Pfx type, only Cert, SerializedCert, and Pkcs12.
This was done for using Android - so the R.raw.key below was my file in the Android Raw folder.
I opened key.p12 as as input stream. Which I then converted to the private key using the libraries as seen in the example.
http://www.flexiprovider.de/examples/ExampleSMIMEsign.html
My code looks like this
Security.addProvider(new de.flexiprovider.core.FlexiCoreProvider());
// Next, we have to read the private PKCS #12 file, since the the
// private key used for signing is contained in this file:
DERDecoder dec = new DERDecoder(getResources().openRawResource(
R.raw.key));
PFX pfx = new PFX();
try {
pfx.decode(dec);
SafeBag safeBag = pfx.getAuthSafe().getSafeContents(0)
.getSafeBag(0);
PKCS8ShroudedKeyBag kBag = (PKCS8ShroudedKeyBag) safeBag
.getBagValue();
char[] password = "my password for the p12".toCharArray();
privKey = kBag.getPrivateKey(password);
new AsyncLoadStorage(this).execute();
} catch (ASN1Exception e) {

Categories

Resources