Is there any way to convert a Org.BouncyCastle.X509.X509Certificate to System.Security.Cryptography.X509Certificates.X509Certificate2?
The inverse operation is easy, combining Org.BouncyCastle.X509.X509CertificateParser with
System.Security.Cryptography.X509Certificates.X509Certificate2.Export().
Easy!!
using B = Org.BouncyCastle.X509; //Bouncy certificates
using W = System.Security.Cryptography.X509Certificates;
W.X509Certificate2 certificate = new W.X509Certificate2(pdfCertificate.GetEncoded());
And now I can validate certificate chain in the server:
W.X509Chain ch = new W.X509Chain();
ch.ChainPolicy.RevocationMode = W.X509RevocationMode.NoCheck;
if (!ch.Build(certificate))
res |= ErroresValidacion.CAInvalida;
Useful to validate pdf certifcates extracted with iTextSharp.
From https://github.com/dotnet/corefx/wiki/ApiCompat :
Most users of X509Certificate and X509Certificate2 objects assume that
the object is immutable except for the Reset()/Dispose() methods, the
use of Import violates this assumption.
In other words, trying to use import throws an exception in .net core. You should now use:
new X509Certificate(cert.GetEncoded());
but, according to the .net API analyzer (https://learn.microsoft.com/en-us/dotnet/standard/analyzers/api-analyzer),
warning PC001: X509Certificate2.X509Certificate2(byte[]) isn't supported on macOS
I guess that is the best answer:
var cert = pdf.Certificates[0];//Org.BouncyCastle.X509.X509Certificate
var cert50 = new X509Certificate();
cert50.Import(cert.GetEncoded());
Related
I'm trying to check the certificate with its revocation list (crl-file). In BouncyCustle library there is a method x509Crl.IsRevoked(), that should be used for this. The point is that it gets x509Certificate object as a parameter, but I can't understand how to create this x509Certificate object.
I used DotNetUtilities.FromX509Certificate() for converting from System.Security.Cryptography.X509Certificates.x509Certificate2 object to Org.BouncyCastle.X509.X509Certificate object, but I faced the problem - method IsRevoked() always returns true - for all crl's I tested.
Question: how to create Org.BouncyCastle.X509.X509Certificate object directly from binary without converting from System.Security.Cryptography.X509Certificates.x509Certificate2?
My code for checking certificate with it's crl-file:
static public void RevocationChecker(string certPath, string crlPath)
{
X509Certificate2 cert = new X509Certificate2();
cert.Import(File.ReadAllBytes(certPath));
Org.BouncyCastle.X509.X509Certificate bouncyCert = DotNetUtilities.FromX509Certificate(cert);
X509CrlParser crlParser = new X509CrlParser();
X509Crl crl = crlParser.ReadCrl(File.ReadAllBytes(crlPath));
bool rezult = crl.IsRevoked(bouncyCert);
Console.WriteLine(rezult);
}
Give this a shot:
System.Security.Cryptography.X509Certificates.X509Certificate cert = new System.Security
.Cryptography.X509Certificates.X509Certificate(File.ReadAllBytes(certPath));`
Org.BouncyCastle.X509.X509Certificate bouncyCert = new Org.BouncyCastle.X509
.X509CertificateParser().ReadCertificate(cert.GetRawCertData());
I'm reading a certificate from a X509Store, that I want to get it's CngKey using
GetCngPrivateKey. But all I'm getting is the following error.
at Security.Cryptography.X509Certificates.X509Native.AcquireCngPrivateKey(SafeCertContextHandle certificateContext)\r\n at Security.Cryptography.X509Certificates.X509Certificate2ExtensionMethods.GetCngPrivateKey(X509Certificate2 certificate)\r\n
The certificate is passing the validation HasCngKey, but I'm not able to get its value. Is there any other way to get the CngKey?
byte[] digest = null;
using (var hmac = SHA256.Create())
{
digest = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(data));
}
var certificate = collection[0];
byte[] firmadigital = null;
CngKey privateKey = null;
AsymmetricAlgorithm privateKey1 = null;
var hasCng = certificate.HasCngKey();
if (hasCng)
{
privateKey = certificate.GetCngPrivateKey();
Console.WriteLine("tiene CNG");
var key = new Security.Cryptography.RSACng(privateKey);
key.SignatureHashAlgorithm = CngAlgorithm.Sha1;
var p = key.SignData(digest);
return Convert.ToBase64String(p);
}
I'm using c# net core 2.0
Thanks
You seem to be using an extra library, since neither .NET Framework nor .NET Core has HasCngKey, GetCngPrivateKey(), or a property-based RSACng class. I'm guessing you're using the cryptography library from the clrsecurity CodePlex prototype.
The functionality you're using is in .NET Framework (as of 4.6) and .NET Core (all versions), but under different names.
Instead of
var hasCng = certificate.HasCngKey();
if (hasCng)
{
privateKey = certificate.GetCngPrivateKey();
Console.WriteLine("tiene CNG");
var key = new Security.Cryptography.RSACng(privateKey);
key.SignatureHashAlgorithm = CngAlgorithm.Sha1;
var p = key.SignData(digest);
return Convert.ToBase64String(p);
}
you want
using (RSA rsa = certificate.GetRSAPrivateKey())
{
Console.WriteLine("tiene RSA. Que tipo no es importante.");
var p = rsa.SignData(digest, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(p);
}
It is correct to put the object from GetRSAPrivateKey() into a using block, because the method returns a distinct object every call.
The reason that GetRSAPrivateKey() was chosen (along with fixing up the RSA base class to be more useful) was so the same code works for Windows CNG, Windows CAPI, Linux, and macOS. The only reason to ever inspect the returned object and cast further is to do pointer-based interop with the OS/cryptolib. (But since Windows can return CNG or CAPI as necessary, it's tough to get even that right)
I need to convert a EC private key generated by BouncyCastle to a CngKey in C#. Ultimately, I'm trying to create a PKCS12 that can be imported into the Windows Key Store and am following the information and code example found here.
The EC key pair is generated as follows:
var ecKeyPairGenerator = new ECKeyPairGenerator("ECDSA");
ECKeyGenerationParameters ecKeyGenParams = new ECKeyGenerationParameters(SecObjectIdentifiers.SecP384r1, new SecureRandom());
AsymmetricCipherKeyPair pair = ecKeyPairGenerator.GenerateKeyPair();
To create a CngKey:
PrivateKeyInfo privKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private);
CngKey cngPrivKey = CngKey.Import(privKeyStruct.GetDerEncoded(), CngKeyBlobFormat.Pkcs8PrivateBlob);
Searching on the web, the above should work, e.g., see here. Instead, I'm getting an Unknown error exception
(CryptographicException) at
System.Security.Cryptography.NCryptNative.ImportKey(). If I pass
CngKeyBlobFormat.EccPrivateBlob to CngKey.Import(), I get an
invalid data exception.
As a new newbie to both .NET, CNG, and Cryto, I feel I'm overlooking something. Any ideas would be appreciated.
Thanks!
I want apply the RSA encryption to my project, but encountered some troubles:
First, I have download the JavaScripts library from
http://www.ohdave.com/rsa/ ,and add reference to my project;
Second, I have define the RSA object and code to initialize that:
internal RSACryptoServiceProvider Rsa
{
get
{
if (HttpContext.Cache["Rsa"] != null)
{
RSACryptoServiceProvider encryptKeys = (RSACryptoServiceProvider)HttpContext.Cache["Rsa"];
return encryptKeys;
}
else
{
return new RSACryptoServiceProvider(1024);
}
}
set
{
HttpContext.Cache.Remove("Rsa");
HttpContext.Cache.Insert("Rsa", value);
}
}
public ActionResult SignUp()
{
this.Rsa = Security.GetRsa();
RSAParameters param= this.Rsa.ExportParameters(true);
//this will bind to view
TempData["exponent"] = Util.BytesToHexString(param.Exponent);
TempData["key"] = Util.BytesToHexString(param.Modulus);
UserInfo user = new UserInfo();
user.Birthday = DateTime.Now.Date;
return View(user);
}
private RSACryptoServiceProvider GetRsa()
{
RSACryptoServiceProvider Rsa = new RSACryptoServiceProvider(1024);
return Rsa;
}
3.then, on JavaScript side , I have code, it encrypt the password user input and the bind it control:
var hash = document.getElementById("Pwd").value;
var exponent = document.getElementById("exponent").innerHTML;
var rsa_n = document.getElementById("key").innerHTML;
setMaxDigits(131);
var key = new RSAKeyPair(exponent, "", rsa_n);
hash = encryptedString(key, "111");
document.getElementById("Pwd").value = hash;
document.getElementById("Pwd2").value = hash;
document.getElementById("error").innerHTML = "";
document.getElementById("submit").click();
4.when user click submit, my C# code get the encrypted pwd string and try to decrypt it but failed with exception: bad data:
[HttpPost]
public ActionResult SignUp(UserInfo user)
{
user.UserId = user.UserId.ToLower(); //ignore case
user.UserGUID = Guid.NewGuid();
user.CreatedDate = DateTime.Now;
user.IsEnabled = false;
user.Pwd = Convert.ToBase64String(Rsa.Decrypt(Util.HexStringToBytes(user.Pwd), false));//Exception:Rsa.Decrypt throw bad data exception
who do you know how to fix it? thank you in advance.
I had a very similar problem in that most of the JavaScript based RSA encryption solutions wasn't "compatible" with .NET's implementation.
Almost all the implementations I found online had one or both of the following items causing the incompatibility with .NET's implementation.
The byte order encoding in JavaScript is different to the byte order that .NET used. This is a biggie as for example a string is represented with a different order of bytes in JS than it is in .NET so you'll need to convert before encrypting and after decrypting. I believe it's enough to just reverse the byte order to match .NET, but don't quote me on that.
Padding was different: .NET uses OAEP padding by default for RSA so the JS implementation of RSA should support the same padding too. I believe OAEP padding is also called PKCS#1 v2.0 padding, but don't quote me on that either.
Aside: I found an amazing JS library, called JavaScript.NET (from jocys.com) that mirrors tons of the .NET BCL functionality, including the RSA implementation, such that I could even use similar classes, properties and methods. Have a look at this. I can confirm it works with .NET RSA implementation. Give it a go - here are some links for it:
Jocys JS.NET Code Project demo
Jocys JS.NET Download
Hth
I am trying co import a .pem key into c#, and I've found a library, which does that: BouncyCastle
I've created a code, which loads public key and is supposed to load the data into DSACryptoServiceProvider:
DSA dsa;
using (StreamReader rdr = new StreamReader(#"pubkey.pem"))
{
PemReader pr = new PemReader(rdr);
DsaPublicKeyParameters o = pr.ReadObject() as DsaPublicKeyParameters;
CspParameters prm = new CspParameters(13);
prm.Flags = System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
//o.Parameters.
dsa = new DSACryptoServiceProvider(prm);
DSAParameters dp = new DSAParameters();
dp.G = o.Parameters.G.ToByteArray();
dp.P = o.Parameters.P.ToByteArray();
dp.Q = o.Parameters.Q.ToByteArray();
dp.Y = o.Y.ToByteArray();
if (o.Parameters.ValidationParameters != null)
{
dp.Counter = o.Parameters.ValidationParameters.Counter;
dp.Seed = o.Parameters.ValidationParameters.GetSeed();
}
//todo: missing: J, X?
dsa.ImportParameters(dp);
}
it crashes on dsa.ImportParameters(dp); with following exception: Cryptographic exception:bad data.
What should I change for this to work?
You need to use the ToByteArrayUnsigned method instead of plain ToByteArray one as otherwise there are cases where the byte array representation ends up with a leading zero byte which breaks everything :)