Read ECC private key PEM into AsymmetricCipherKeyPair c# bouncy castle - c#

I generate an ECC key pair in PEM format using Bouncy Castle using:
var curve = ECNamedCurveTable.GetByName("secp256k1");
var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed());
var secureRandom = new SecureRandom();
var keyParams = new ECKeyGenerationParameters(domainParams, secureRandom);
var generator = new ECKeyPairGenerator("ECDSA");
generator.Init(keyParams);
AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair();
TextWriter textWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(textWriter);
pemWriter.WriteObject(keyPair.Private);
pemWriter.Writer.Flush();
string pem_privatekey = textWriter.ToString();
My current ECC private key is:
-----BEGIN EC PRIVATE KEY-----MIIBUQIBAQQgyDHBaj30dcIsS4otdOXR8ue+rZDwHcGEjxwle3H24W6ggeMwgeACAQEwLAYHKoZIzj0BAQIhAP////////////////////////////////////7///wvMEQEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwRBBHm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeYSDradyajxGVdpPv8DhEIqP0XtEimhVQZnEfQj/sQ1LgCIQD////////////////////+uq7c5q9IoDu/0l6M0DZBQQIBAaFEA0IABHxw0PK0uEvnF1lwhkLmHUlVtQVUrLp/1EcKzfAm6xOL/I6LtQ9nXPxDNhaxf/rPtk3DkZ5CaO0hLr1trCRrJz8=-----END EC PRIVATE KEY-----
I want to read this pem format private in a bouncy castle ECPrivateKeyParameters or AsymmetricCipherKeyPair format.
I am trying the following code.
pem is the above private key string.
PemReader pr = new PemReader(new StringReader(pem));
ECPrivateKeyParameters KeyPair = (ECPrivateKeyParameters)pr.ReadObject();
Why this returns null? Please correct me.

pr.ReadObject() returns an AsymmetricCipherKeyPair instance here. This has the properties Private and Public which here returns an ECPrivateKeyParameters and ECPublicKeyParameters instance respectively, i.e. the code should be:
PemReader pr = new PemReader(new StringReader(pem));
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
ECPrivateKeyParameters privateKeyParams = (ECPrivateKeyParameters)keyPair.Private;
ECPublicKeyParameters publicKeyParams = (ECPublicKeyParameters)keyPair.Public; // for completeness

Related

Creating Netsuite Certificate X509 using C#

