I want to do send a request to api method. But I need to verify signature. I'm using openssl. Firstly I'm creating a signature in this method;
var certificate = new X509Certificate2(certificatePath, certificatePass, X509KeyStorageFlags.Exportable);
var originalData = Encoding.UTF8.GetBytes(dataToSign);
using (var rsa = certificate.GetRSAPrivateKey())
{
var signeddata = rsa.SignData(originalData, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(signeddata);
}
Then need to verify with this code;
var certificate = new X509Certificate2(ceftificatePath, "certificatePass", X509KeyStorageFlags.MachineKeySet);
var dataToVerifyBytes = Encoding.UTF8.GetBytes(dataToVerify);
var signatureBytes = Convert.FromBase64String(signature);
using (var rsaAlg = (RSACryptoServiceProvider)certificate.PublicKey.Key)
using (var sha256 = new SHA256Managed())
{
return rsaAlg.VerifyData(dataToVerifyBytes, sha256, signatureBytes);
}
But I'm getting error when verified.
Verified Error
Error detail is;
Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.
Also I'm trying this with .NET framework 4.8.0.
Take a look at this post on a separate website. It looks like your exactly question. Try to look up your question before posting it on stackoverflow next time.
Related
I'm trying to make a soap service.
To send request I need to use X509 Certificate. I used X509Certificate2 class for that purpose.
The problem is that its keys are System.Security.Cryptography.RSACryptoServiceProvider class that accepts only "http://www.w3.org/2000/09/xmldsig#rsa-sha1" signature algorithm.
In our case sha256 signature algorithm is needed.
Have you got any idea how can I deal with that?
Code looks like this:
SoapService.GetOrderStatusRequest request = new SoapService.GetOrderStatusRequest()
{
orderId = Int32.Parse(txtID.Text),
requestHeader = new SoapService.RequestHeader()
{
institutionId = 123,
requestId = "aeacbff8-ba6d-4a01-8e76-0b4384c24721",
system = "Test"
}
};
var cert = new X509Certificate2(AppDomain.CurrentDomain.BaseDirectory + "//cert.p12", "Passs123");
client.ChannelFactory.Credentials.ClientCertificate.Certificate = cert;
client.ClientCredentials.ClientCertificate.Certificate = cert;
SoapService.GetOrderStatusResponse response = client.getOrderStatus(request);
txtResult.Text = response.order.name;
Edit1.
I found out this is not problem with X509Certificate2 configuration, but with binding configuration... with message security to be exac.
Unfortunately I still have some errors :/
After connecting to a Tezos wallet, you can send over a payload requesting it be signed.
Given the signature, wallet address, and a pre-defined message (payload) what are the steps to determine the authenticity of that signature.
You can do that in C# using Netezos library.
First, you need to obtain the public key for a given wallet address:
using Netezos.Rpc;
using var rpc = new TezosRpc("https://mainnet-tezos.giganode.io/");
var rawPubKey = await rpc.Blocks.Head.Context.Contracts[address].ManagerKey.GetAsync<string>();
Then you can verify the signature:
using Netezos.Keys;
var pubKey = PubKey.FromBase58(rawPubKey);
var isValid = pubKey.Verify(message, signature);
import { verifySignature } from '#taquito/utils';
verifySignature(
payloadBytes,
publicKey,
updateAatarLinkDto.signature,
);
You need to include payloadBytes and signature to verify.
I have a web service which need the body signing on all the requests. so i wonder what is the best practice in order to do that? I'm using this method in order to sign the string but i guess its not the best way. because my private key never disposes:
using (var provider = new RSACryptoServiceProvider())
{
provider.ImportParameters(ProjectValues.PrivateKey.ExportParameters(true));
encryptByteList = provider.SignData(content, CryptoConfig.MapNameToOID("SHA256"));
}
I already read the certificate and private key once when the project loaded for first time. Like this:
Certificate = new X509Certificate2("my pfx path", "***", X509KeyStorageFlags.Exportable);
PrivateKey = (RSACryptoServiceProvider)Certificate.PrivateKey;
Then I found this method:
var cert = new X509Certificate2("my pfx path", "***", X509KeyStorageFlags.Exportable);
using (var rsa = cert.GetRSAPrivateKey())
{
encryptByteList = rsa.SignData(content, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
but this one works if i read certificate from file on every requests. obviously its not a efficient way
Identical code except for the CreateAuthenticationHeader functions below. In .Net 4.5 MVC5 I can REST-access (REST, no storage library) an azure table without difficulty using this:
private static string CreateAuthorizationHeader(string canonicalizedString)
{
var sharedKeyParts = SvcComsCommon.AzureStorageConnectStringDict();
var signature = string.Empty;
using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(sharedKeyParts["AccountKey"])))
{
var dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
var account = sharedKeyParts["AccountName"];
var authorizationHeader = string.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
account,
signature);
return authorizationHeader;
}
On Windows IoT-Core (UWP) newest from Oct. 2015 I use the following (since the above is not supported), which gives me a 403 error and complains that my signature is wrong. The rest of the code is identical. What is the nuance I am missing?
private static string CreateAuthorizationHeader(string canonicalizedString)
{
var sharedKeyParts = SvcComsCommon.AzureStorageConnectStringDict(); // Just the Azure Storage Connection String as Dictionary. No tricks.
var key = CryptographicBuffer.ConvertStringToBinary(sharedKeyParts["AccountKey"], BinaryStringEncoding.Utf8);
var msg = CryptographicBuffer.ConvertStringToBinary(canonicalizedString, BinaryStringEncoding.Utf8);
// Create HMAC.
var objMacProv = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
var hash = objMacProv.CreateHash(key);
hash.Append(msg);
var signature = CryptographicBuffer.EncodeToBase64String(hash.GetValueAndReset());
// Header
var account = sharedKeyParts["AccountName"];
var authorizationHeader = string.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
account,
signature);
return authorizationHeader;
}
I've read the other posts, still not seeing what is missing.
Update Error message on IoT-Core RPi ARM
The operation identifier is not valid.
at SharedLibrary!<BaseAddress>+0x8d1eb9
at SharedLibrary!<BaseAddress>+0xd0e30b
at SharedLibrary!<BaseAddress>+0xd0e7af
at SharedLibrary!<BaseAddress>+0xd0e715
at SharedLibrary!<BaseAddress>+0xd0e69f
at RpiHeadlessCS.Devices.HxaRs485Ftdi.<ReadAsync>d__26.MoveNext()
Exception thrown: 'System.Exception' in RpiHeadlessCS-uwp.Interop.dll
Read async error: The operation identifier is not valid.
UWP has a bug in the framework pertaining to caching behavior that causes Auth errors for Azure Storage. They're working on a fix, but I'm not 100% sure when that fix will be deployed. Sorry about that!
When the line to extract the public key is executed, an LDAP request is sent:
this.certificate = new X509Certificate2(buffer);
System.Security.Cryptography.X509Certificates.PublicKey key = this.certificate.PublicKey;
50 0.853745000 xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx LDAP 404 searchRequest(1) "" baseObject
...which I believe is authenticating the currently logged on user. I really need to avoid this call, as on a customer system this causes a long delay because of network configuration.
I'm assuming it's attempting to do some authentication around some kind of key store, but as in this case the certificate is all contained in the buffer provided, all I want is for the key to be used without this request being sent.
All I actually want is to create an RSACryptoServiceProvider from the private key in the certificate. I tried a few methods I've found on here involving GetPrivateKey, but struggled to get anything to work.
Thanks in advance!
EDIT Test program:
static void Main( string[] args )
{
var certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(#"E:\Temp\Cert.cer");
System.Security.Cryptography.X509Certificates.PublicKey key = certificate.PublicKey;
}
The certificate I tested with can be found here: Cert.cer
Yes, it's not the strongest signature or key, before I get comments!
Thanks again.
EDIT: I actually worked around this by using a suggestion to use BouncyCastle. I use this to parse the certificate:
X509CertificateParser parser = new X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate cert = parser.ReadCertificate(buffer);
I then extract the modulus and exponent and push them into a Microsoft RSAParameters:
RsaKeyParameters key = (RsaKeyParameters)cert.GetPublicKey();
// Construct a microsoft RSA crypto service provider using the public key in the certificate
RSAParameters param = new RSAParameters();
param.Exponent = key.Exponent.ToByteArrayUnsigned();
param.Modulus = key.Modulus.ToByteArrayUnsigned();
I can then construct the Microsoft RSACryptoServiceProvider from this:
using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
{
provider.ImportParameters(param);
byte[] rsaBlock = provider.Encrypt(preMasterSecret, false);
this.Client.Writer.Write(rsaBlock);
}
I never got any other response, so here's the Bouncycastle implementation I used.
X509CertificateParser parser = new X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate cert = parser.ReadCertificate(buffer);
I then extract the modulus and exponent and push them into a Microsoft RSAParameters:
RsaKeyParameters key = (RsaKeyParameters)cert.GetPublicKey();
// Construct a microsoft RSA crypto service provider using the public key in the certificate
RSAParameters param = new RSAParameters();
param.Exponent = key.Exponent.ToByteArrayUnsigned();
param.Modulus = key.Modulus.ToByteArrayUnsigned();
I can then construct the Microsoft RSACryptoServiceProvider from this:
using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
{
provider.ImportParameters(param);
byte[] rsaBlock = provider.Encrypt(preMasterSecret, false);
this.Client.Writer.Write(rsaBlock);
}