I have a PGP key pair that I created with Kleopatra and I want to know how I can access it using C#?
I am using the PgpCore library to decrypt a file, but it appears I need to feed it the key file and I don't know where it is stored on the machine or the best way to access it.
Is there some way I can query Kleopatra with the ID of the certificate to retrieve the key?
Super late to this, but going through this myself. I think you'll have to export the keys, and then point at the file path where you store them to use in C#
Kleopatra
Export private key: right-click and select 'backup secret keys'
Export public key: right-click' export keys' to back up the public key.
PGPCore code for encryption and decryption:
Encryption using the public key:
// Load keys
EncryptionKeys encryptionKeys;
using (Stream publicKeyStream = new FileStream(#"C:\TEMP\Keys\public.asc", FileMode.Open))
encryptionKeys = new EncryptionKeys(publicKeyStream);
PGP pgp = new PGP(encryptionKeys);
// Reference input/output files
using (FileStream inputFileStream = new FileStream(#"C:\TEMP\Content\content.txt", FileMode.Open))
using (Stream outputFileStream = File.Create(#"C:\TEMP\Content\encrypted.pgp"))
// Encrypt
await pgp.EncryptStreamAsync(inputFileStream, outputFileStream);
Decryption using the private key and password:
// Load keys
EncryptionKeys encryptionKeys;
using (Stream privateKeyStream = new FileStream(#"C:\TEMP\Keys\private.asc", FileMode.Open))
encryptionKeys = new EncryptionKeys(privateKeyStream, "password");
PGP pgp = new PGP(encryptionKeys);
// Reference input/output files
using (FileStream inputFileStream = new FileStream(#"C:\TEMP\Content\encryptedContent.pgp", FileMode.Open))
using (Stream outputFileStream = File.Create(#"C:\TEMP\Content\decrypted.txt"))
// Decrypt
await pgp.DecryptStreamAsync(inputFileStream, outputFileStream);
Obviously change the file paths to the corresponding key path, , encrypt = public, decrypt = private
Related
Is it possible to generate hash of a file using certificate information?
I have certificate details like this
"details": {
"certificate": "XIIHBTCCBO2gAwIBAgIQGuE3Q0ztnKRiYRN.....",
"public_key": "XIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQE...."
},
Using this information I need to create a digestvalue. Assuming the digest value is hash of a file created using the above certificate.
I am using below code to generate hash, but not able to figure out how to use certificate as well.
public static string SHA256CheckSum(string filePath)
{
using (SHA256 SHA256 = SHA256Managed.Create())
{
using (FileStream fileStream = File.OpenRead(filePath))
return Convert.ToBase64String(SHA256.ComputeHash(fileStream));
}
}
I am writing a zip file generator which will be consumed by a third party using a specific encryption algorithm
I have found the enumeration of algorithms here:
ICSharpCode.SharpZipLib.Zip.EncryptionAlgorithm
But I don't know how to apply the algorithm to a given zip archive.
Here's my code.
using (FileStream fsOut = File.Create(fullPath + ".zip"))
using (var zipStream = new ZipOutputStream(fsOut))
{
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
zipStream.Password = "password";
using (MemoryStream memoryStream = new MemoryStream())
using (TextWriter writer = new StreamWriter(memoryStream))
{
// redacted: write data to memorytream...
var dataEntry = new ZipEntry(fullPath.Split('\\').Last()+".txt");
dataEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(dataEntry);
memoryStream.WriteTo(zipStream);
zipStream.CloseEntry();
}
}
Edit
DotNetZip allows you to also choose Zip 2.0 PKWARE encryption algorithm.
As I understand from reading the code and forum posts, EncryptionAlgorithm exists to document the values available in the Zip standard and not as an option for the end user.
The encryption algorithms that are actually available to you are AES128 and AES256. You apply the algorithm on each entry by assigning the AESKeySize property.
So in your case:
// Specifying the AESKeySize triggers AES encryption. Allowable values are 0 (off), 128 or 256.
// A password on the ZipOutputStream is required if using AES.
dataEntry.AESKeySize = 256;
(the comments come from this page https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples/6dc300804f36f981e516fa477219b0e40c192861)
From a legacy program:
bye[] rsaPrivateKeyExport = RSACryptoProvider.ExportCspBlob(true);
These keys are stored in a file.
As part of a legacy refresh, I need to use CNG RSA keys.
So something like reading the old blob and then converting:
CngKey cngPrv = CngKey.Import(rsaPrvKeyExport,
CngKeyBlobFormat.GenericPrivateBlob);
But I cannot get this to work?
How do I convert the old blob type to the new one? Do I only use parts of the old blob?
The key length is 2048.
GenericPrivateBlob is a CNG-specific format, it doesn't mean "try any private thing".
CNG is capable of opening CAPI key blobs, using the formats identified at https://learn.microsoft.com/en-us/windows/desktop/api/Bcrypt/nf-bcrypt-bcryptexportkey.
private static readonly CngKeyBlobFormat s_legacyRsaPrivateBlobFormat =
new CngKeyBlobFormat("CAPIPRIVATEBLOB");
...
byte[] exported;
using (RSACryptoServiceProvider a = new RSACryptoServiceProvider(2048))
{
exported = a.ExportCspBlob(true);
}
RSA b;
using (CngKey key = CngKey.Import(exported, s_legacyRsaPrivateBlob))
{
b = new RSACng(key);
}
// This using is broken out here just to show that the constructed object can safely outlive
// the CngKey object that it was created from.
using (b)
{
...
}
I am using the key-pair to sign my XML (using SignedXml) and I embed the public key in my app as embedded resources.
Here how I create the key pair
sn -k Warehouse.snk
sn -p Warehouse.snk WarehousePublic.snk
When I tried to read the WarehousePublic.snk I get an exception Bad Version of provider.
Here is my code:
using (Stream stream = assembly.GetManifestResourceStream("WareApp.Resources.WarehousePublic.snk"))
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(bytes); //the exception occurred here
...
...
...
}
}
Is there a way to create RSACryptoServiceProvider from public key only?
I have also tried to use X509Certificate2
X509Certificate2 cert = new X509Certificate2(bytes); //I got exception here
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert2.PublicKey.Key;
But I get exception Cannot find the requested object.
Any idea?
Thanks
I'll accepted Shaamaan answer because he is "half" right. You can actually use SN to sign certificate. ImportCspBlob() will work! However, when you tried to to import public key that generated using sn -p Warehouse.snk WarehousePublic.snk, it won't work.
In order to make it work, you need to generate public key in XML using RSACryptoServiceProvider.ToXmlString(false) and embed it as "embedded resources".
What I did is I create a console application. Just cut and paste my code below to generate public key in XML file.
class Program
{
static void Main(string[] args)
{
if (args.Length < 2)
{
Console.WriteLine("Invalid Argument");
Console.WriteLine("Usage:");
Console.WriteLine("\tExtractPublicKey [Input SNK File] [Output XML File]");
return;
}
using (FileStream fs = File.Open(args[0], FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(bytes);
using (StreamWriter sw = new StreamWriter(File.Open(args[1], FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)))
sw.Write(rsa.ToXmlString(false));
}
}
}
}
After you compile it, to use the executable simply call:
ExtractPublicKey.exe [SNK File with Private Key] [Output Public Key in XML File]
To use the embedded certificate, simply do:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(stream.ReadToEnd());
I hope this help someone that come across the similar problem.
Cheers
UPDATED
Shaamaan answer should be followed. Please READ Shaamaan comment with MSDN link. He answer stands because he is not ONLY provide a correct way for security, but also inform me why SN is not right security tool. Thank you Shaamaan!
I think using SN to generate certificates for signing (using the RSACryptoServiceProvider at least) is unsupported. That would explain the error, I think. What you're looking for, in Windows, is a .PFX file (i.e. certificate with key) and .CER file (certificate without private key).
SN (MSDN link) doesn't provide security, and is only used for identity. You can use IIS or makecert.exe to generate a self-signed certificate that should work with what you're trying to do (i.e. a .PFX file and / or certificate already imported into the Windows certificate store). You can then extract the .CER file from that and use it for your project.
I am trying to use BouncyCastle to encrypt a file using the PKCS 7 file standard. Here is the code I have which outputs a p7m file. When I go to decrypt the file (using Entrust) I am prompted for my key store password, so it knows the file was encrypted for me using AES 128, but it cannot decrypt the body of the file. Something has to be going wrong on the encrypt.
byte[] fileContent = readFile(filename);
FileStream outStream = null;
Stream cryptoStream = null;
BinaryWriter binWriter = null;
try
{
CmsEnvelopedDataStreamGenerator dataGenerator = new CmsEnvelopedDataStreamGenerator();
dataGenerator.AddKeyTransRecipient(cert); //cert is the user's x509cert that i am encrypting for
outStream = new FileStream(filename + ".p7m", FileMode.Create);
cryptoStream = dataGenerator.Open(outStream, CmsEnvelopedGenerator.Aes128Cbc);
binWriter = new BinaryWriter(cryptoStream);
binWriter.Write(fileContent);
}
And when i try and decrypt the file using BouncyCastle I get this error when i pass the file contents to a CMSEnveloped Object:
IOException converting stream to byte array: Attempted to read past the end of the stream.
Any ideas whats going on here?
I used the EnvelopedCMS class to accomplish this.
http://msdn.microsoft.com/en-us/library/bb924575(VS.90).aspx