Generate AES Key and Encode it to Base 64 String - c#

I need to generate an AES key and send it to the server.
Creating the key doesn't seem to be a problem:
var aesProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
var aesKey = aesProvider.CreateSymmetricKey(CryptographicBuffer.GenerateRandom(16));
However, exporting the AES key to a base64 encoded string seemes impossible;
I've tried exporting it using the Export/ExportPublic methods on the key object, but they all throw NotImplemented exception:
aesKey.ExportPublicKey(); not implemented
aesKey.ExportPublicKey(CryptographicPublicKeyBlobType.BCryptPublicKey);
aesKey.ExportPublicKey(CryptographicPublicKeyBlobType.Capi1PublicKey);
aesKey.Export();
aesKey.Export(CryptographicPrivateKeyBlobType.BCryptPrivateKey);
aesKey.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);
aesKey.Export(CryptographicPrivateKeyBlobType.Pkcs8RawPrivateKeyInfo);
aesKey.Export(CryptographicPrivateKeyBlobType.Capi1PrivateKey);

Related

How to decrypt an OpenPGP RSA Encrypted text file in C#?

I am hoping that this question can be met with some guidance for someone who is beginning to work with encryption/decryption in C#. There are existing examples on the web regarding this, but I am truthfully struggling to put it all into practice for my given situation.
If given a text file that has been encrypted using OpenPGP with RSA, what is the best method to decrypt this in C#?
This is what I am attempting:
Using Kleopatra OpenPGP, I am generating a key pair using 2048bit RSA. This generates a private and public key.
I am then encrypting/signing a text file with a few word in it as a test.
In C#, I want to decrypt this text file.
Current code:
byte[] encryptedData = File.ReadAllBytes("C:\\PGP Encryption\\test.txt.gpg"); // The encrypted text file generated by Kleopatra.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Import the RSA Key information. This needs
//to include the private key information.
RSA.ImportParameters(RSAKeyInfo);
//Decrypt the passed byte array and specify OAEP padding.
decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
}
return decryptedData;
Unfortunately, the RSA.Decrypt() call throws an exception that reads "The data to be decrypted exceeds the maximum for this modulus of 128 bytes."
I also do not believe that my private key is actually being loaded, as I'm not explicitly stating where the key is. But I don't see how the RSAParameters object is supposed to get populated otherwise.
If anyone can point me in the right direction to decrypt a file in this way, thank you in advance for your time and information.
It's looks like you need this library (see Decrypt section) https://github.com/mattosaurus/PgpCore

Export RSA Public Key in DER Format and decrypt data

I need to get the bytes of my RSA Public Key in the DER format and send this key to an API. This API will then send me something encrypted using this Public Key back and i need to decrypt it.
First problem, it seems that C# doesn't have the ability to export RSA Keys in the DER Format. So it seems i have to rely on a 3rd party package like BouncyCastle. I also found a way to generate and export my Public Key in the DER Format with this package:
var generator = new RsaKeyPairGenerator();
generator.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
var keyPair = generator.GenerateKeyPair();
var publicKeyParam = (RsaKeyParameters)keyPair.Public;
var publicKey = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKeyParam).GetDerEncoded();
So now i only had to Base64 encode those bytes and send it to the API and the API is happy. But now i'm stuck trying to figure out how i can decrypt the dat i received. First of all i decoded the base64 string and now i'm stuck with the bytes of the data. I can get the private key from the BouncyCastle "thing", but i cant seem to convert it to RsaCryptoServiceProvider correctly and the BouncyCastle documentation is kind of weird.
If anyone has an idea or another approach i would be more than happy.
Based on the comments i came up with this solution:
var rsa = new RSACryptoServiceProvider(2048); // my rsa to decrypt and encrypt data
var publicKeyParam = DotNetUtilities.GetRsaPublicKey(rsa.ExportParameters(false));
var publicKey = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKeyParam).GetDerEncoded(); // my exported public key in DER format
Thanks alot James K Polk!

Decrypting Crypto++ RSA cipher text in C# causes exception

