RSA decryption in .NET 6 - Incorrect parameter - c#

I am working with a friend to decode an RSA-encrypted message. We have a sample working in Go lang but need to do the same in .NET 6+.
package main
import (
"crypto/rand"
cryptorsa "crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"log"
)
type RSA struct {
publicKey *cryptorsa.PublicKey
privateKey *cryptorsa.PrivateKey
}
func NewRSA() (*cryptorsa.PrivateKey, error) {
const pubPEM = `-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----`
key, err := ParsePrivateKey([]byte(pubPEM))
if err != nil {
return nil, err
}
return key, nil
}
func ParsePrivateKey(privateKeyPEM []byte) (*cryptorsa.PrivateKey, error) {
block, _ := pem.Decode(privateKeyPEM)
if block == nil {
return nil, errors.New("decoding private key failed")
}
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, errors.New("parsing private key failed")
}
return privateKey, nil
}
func main() {
rsa, err := NewRSA()
if err != nil {
log.Fatal(err)
}
const encryptedMessage = `
-----BEGIN CVV2 MESSAGE-----
khA8wKKZEvf5uZKacdhhkQIS8u30RaoaASMEkOXCB+BcWx5lAE3KpKNDpppA01f8
Lr84opHTBdj24BUW3zAUbulX4dwX+COipbvOAgT06ndwGe2j2vTj5QP7t4YE/cag
Wnj1jxpN+0XdCW9lFZmmfMry1YanIbMabDyGMuSeF3QkqQKZID9VKX0F5HxG7hsF
GhBoJJ7s8qCoVH41kfJD/xImfHgzPcLrXg56vg+AHgHo/So4dUJUuClcsayclsTP
mRqkQCOqHa2rrB7K15h8B4gVGEQUT4UdAR7dYjoj7tOCYQeT0n27pUAQ/+YK1fGa
rqnHDNgO8CH8LPo3C58uhJ0gR3HmwfY613yg28/iSw1v+UWQiFaxSPJ5DI+2cRji
ZPoWjCj/346r/8mV2tDZCGKKPUXAXIUyYrjGEx/t+jJirX69aoaLC17HBxLGvcUK
cFh/1nXGEbemaOfqWni+vF6qkeeWnDvaYJAcxuivhM/r49aTDYxQ3Pi8o1xWH6Gk
S+8wwKqhUlgD8mF0OWWwMAmb7OBd4e6nYwEIjUcEt6MiOaltpzxMY0biuIUY31WNlnO+M5yh3cZT76fPDzgkSlmVFDVehxK+Tg+N6bk23VYNcKJ8QVpOPAF3zZyu30IT emtx0w+9EqM1KX1sTRgkqIMGeajbfSHFGc07WZobkXk=
-----END CVV2 MESSAGE----- `
block, _ := pem.Decode([]byte(encryptedMessage))
fmt.Println("this is block:", block)
decryptedMessage, err := cryptorsa.DecryptOAEP(sha256.New(), rand.Reader, rsa, block.Bytes, []byte("CVV2"))
if err != nil {
log.Fatal(err)
}
log.Println(fmt.Sprintf("Decrypted number: %s", decryptedMessage))
}
We've tried following for .NET 6 and .NET 7 but it's not working:
using EncryptDecryptRSA;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;
using System.Security.Cryptography;
using System.Text;
namespace ConsoleTester
{
class Program
{
static void Main(string[] args)
{
string cyphertext = #"khA8wKKZEvf5uZKacdhhkQIS8u30RaoaASMEkOXCB+BcWx5lAE3KpKNDpppA01f8
Lr84opHTBdj24BUW3zAUbulX4dwX+COipbvOAgT06ndwGe2j2vTj5QP7t4YE/cag
Wnj1jxpN+0XdCW9lFZmmfMry1YanIbMabDyGMuSeF3QkqQKZID9VKX0F5HxG7hsF
GhBoJJ7s8qCoVH41kfJD/xImfHgzPcLrXg56vg+AHgHo/So4dUJUuClcsayclsTP
mRqkQCOqHa2rrB7K15h8B4gVGEQUT4UdAR7dYjoj7tOCYQeT0n27pUAQ/+YK1fGa
rqnHDNgO8CH8LPo3C58uhJ0gR3HmwfY613yg28/iSw1v+UWQiFaxSPJ5DI+2cRji
ZPoWjCj/346r/8mV2tDZCGKKPUXAXIUyYrjGEx/t+jJirX69aoaLC17HBxLGvcUK
cFh/1nXGEbemaOfqWni+vF6qkeeWnDvaYJAcxuivhM/r49aTDYxQ3Pi8o1xWH6Gk
S+8wwKqhUlgD8mF0OWWwMAmb7OBd4e6nYwEIjUcEt6MiOaltpzxMY0biuIUY31WNlnO+M5yh3cZT76fPDzgkSlmVFDVehxK+Tg+N6bk23VYNcKJ8QVpOPAF3zZyu30ITemtx0w+9EqM1KX1sTRgkqIMGeajbfSHFGc07WZobkXk=";
string privateKey = #"
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";
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
byte[] b = Encoding.UTF8.GetBytes(cyphertext);
byte[] byteData = Convert.FromBase64String(cyphertext);
Decryption(byteData, privateKey, true);
}
static public void Decryption(byte[] Data, string key, bool DoOAEPPadding)
{
try
{
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
RSA.ImportFromPem(key);
// tried with both false and true
// also provided OEAP padding but no luck
var decryptedData = RSA.Decrypt(Data, false);
}
}
catch (CryptographicException e)
{
Console.WriteLine(e.ToString());
}
}
}
}
With RSA.Decrypt(Data, false) we get:
Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'The parameter is incorrect.'
With RSA.Decrypt(Data, true), we get:
System.Security.Cryptography.CryptographicException: 'Cryptography_OAEPDecoding'
Went through a lot of other questions, but didn't work for us.

