Currently, am working on client server application(Chat) am implementing security for server and clients, few of the client is written in java SMACK library, they are using TLS Pining for JAVA it needs sha2 hash [https://github.com/Flowdalic/java-pinning][1]
Server is implemented using C#, I have certificate on server side how can I get the sha2 public key with below format from the certificate, below is my code.
cer =new X509Certificate2(ConfigurationManager.AppSettings["CertificateName"],"123456");
string hellow= cer.GetCertHashString(); //it will return sha1 hash
what I need is the below format and sha2-256 key from the certificate
SHA2-256 key
83:F9:17:1E:06:A3:13:11:88:89:F7:D7:93:02:BD:1B:7A:20:42:EE:0C:FD:02:9A:BF:8D:D0:6F:FA:6C:D9:D3
I have found the solution for my question, let me share.
If you want to get certificate's SHA256 thumbprint, you have to do some manual work. Built-in Thumbprint property is SHA1 only.
Yo have to use a SHA256 class and compute hash over certificate's content:
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace MyNamespace {
class MyClass {
public static String GetSha2Thumbprint(X509Certificate2 cert) {
Byte[] hashBytes;
using (var hasher = new SHA256Managed()) {
hashBytes = hasher.ComputeHash(cert.RawData);
}
return BitConverter.ToString(hashBytes).Replace("-", ":");
}
}
}
Related
I want to get the public key from x509 pem file, I tried to use this library System.Security.Cryptography.X509Certificates; but couldn't be able to figure it out how to get the Publci key as pem file.
My code:
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace ScottBrady.Pem.NetCore
{
public class Program
{
private const string CertPem = #"MIID9jCCA5ugAwIBAgITbwAAeCy9aKcLA99HrAABAAB4LDAKBggqhkjOPQQDAjBj
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNnb3YxFzAV
BgoJkiaJk/IsZAEZFgdleHRnYXp0MRwwGgYDVQQDExNUU1pFSU5WT0lDRS1TdWJD
QS0xMB4XDTIyMDQxOTIwNDkwOVoXDTI0MDQxODIwNDkwOVowWTELMAkGA1UEBhMC
U0ExEzARBgNVBAoTCjMxMjM0NTY3ODkxDDAKBgNVBAsTA1RTVDEnMCUGA1UEAxMe
VFNULS05NzA1NjAwNDAtMzEyMzQ1Njc4OTAwMDAzMFYwEAYHKoZIzj0CAQYFK4EE
AAoDQgAEYYMMoOaFYAhMO/steotfZyavr6p11SSlwsK9azmsLY7b1b+FLhqMArhB
2dqHKboxqKNfvkKDePhpqjui5hcn0aOCAjkwggI1MIGaBgNVHREEgZIwgY+kgYww
gYkxOzA5BgNVBAQMMjEtVFNUfDItVFNUfDMtNDdmMTZjMjYtODA2Yi00ZTE1LWIy
NjktN2E4MDM4ODRiZTljMR8wHQYKCZImiZPyLGQBAQwPMzEyMzQ1Njc4OTAwMDAz
MQ0wCwYDVQQMDAQxMTAwMQwwCgYDVQQaDANUU1QxDDAKBgNVBA8MA1RTVDAdBgNV
HQ4EFgQUO5ZiU7NakU3eejVa3I2S1B2sDwkwHwYDVR0jBBgwFoAUdmCM+wagrGdX
NZ3PmqynK5k1tS8wTgYDVR0fBEcwRTBDoEGgP4Y9aHR0cDovL3RzdGNybC56YXRj
YS5nb3Yuc2EvQ2VydEVucm9sbC9UU1pFSU5WT0lDRS1TdWJDQS0xLmNybDCBrQYI
KwYBBQUHAQEEgaAwgZ0wbgYIKwYBBQUHMAGGYmh0dHA6Ly90c3RjcmwuemF0Y2Eu
Z292LnNhL0NlcnRFbnJvbGwvVFNaRWludm9pY2VTQ0ExLmV4dGdhenQuZ292Lmxv
Y2FsX1RTWkVJTlZPSUNFLVN1YkNBLTEoMSkuY3J0MCsGCCsGAQUFBzABhh9odHRw
Oi8vdHN0Y3JsLnphdGNhLmdvdi5zYS9vY3NwMA4GA1UdDwEB/wQEAwIHgDAdBgNV
HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwMwJwYJKwYBBAGCNxUKBBowGDAKBggr
BgEFBQcDAjAKBggrBgEFBQcDAzAKBggqhkjOPQQDAgNJADBGAiEA7mHT6yg85jtQ
GWp3M7tPT7Jk2+zsvVHGs3bU5Z7YE68CIQD60ebQamYjYvdebnFjNfx4X4dop7Ls
EBFCNSsLY0IFaQ==";
private const string EccPem = #"MHQCAQEEIDyLDaWIn/1/g3PGLrwupV4nTiiLKM59UEqUch1vDfhpoAcGBSuBBAAKoUQDQgAEYYMMoOaFYAhMO/steotfZyavr6p11SSlwsK9azmsLY7b1b+FLhqMArhB2dqHKboxqKNfvkKDePhpqjui5hcn0Q==
";
public static void Main()
{
// parsing a cert from a PEM file. PEM labels have been stripped
var cert = new X509Certificate2(Convert.FromBase64String(CertPem));
Console.WriteLine($"Certificate loaded with subject '{cert.Subject}' and a key type of '{cert.PublicKey.Oid.FriendlyName}'");
var keey = cert.GetECDsaPublicKey();
Console.WriteLine(keey);
// parsing an ECC key from a PEM file. PEM labels have been stripped
var key = ECDsa.Create();
key.ImportECPrivateKey(Convert.FromBase64String(EccPem), out _);
Console.WriteLine($"Key loaded with key size of '{key.KeySize}'");
var certWithPrivateKey = cert.CopyWithPrivateKey(key);
}
}
}
Can I retrieve public key by providing keyID.( I have imported the public key using kleopatra)
Note:
I am currently passing the public key file path to encrypt the stream.I am successfully encrypting the stream without any issues using BountyCastle nuget package.
I have tried this:
PgpPublicKeyRingBundle bun = new PgpPublicKeyRingBundle(new byte[200]);
var publicc = bun.GetPublicKey(long.Parse("12ERTY564"));
Update:
The above is test KeyID.
I am trying to parse X509 sertificate custom extension. (I have created a self signed certificate with custom extentions of type "certificate policy"). I need to parse this "certificate policy" and its values. Programatically I can get the name of the custom extention that is "certificate policy" but I can not get its values..The code that i am using is as the following:
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
var cert = (X509Certificate2)certificate;
foreach (X509Extension ext in cert.Extensions)
{
// AsnEncodedData x = new AsnEncodedData(ext.Oid, ext.RawData);
MessageBox.Show("Name: " + ext.Oid.FriendlyName + "\nValue: " + ext.Oid.Value);
}
return true;
}
This code onlye display "Certificate Policy" but I need the parse elements of the policy shown in below:
The values under the Certificate Policy elements:
[1]Certificate Policy:
Policy Identifier=1.2.3.4
[2]Certificate Policy:
Policy Identifier=1.5.6.7.8
[3]Certificate Policy:
Policy Identifier=1.3.5.8
[3,1]Policy Qualifier Info:
Policy Qualifier Id=CPS
Qualifier:
Tarzano
[3,2]Policy Qualifier Info:
Policy Qualifier Id=User Notice
Qualifier:
Notice Reference:
Organization=Tarzano Ltd
Notice Number=1, 2, 3, 4
Notice Text=Buraya mesaj yazilabilir
thanks for help !
At first, you will need an ASN.1 parser and use X.509 ASN.1 modules to decode extension value to a collection of policies. I wrote a managed class that extends existing X.509 extensions from .NEt library in my PowerShell PKI module. You can grab managed .dll or project sources from PSPKI project site: http://pspki.codeplex.com/ to get an idea how to decode this extension (I'm using my own ASN.1 parser, so code snippets here will not make much sense) if you want to have something your own (and do not rely on 3rd party assemblies).
there is a PKI.Core.dll (sources are attached too). X.509 extension classes are defined in System.Security.Cryptography.X509Certificates namespace. And documetation for this class in the library: http://pkix2.sysadmins.lv/library/html/T_System_Security_Cryptography_X509Certificates_X509CertificatePoliciesExtension.htm
Extensions are made in a similar way (they inherit from X509Extension class) as .NET native with the exception that my extensions are fully native (do not use CryptoAPI c++ functions, like in .NET).
There appears to be no built-in support in .NET for parsing the ASN.1 data of x509 extensions, beyond the .Format() method, which reverts to returning a hex-encoded string if it encounters any unknown object type.
But the widely used BouncyCastle library, https://www.bouncycastle.org/csharp/, also available through NuGet, has good ASN.1 parsing support. Here is a sample that prints all the OID-type objects found in the extensions of a certificate. It works well on extensions that .NET cannot parse and display. The Org.BouncyCastle.Asn1.Utilities.Asn1Dump.DumpAsString() method is also useful.
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1;
public class AsnTest {
public static void Main() {
var certificate = new X509Certificate2(File.ReadAllBytes("Test.x509"));
foreach (var ext in certificate.Extensions) {
// This is as far as we reliably get with native .NET libraries, switch to BouncyCastle for additional parsing
var o = new Asn1InputStream(ext.RawData).ReadObject();
var q = new Queue<Asn1Sequence>();
var i = new List<DerObjectIdentifier>();
if (o is Asn1Sequence) {
q.Enqueue(o as Asn1Sequence);
} else if (o is DerObjectIdentifier) {
i.Add(o as DerObjectIdentifier);
}
while (q.Any()) {
var s = q.Dequeue();
i.AddRange(s.OfType<DerObjectIdentifier>());
foreach (var n in s.OfType<Asn1Sequence>())
{
q.Enqueue(n);
}
}
if (i.Any()) {
Console.WriteLine("Found the follwing OID value(s) in the " + ext.Oid.Value + " extension: " + string.Join(", ", i.Select(j => j.Id)));
} else {
Console.WriteLine("Found no OID values in the " + ext.Oid.Value + " extension.");
}
}
}
}
Consider the following complete program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace RemoteCertNameMismatchDiagnosis
{
class Program
{
private static bool AcceptAllCertificates(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
Console.WriteLine(sslPolicyErrors.ToString());
return true;
}
static void Main(string[] args)
{
TcpClient client;
SslStream sslStream;
bool acceptAnyCert = false;
client = new TcpClient("google.com", 443);
if (acceptAnyCert)
sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(AcceptAllCertificates), null);
else
sslStream = new SslStream(client.GetStream(), false);
try
{
sslStream.AuthenticateAsClient("test client");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.ReadLine();
}
}
}
It reports this exception
System.Security.Authentication.AuthenticationException: The remote
certificate is invalid according to the validation procedure.
every time. By changing acceptAnyCert to true on line 26, I can have it output this
RemoteCertificateNameMismatch
, leading me to believe it's unhappy with the name on the cert.
This behavior persists whether I point at google.com, amazon.com, or anywhere else on line 28. I don't think google, microsoft, and amazon all have defective certificates. What am I doing wrong?
You need to pass "google.com" to AuthenticateAsClient - it expects the server name as a parameter, not your client name.
Just Updating my experience here, Recently, I got same issue in my SMTP communication with SSL enabled. Problem is - my client certificate name is not matching with server certificate and issue has been fixed by after changing my client certificate name as server certificate.
Regards
Abdul
I am trying to get a MAC TripleDES equivalent of the C# MACTripleDES class.
I have tried following mcrypt(), but that is just encoding in TripleDES. I need to get an equivalent MACTripleDES string as the one that is generated in C# to authenticate a message.
I have also looked at PHP's hash_hmac() function but it does not give the option of generating a MAC with TripleDES
I'm not sure since Microsoft didn't bother to say what standard their class conforms to, but I suspect that this NIST document is what the Microsoft class is computing, only using triple DES in place of DES.
I guess you will have to write your own method using the primitives in mcrypt.
EDIT 1:
Inspired by the bounty, I have these two examples showing equivalent result in PHP and C#.
First, C#:
using System;
using System.Text;
using System.Security.Cryptography;
namespace TDESMacExample
{
class MainClass
{
public static void Main (string[] args)
{
var keyString = "012345678901234567890123";
var keyBytes = Encoding.ASCII.GetBytes(keyString);
var mac = new MACTripleDES(keyBytes);
var data = "please authenticate me example number one oh one point seven niner";
Console.WriteLine(data.Length);
var macResult = mac.ComputeHash(Encoding.ASCII.GetBytes(data));
Console.WriteLine(BitConverter.ToString(macResult));
// B1-29-14-74-EA-E2-74-2D
}
}
}
Next, PHP:
<?php
$data = 'please authenticate me example number one oh one point seven niner';
$key = '012345678901234567890123'; // Key must be 24 bytes long
$iv = '\x00\x00\x00\x00\x00\x00\x00\x00'; // All zero IV is required
$cipher = mcrypt_cbc(MCRYPT_3DES, $key, $data, MCRYPT_ENCRYPT, $iv);
$mac_result = substr($cipher, -8); // Last 8 bytes of the cipher are the MAC
echo "mac result : " . bin2hex($mac_result);
echo "<br>";
?>
The MAC is simply the last eight bytes of the CBC encrypted data. If the key, IV, and the padding method matches, you should be able to just use those bytes.
For more details about MAC definition, see Appendix F of FIPS-81, DES Modes of Operation.