I've written 3 functions in C++ using Crypto++ to generate key pairs, encrypt and decrypt a string. Crypto++ side:
//Decode public key
RSA::PublicKey pbKeyDecoded;
StringSource ss2(publicKey, true, new Base64Decoder);
pbKeyDecoded.BERDecode(ss2);
Integer m = Integer((const byte*)plaintext.data(), plaintext.size());
Integer crypted = pbKeyDecoded.ApplyFunction(m);
...
What I do is, generate the key, DER Encode it, and then encode it to Base64. After than, I'm ciphering a plaintext via the public key and save both the private key and the cipher as base64 encoded strings in two separate files.
Now to C#. I'm reading the base64 string, decoding them and load them via AsnParser, which seem to load just fine. Then I call Decrypt. C# side:
AsnKeyParser keyParser = new AsnKeyParser("rsa-public.der");
RSAParameters publicKey = keyParser.ParseRSAPublicKey();
CspParameters csp = new CspParameters;
csp.KeyContainerName = "RSA Test (OK to Delete)";
csp.ProviderType = PROV_RSA_FULL; // 1
csp.KeyNumber = AT_KEYEXCHANGE; // 1
RSACryptoServiceProvider rsp = new RSACryptoServiceProvider(csp);
rsp.PersistKeyInCsp = false;
rsp.ImportParameters(privateKey);
//Causes exception here..
var data = rsp.Decrypt(cipherArr, true);
...
But I'm getting exception error when I try to decrypt it with fOAEP = true: CryptographicException: Error occurred while decoding OAEP padding. If I pass fOAEP = false then I get CryptographicException: The parameter is incorrect.
Why am I getting an exception in C# when attempting to decrypt the Crypto++ cipher text?
... I'm getting exception error when I try to decrypt it: CryptographicException: Error occurred while decoding OAEP padding. That's if I pass true for the fOAEP bool, if I pass false to it I get CryptographicException: The parameter is incorrect.
You are having the same problem as Encrypt and Decrypt a message using raw RSA algorithim in Crypto++? and How to sync Crypto++ RSA with C# RSA crypto service provider? It must be our month for the "Raw RSA" schemes...
On the Crypto++ side of the equation, you are performing raw RSA. You are simply applying the forward function, which is exponentiation, and you are not formatting the message:
//Decode public key
RSA::PublicKey pbKeyDecoded;
StringSource ss2(publicKey, true, new Base64Decoder);
pbKeyDecoded.BERDecode(ss2);
Integer m = Integer((const byte*)plaintext.data(), plaintext.size());
Integer crypted = pbKeyDecoded.ApplyFunction(m);
...
On the C# side of things, you are performing RSA decryption using PKCS #1 with either PKCS #1.5 padding or OAEP padding:
RSACryptoServiceProvider rsp = new RSACryptoServiceProvider(csp);
rsp.PersistKeyInCsp = false;
rsp.ImportParameters(privateKey);
//Causes exception here..
var data = rsp.Decrypt(cipherArr, true);
Its not clear to me if the C# version of your code can perform OAEP padding because its it requires a certain version of the CLR. You may only have PKCS padding available.
I believe you have two choices. First, you can use a standard RSA encryption method in Crypto++. The Crypto++ wiki lists them at RSA Cryptography and RSA Encryption Schemes:
typedef RSAES<PKCS1v15>::Decryptor RSAES_PKCS1v15_Decryptor;
typedef RSAES<PKCS1v15>::Encryptor RSAES_PKCS1v15_Encryptor;
typedef RSAES<OAEP<SHA> >::Decryptor RSAES_OAEP_SHA_Decryptor;
typedef RSAES<OAEP<SHA> >::Encryptor RSAES_OAEP_SHA_Encryptor;
Second, you need to perform Raw RSA in C#. To perform Raw RSA in C#, you will need to get a BigInteger class and apply the inverse function manually.
I would encourage you to use RSA Encryption with OAEP padding. If OAEP is not available, then the second choice would be PKCS padding. Finally, if all you have is Raw RSA, then I would look for another encryption system because Raw RSA is so insecure.

Get private key file with sha256 in C #

Currently I perform this operation through openssl, and I have had no problem with the generated file
openssl dgst -sha256 -sign privateKey.key -out file.txt.signature file.txt
Now, we want to automate the generation of the file using C #, but I have not been able to get the same result.
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(CreateToken("key...", "text"));
Console.ReadLine();
}
public static string CreateToken(string key, string message)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(key);
HMACSHA256 hmacsha256 = new HMACSHA256(keyByte);
byte[] messageBytes = encoding.GetBytes(message);
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return System.Text.Encoding.UTF8.GetString(hashmessage);
}
}
I'm new to working with this, what would be the right way?
Am I not retrieving the information properly ?, Should I get the content directly from the file?
Thank you very much.
Signature generation is not the same thing as HMAC message authentication and it uses a different key. As HMAC can use a key of any size, it will probably take the private key, but that's not how it is supposed to work. RSA is an asymmetric algorithm that uses private and public keys, MAC uses symmetric, secret keys. The dgst -sign instead uses RSA PKCS#1 v1.5 padding to sign the file.
From the OpenSSL Wiki on dgst:
When signing a file, dgst will automatically determine the algorithm (RSA, ECC, etc) to use for signing based on the private key's ASN.1 info. When verifying signatures, it only handles the RSA, DSA, or ECDSA signature itself, not the related data to identify the signer and algorithm used in formats such as x.509, CMS, and S/MIME.
HMAC is not the same thing as SHA-256 either. RSA signature generation uses a hash, not a HMAC. You should use the SHA256 class to create a hash. HMAC is a message authentication code build using the SHA-256 hash. However, the SHA class is not needed as signature generation usually includes the hash generation (you sign a message, not a hash value).
So to create a signature, take a look at the RSAPKCS1SignatureFormatter class, it includes an example at the bottom. Try again using this example.
Make sure your message only contains ASCII (both in the text file as in your string) or your result may fail as well.