OAEP has several parameters that must be specified if they differ from the default values of the library used: the content digest, the MGF1 digest and a label. The default values from RFC8017 are SHA-1 for both digests and an empty label (these do not necessarily have to correspond to those of the library used).
Usually, the label is left empty. This is so common that some libraries do not even provide the option to use a different value, as in the case of the native .NET methods, which uses fixed an empty label. Since a different label was applied during encryption, namely CVV2, decryption with the native .NET methods is not possible. Instead, C#/BouncyCastle must be used:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;
...
byte[] ciphertext = Convert.FromBase64String(ciphertextB64);
PemReader pemReader = new PemReader(new StringReader(privatePkcs1PEM));
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
Sha256Digest sha256 = new Sha256Digest();
OaepEncoding oaepEncoding = new OaepEncoding(new RsaEngine(), sha256, sha256, Encoding.UTF8.GetBytes("CVV2"));
oaepEncoding.Init(false, keyPair.Private);
byte[] plaintext = oaepEncoding.ProcessBlock(ciphertext, 0, ciphertext.Length);
Console.WriteLine(Encoding.UTF8.GetString(plaintext)); // 447
This returns 447 as plain text.
Note that in the above example privatePkcs1PEM must be a PEM encoded private RSA key in PKCS#1 format. privateKey used in your code is missing header and footer (-----BEGIN/END RSA PRIVATE KEY-----), so this is not a valid PEM key (and therefore ImportFromPem() should fail).
If an empty label is applied during encryption, the native .NET methods can be used for decryption: RSA.Decrypt(Byte[], RSAEncryptionPadding) with RSAEncryptionPadding.OaepSHA256. This applies SHA-256 for both digests and an empty label.

Related

How to get ECDSA Public Key from x509 pem file

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);
}
}
}

How to sign a message with existing private key by using ECDsa on dotnet core 3.1 MacOS?

I generated a key by running following command:
openssl ecparam -genkey -name secp256k1 -out private.key
Worth mentioning that I had to use secp256k1 curve.
Here is private.key:
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIMaqRFP3zkco2B2xZaIDQ0/JGcgOqzLPcTTJPqvpu+UooAcGBSuBBAAK
oUQDQgAEp0mktO9BMlsVw9lG8EIxr9wZizBHSlUv3VIbf3sTBmCxE4myJvZcgF8b
qDp0T/o9TqnsBw15LU3wdnqV4tJp6w==
-----END EC PRIVATE KEY-----
Then I tried to sign some random plain-text message:
var privateKey = CngKey.Import(privateKeyBytes, CngKeyBlobFormat.EccPrivateBlob);
var signer = new ECDsaCng(privateKey);
var signed = signer.SignData(messageBytes, HashAlgorithmName.SHA256);
But encountered a problem when called CngKey.Import: Windows Cryptography Next Generation (CNG) is not supported on this platform. (MacOS)
Is there any way to accomplish it cross-platform?
This library uses pure C# to safely generate keys, sign and verify ECDSA-secp256k1 signatures. Runs on .NET Standard 1.3+. Here is an example:
using System;
using EllipticCurve;
PrivateKey privateKey = PrivateKey.fromPem(privateKeyPem);
Signature signature = Ecdsa.sign(message, privateKey);
Console.WriteLine(signature.toBase64());
PublicKey publicKey = privateKey.publicKey();
Console.WriteLine(Ecdsa.verify(message, signature, publicKey));
Thanks to Maarten Bodewes I found BouncyCastle.NetCore package.
Here is a solution:
public void Main()
{
var asymmetricCipherKeyPair = ReadAsymmetricCipherKeyPairFromPem("./key.pem");
var signature = GetSignature(asymmetricCipherKeyPair.Private, "Some message");
}
private string GetSignature(AsymmetricKeyParameter privateKeyParameter, string message)
{
var signer = SignerUtilities.GetSigner("SHA-256withECDSA");
signer.Init(true, privateKeyParameter);
signer.BlockUpdate(Encoding.ASCII.GetBytes(message), 0, Encoding.ASCII.GetBytes(message).Length);
var signature = signer.GenerateSignature();
return Convert.ToBase64String(signature);
}
private AsymmetricCipherKeyPair ReadAsymmetricCipherKeyPairFromPem(string pathToPem)
{
using var reader = File.OpenText(pathToPem);
var keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
return keyPair;
}