I am trying to generate a certificate using Bouncy Castle. When I load it into Netsuite it says certificate parsing error.
The certificate must meet the following requirements:
The public part of the certificate must be in x.509 format with a file extension of .cer, .pem, or .crt.
The length of the RSA key must be 3072 bits, or 4096 bits. The length of EC key must 256 bits, 384 bits, or 521 bits.
The maximum time period that a certificate can be valid is two years. If the certificate is valid for a longer time period, the system automatically shortens the time period to two years.
One certificate can only be used for one combination of integration record, role, and entity. If you want to use the same integration record for multiple entities or roles, you must use a different certificate for each unique combination.
The following example shows how to create a valid certificate using OpenSSL:
openssl req -x509 -newkey rsa:4096 -sha256 -keyout auth-key.pem -out auth-cert.pem -nodes -days 730.
Using the code below
public async Task GenerateX509Certificate()
{
int TenantId = (int)_session.TenantId;
var IntegrationData = await _appIntegrationRepository.FirstOrDefaultAsync(c => c.TenantId == TenantId);
RsaKeyPairGenerator g = new RsaKeyPairGenerator();
g.Init(new KeyGenerationParameters(new SecureRandom(), 3072));
AsymmetricCipherKeyPair pair = g.GenerateKeyPair();
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private);
byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetDerEncoded();
string serializedPrivate = Convert.ToBase64String(serializedPrivateBytes);
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pair.Public);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
string serializedPublic = Convert.ToBase64String(serializedPublicBytes);
// Distribute PEMs.
IntegrationData.PublicKey = serializedPublic;
IntegrationData.PrivateKey = serializedPrivate;
var key = GenerateX509Certificate("company","Los Angeles");
var outputkey = Convert.ToBase64String(key.GetRSAPrivateKey().ExportRSAPrivateKey());
TextWriter textWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(textWriter);
pemWriter.WriteObject(key);
pemWriter.Writer.Flush();
string privateKey = textWriter.ToString();
await _appIntegrationRepository.UpdateAsync(IntegrationData);
}
public static X509Certificate2 GenerateX509Certificate(string commonName, string locality)
{
var keyPair = GetAsymmetricCipherKeyPair();
var certificateGenerator = GetX509V3CertificateGenerator(keyPair, commonName, locality);
var bouncyCastleCertificate = GenerateBouncyCastleCertificate(
keyPair, certificateGenerator);
return GenerateX509CertificateWithPrivateKey(
keyPair, bouncyCastleCertificate);
}
private static AsymmetricCipherKeyPair GetAsymmetricCipherKeyPair()
{
var keyPairGen = new RsaKeyPairGenerator();
var keyParams = new KeyGenerationParameters(
new SecureRandom(new CryptoApiRandomGenerator()), 4096);
keyPairGen.Init(keyParams);
var keyPair = keyPairGen.GenerateKeyPair();
return keyPair;
}
private static X509V3CertificateGenerator GetX509V3CertificateGenerator(
AsymmetricCipherKeyPair keyPair, string commonName, string locality)
{
IDictionary attrs = new Hashtable();
attrs[X509Name.CN] = commonName;
attrs[X509Name.L] = locality;
IList ord = new ArrayList();
ord.Add(X509Name.CN);
ord.Add(X509Name.L);
var gen = new X509V3CertificateGenerator();
gen.SetSerialNumber(BigInteger.ProbablePrime(120, new Random()));
gen.SetNotAfter(DateTime.Now.AddDays(1));
gen.SetNotBefore(DateTime.Now.AddDays(-1));
gen.SetPublicKey(keyPair.Public);
gen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
gen.SetSubjectDN(new X509Name(ord, attrs));
gen.SetIssuerDN(new X509Name(ord, attrs));
var ski = new SubjectKeyIdentifier(
SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public));
gen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, ski);
var keyUsage = new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyCertSign);
gen.AddExtension(X509Extensions.KeyUsage, true, keyUsage);
return gen;
}
private static X509Certificate GenerateBouncyCastleCertificate(
AsymmetricCipherKeyPair keyPair, X509V3CertificateGenerator gen)
{
ISignatureFactory sigFact = new Asn1SignatureFactory(
"SHA256WithRSA", keyPair.Private);
var bcCert = gen.Generate(sigFact);
return bcCert;
}
private static X509Certificate2 GenerateX509CertificateWithPrivateKey(
AsymmetricCipherKeyPair keyPair,
X509Certificate bcCert)
{
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
var asn1Seq = (Asn1Sequence)Asn1Object.FromByteArray(
privateKeyInfo.ParsePrivateKey().GetDerEncoded());
var rsaPrivateKeyStruct = RsaPrivateKeyStructure.GetInstance(asn1Seq);
var rsa = DotNetUtilities.ToRSA(rsaPrivateKeyStruct);
var x509Cert = new X509Certificate2(bcCert.GetEncoded());
return x509Cert.CopyWithPrivateKey(rsa);
}

Generate key/Encryption/Decryption for RSACryptoProvider and BouncyCastle

Key generated through RSACryptoProvider is work for BouncyCastle Encryption (using publickey) / Decryption (using privatekey) ?
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
var pu = rsa.ToXmlString(false);
var pr = rsa.ToXmlString(true);
}
Also, how to generate key using BouncyCastle ?
Answer to first question, yes, RSA is a standard and it doesn't depends on the libraries used.
Second, try this:
public static void GetRsaKeyPair(out string privateXml, out string publicXml)
{
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom secureRandom = new SecureRandom(randomGenerator);
var keyGenerationParameters = new KeyGenerationParameters(secureRandom, 1024);
var rsaKeyPairGenerator = new RsaKeyPairGenerator();
rsaKeyPairGenerator.Init(keyGenerationParameters);
AsymmetricCipherKeyPair rsaKeyPair = rsaKeyPairGenerator.GenerateKeyPair();
var privateRsaParameters = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)rsaKeyPair.Private);
using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider())
{
rsaProvider.ImportParameters(privateRsaParameters);
privateXml = rsaProvider.ToXmlString(true);
publicXml = rsaProvider.ToXmlString(false);
}
}

C# - AsymmetricCipherKeyPair to hexadecimal