NotImplementedException when decrypting RSA signed hash

I want to verify a private key signed SHA256 hash using the CryptographicEngine in a UWP application. The hash is created externally and is signed with a private RSA key with passphrase. For this example however, I also generate the unsigned hash. Both hashes are then compared at the end to verify that they are the same.
I have created my private and public keys using OSX command line, specified in this blog.
This gave me two .pem files. My public key has the following structure:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3fasaNKpXDf4B4ObQ76X
qOaSRaedFCAHvsW4G0PzxL/...ETC ETC
-----END PUBLIC KEY-----
Here is my C# code to decrypt the hash:
//HASH THE INPUT STRING
var inputText = "stringtohash";
// put the string in a buffer, UTF-8 encoded...
IBuffer input = CryptographicBuffer.ConvertStringToBinary(inputText,
BinaryStringEncoding.Utf8);
// hash it...
var hasher = HashAlgorithmProvider.OpenAlgorithm("SHA256");
IBuffer hashed = hasher.HashData(input);
// format it...
string ourhash = CryptographicBuffer.EncodeToBase64String(hashed);
Debug.WriteLine(ourhash);
//CONVERT EXTERNAL HASH TO BUFFER
IBuffer data = CryptographicBuffer.DecodeFromBase64String("b18fbf9bc0fc7595af646155e18b71e1aeccf01719f9f293c72217d7b95cc2106edb419078c4c5c1c7f7d106b90198a4f26beb49ff4a714db4bface1f94fff193b8126ce05fe13825144a3dde97f55399846b6fd768f1fb152f1ba71bbf5cde8c1a7e58621a493070256e2444db36c346a88e870906529cf13c072ead50b6a01b2e74c7ef8c5d423e8ea25220f524b563ae2c3345b7837f9cd1a357540b1380c86287b9a240cf67f7518f11418352b665b657c5ffb6cbcb6126ec59e360de6304392b78cf4de79b52d73b8292df6a1e643d0c0f0945aae5949b391e2915772c996f03e6d1879192b7edf0f40c01b875e768358aa47a992070f628418ddf06472");
//CONVERT PUBLIC KEY TO BUFFER
IBuffer publickey = CryptographicBuffer.DecodeFromBase64String("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3fasaNKpXDf4B4ObQ76XqOaSRaedFCAHvsW4G0PzxL / RuAQFz80esZPyyDCps1PAbTKzQ + QblChPo7PJkbsU4HzNN4PIRGh5xum6SRmdvOowrlTUtyxdOkRJoFxmiR / VCea + PUspt26F7PLcK9ao5 + hVzMvPuqdYenqzd01f1t5hQEhFQ9qjB6Es8fpizHd / RSRfZ7n6rVKm9wYfCRLB7GJ7IHhWGuZrx9fjzsbW8eagu06qRhnUuR5oDVjXC8ZeazsRiw50xMuOzkhX9Oo081IYikwCgseJmQhT7vF4lZoyeB4qJpwTCA + glSy1w9N8ZfxyXK8QaT2RsrBrzl0ZCwIDAQAB");
// Open an asymmetric algorithm provider for the specified algorithm.
AsymmetricKeyAlgorithmProvider rsa = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);
// Import Key
CryptographicKey key = rsa.ImportPublicKey(publickey, CryptographicPublicKeyBlobType.X509SubjectPublicKeyInfo);
// Decrypt the Hash using our Key
IBuffer result = CryptographicEngine.Decrypt(key, data, null);
Debug.WriteLine(result.ToString());
//Compare the two hashes
if (data == result) {
//Hash is verified!
}
Unfortunately when reaching the Decrypt method I get a NotImplementedException with error
The method or operation is not implemented
I researched online and I understand what needs to happen in theory but I don't know how to debug this further. What can I try?
Although both called PKCS#1 v1.5 padding, the padding for signature generation and encryption is not identical, see RFC 3447 for more details.
If you look at the RsaPkcs1 property you can see it is aimed at encryption:
Use the string retrieved by this property to set the asymmetric algorithm name when you call the OpenAlgorithm method. The string represents an RSA public key algorithm that uses PKCS1 to pad the plaintext. No hash algorithm is used.
As I don't see any option for "raw RSA", i.e. RSA without padding, it seems you are only able to verify your signature. However, RSA decryption expects an RSA private key. It's very likely that you get the error because of this: if you try and decrypt with a public key it will fail.
If you want to precompute the hash you can use VerifySignatureWithHashInput.
For other functionality you may have to use e.g. the C# lightweight API of Bouncy Castle. In the end you don't need platform provided cryptography to verify a signature.

Categories

Resources