Get Sha256 public key from certificate

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("-", ":");
}
}
}

Encrypt data by using a public key in c# and decrypt data by using a private key in php

I'm trying to encrypt a JSON string in C# en decrypt it in PHP by using OpenSSL RSA.
The following code is in C#:
public static string EncryptData(string data)
{
string key = #"-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/J/txQvYBm5iOHRRRtgdXd5hq
DEavxy5OExSiwjJgOgT72A9GX7+E7QYfhUZJTGtf+/J84tuJPx6/Ff1dZa1XRW84
/n5m7fw93CTVwpfRFi0Owenor44zgk6ABSfMlCzwGfdcS8AFiWCFUBpatKte6PaO
/WfYK7qz/5faSp3FawIDAQAB
-----END PUBLIC KEY-----";
OpenSSL.Crypto.CryptoKey pKey = OpenSSL.Crypto.CryptoKey.FromPublicKey(key, null);
OpenSSL.Crypto.RSA rsa = pKey.GetRSA();
byte[] encryptedData = rsa.PublicEncrypt (Encoding.UTF8.GetBytes(data), OpenSSL.Crypto.RSA.Padding.PKCS1);
rsa.Dispose();
return Convert.ToBase64String (encryptedData);
}
then I send the encoded encryptedData to PHP and put it into the PrivateKeyDecrypt function.
Code in PHP:
<?php
// include the lib
//require_once('OpenSSL.php');
$ssl = new OpenSSL();
$ssl->loadPrivateKeyWithoutPath('-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC+wVuIECnd7dvt7yqoElg4DL8jSKFpUavKfviSBE2Z+5z5YWnf
i4mp/r0P0jVbE+dfqReaIr4UOt//hPvwvioAJ576KPOCTYZiIGehkqafGWS+01wH
nAPSj/C7Xt7F9Mh5McH4CnBR5VN93KKZtQtfNsNPPBdXwQuquONOUgUgTwIDAQAB
AoGAIQkvpvLVrV/CVQS0qIL00FA00hGEEs9YJyuyNOeV4PMYjn/2bAaogs5hQ9ot
72YVDhYkxkb6EFrZ7FDFqT3l2/BpQEsJ6/GQq2gX0rYGfJ5sWrN+KIuSJr4FWSN+
LrvIEr35hKHY6mytiQg9D58b5kSjaB9ea/qhh/hJL2VfWGECQQDlBBJsccR2ZzzH
QN5omwFrUuxnqraY5LyZB8xUnqo9iDULO+GTcW/5eO9TBoWuDf1Ul3Snts9Tb+uD
UYL1y5onAkEA1Ts182anQHCjUtp2hooLjDcOvIK3gi5TchqHW6T4K3tNtnbfOB9P
gMNgcKljjXlQXl3ornvLTYBC483MS4RpmQJAZMiS9whmBhlOpP1GI1C7oih/Auwc
qVJYMRw+bqrYjnWnqkby8XkFZwsyfx4qrDtZ1eVFIB2SRczGHyc688JjFwJBAIxa
lx6J2VlfSwIEbrQMNaGrs/V9jVERMTgQIjy+j+P/G54ZDMEiSvCUqew+cxryWWZk
Jf6D2cQ/wsez9N9YXzECQQDMH6jS9vp7aabI2UKy5RhTqvP6kRmi28/GHb/8QrFx
tldiw2THvc4+4QT9tuv5OA6xRnEO5mt5u3vFHciqeRR7
-----END RSA PRIVATE KEY-----');
public function PrivateKeyDecrypt($raw_data, $base64 = TRUE)
{
if ($this->privateKey == NULL)
trigger_error("Private key has not been specified.", E_USER_ERROR);
if (!openssl_private_decrypt(($base64) ? base64_decode($raw_data) : $raw_data, $decrypted_data, $this->privateKey, $this->padding))
trigger_error("Unable to decrypt data.", E_USER_ERROR);
return $decrypted_data;
}
The error I get when I call the PrivateKeyDecrypt function is:
FATAL ERROR: unable to decrypt data in ...
Does anyone have any idea what causes this error?
Make your padding match OpenSSL.Crypto.RSA.Padding.PKCS1 in your C# code.

MACTripleDES in PHP

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.

Categories

Resources