I would like an ECDSA AsymmetricCipherKeyPair that I generate in hexadecimal format. Both the public and private keys.
Now I am doing this:
//Generate key pair
ECKeyPairGenerator gen = new ECKeyPairGenerator("ECDSA");
SecureRandom secureRandom = new SecureRandom();
KeyGenerationParameters keyGenParam = new KeyGenerationParameters(secureRandom, keySize);
gen.Init(keyGenParam);
AsymmetricCipherKeyPair keys = gen.GenerateKeyPair();
//Create a PEM and then extract the BASE64 part
var key = keys.Private;
TextWriter textWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(textWriter);
pemWriter.WriteObject(key);
pemWriter.Writer.Flush();
string pem = textWriter.ToString();
var pem2 = pem.Split('\r').Skip(1).TakeWhile(i => !i.Contains("-----")).ToArray();
pem = string.Join("",pem2);
//BASE64 to byte[] to hex
byte[] bytes = Convert.FromBase64String(pem);
string hex = BitConverter.ToString(bytes);
There must be an easier way to get the hexadecimal output.
For the private key:
bytes = Org.BouncyCastle.Pkcs.PrivateKeyInfoFactory.CreatePrivateKeyInfo(keys.Private).ParsePrivateKey().GetDerEncoded();
and the public:
bytes = Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keys.Public).GetDerEncoded();

How to import Firebase Private Key into C#?

I would like to know how Firebase key could be imported to c#
and being used as SingingCredintials for JWT?
private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAAS\n-----END PRIVATE KEY-----\n",
I have tried the following so far, but it bring wrong signing algorithm not RS256
RsaPrivateCrtKeyParameters key;
using (StringReader sr = new StringReader(fbPrivateKey)) //here used StringReader
{
PemReader pr = new PemReader(sr);
key = (RsaPrivateCrtKeyParameters)pr.ReadObject(); //no more keyPair because I just have the privKey only
}
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters(key);
RSACryptoServiceProvider rsa;
rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParams);
var nRsa = PemKeyUtils.GetRSAProviderFromPemFile(fbPrivateKey);
Microsoft.IdentityModel.Tokens.RsaSecurityKey _signingKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(nRsa);
Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials =
new Microsoft.IdentityModel.Tokens.SigningCredentials(_signingKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256);
Also I have tried this with no success
string jwt = string.Empty;
RsaPrivateCrtKeyParameters keyPair;
using (StringReader sr = new StringReader(fbPrivateKey)) //here used StringReader
{
PemReader pr = new PemReader(sr);
keyPair = (RsaPrivateCrtKeyParameters)pr.ReadObject(); //no more keyPair because I just have the privKey only
}
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyPair);
It bring the keyid null and the algorithim rsa-sha1, which is supposed to be rsa256.

Signing a string with RSA private key on .NET?

byte[] plaintext = System.Text.Encoding.UTF8.GetBytes("AAAAAAAAAAAAA");
TextReader trCer = new StreamReader(#"AA.key"); //key in PEM format
PemReader rdCer = new PemReader(trCer);
AsymmetricCipherKeyPair o = rdCer.ReadObject() as AsymmetricCipherKeyPair;
ISigner sig = SignerUtilities.GetSigner("MD5WithRSAEncryption");
sig.Init(true, o.Private);
sig.BlockUpdate(plaintext,0,plaintext.Length);
Byte[] signature = sig.GenerateSignature();
string signatureHeader = Convert.ToBase64String(signature);
Console.WriteLine(signatureHeader);
How I can use a key in DER format?
I'm using the library BouncyCastle.Crypto.dll
`
You should convert der file to pem file using OpenSsl:
openssl x509 -inform der -in certificate.cer -out certificate.pem
And then generate sign from pem using BountyCastle like this:
using (var rsa = new RSACryptoServiceProvider())
{
var privateKey = new StringBuilder();
privateKey.AppendLine("-----BEGIN RSA PRIVATE KEY-----");
privateKey.AppendLine(_config.Value.PrivateKey);
privateKey.AppendLine("-----END RSA PRIVATE KEY-----");
var pem = new PemReader(new StringReader(privateKey.ToString()));
var keyPair = (AsymmetricCipherKeyPair)pem.ReadObject();
var privateKeyParameters = (RsaPrivateCrtKeyParameters)keyPair.Private;
var rsaParameters = DotNetUtilities.ToRSAParameters(privateKeyParameters);
rsa.ImportParameters(rsaParameters);
var sign = rsa.SignData(Encoding.UTF8.GetBytes(data), new HashAlgorithmName("SHA1"),
RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(sign);
}
Above snipped code use private key as a string and I wrap it into pem format.

Categories

Resources