C# (NET6) - creating keypair (public cert/private key) FROM PFX - c#

I'd like to export PFX (public + private part) to separate files (*.cer, *.key). PFX may (or may not) be password protected.
I've tried to achieve my goal, which is fine with certificate (public), but causes a problem with private key.
My bootastrap class is as below:
public class CertBootstrap
{
private readonly FileInfo CertificateFile;
private readonly SecureString CertificatePassword;
public bool HasPasswordBeenSet { get; private set; } = false;
public X509Certificate2 Certificate { get; private set; }
public CertBootstrap(FileInfo certificationFile, string password)
{
if(!certificationFile.Exists)
{
throw new FileNotFoundException(certificationFile.FullName);
}
CertificateFile = certificationFile;
HasPasswordBeenSet = true;
CertificatePassword = ConvertPassword(password);
}
public CertBootstrap(FileInfo certificationFile)
{
if(!certificationFile.Exists)
{
throw new FileNotFoundException(certificationFile.FullName);
}
CertificateFile = certificationFile;
HasPasswordBeenSet = false;
}
public CertBootstrap(string certificationFullFileName, string password)
{
var certificateFile = new FileInfo(certificationFullFileName);
if(certificateFile == null || !certificateFile.Exists)
{
throw new FileNotFoundException(certificationFullFileName);
}
CertificateFile = certificateFile;
HasPasswordBeenSet = true;
CertificatePassword = ConvertPassword(password);
}
public CertBootstrap(string certificationFullFileName)
{
var certificateFile = new FileInfo(certificationFullFileName);
if(certificateFile == null || !certificateFile.Exists)
{
throw new FileNotFoundException(certificationFullFileName);
}
CertificateFile = certificateFile;
HasPasswordBeenSet = false;
}
public bool VerifyPassword(string password)
{
try
{
byte[] fileContent = File.ReadAllBytes(CertificateFile.FullName);
var certificate = new X509Certificate2(fileContent, password);
}
catch(CryptographicException ex)
{
if((ex.HResult & 0xFFFF) == 0x56)
{
return false;
}
;
throw;
}
return true;
}
private static SecureString ConvertPassword(string password)
{
var secure = new SecureString();
foreach(char c in password)
{
secure.AppendChar(c);
}
return secure;
}
public void LoadBootstrap()
{
LoadBootstrap(X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
}
public void LoadBootstrap(X509KeyStorageFlags keyStorageFlags)
{
this.Certificate = this.HasPasswordBeenSet ? new X509Certificate2(this.CertificateFile.FullName, this.CertificatePassword, keyStorageFlags) : new X509Certificate2(this.CertificateFile.FullName);
}
private static RSA ExportPrivateKeyCoreNet5Net6(RSA privateKey)
{
var password = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
PbeParameters pPar = new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 100_000);
try
{
byte[] tempG = privateKey.ExportEncryptedPkcs8PrivateKey(password, pPar);
using(RSA exportRewriter = RSA.Create())
{
exportRewriter.ExportParameters(true);
exportRewriter.ImportEncryptedPkcs8PrivateKey(password, tempG, out _);
return exportRewriter;
}
}
catch(Exception e)
{
//catch this error
string em = e.Message;
throw;
}
}
private static byte[] ExportPrivateKey(RSA privateKey)
{
try
{
return privateKey.ExportPkcs8PrivateKey();
}
catch(CryptographicException)
{
}
return ExportPrivateKeyCoreNet5Net6(privateKey).ExportRSAPublicKey();
}
public byte[] GeneratePrivateKeyPem()
{
byte[] privateCertKeyBytes = ExportPrivateKey(this.Certificate.GetRSAPrivateKey());
char[] newPemData = PemEncoding.Write("PRIVATE KEY", privateCertKeyBytes);
return newPemData.Select(c => (byte)c).ToArray();
}
public byte[] GenerateCertificatePem()
{
var certData = Certificate.RawData;
var newPemData = PemEncoding.Write("CERTIFICATE", certData);
return newPemData.Select(c => (byte)c).ToArray();
}
public FileInfo SaveCertificate()
{
var newData = GenerateCertificatePem();
var oldFile = Path.GetFileNameWithoutExtension(CertificateFile.FullName);
var newCertPemFile = new FileInfo($#"{CertificateFile.DirectoryName}\{oldFile}.cer");
return SaveNewCertFile(newCertPemFile, newData);
}
public FileInfo SavePrivateKey()
{
var newData = GeneratePrivateKeyPem();
var oldFile = Path.GetFileNameWithoutExtension(CertificateFile.FullName);
var newPrivateKeyPemFile = new FileInfo($#"{CertificateFile.DirectoryName}\{oldFile}.key");
return SaveNewCertFile(newPrivateKeyPemFile, newData);
}
public FileInfo SaveNewCertFile(FileInfo newFile, byte[] data)
{
File.WriteAllBytes(newFile.FullName, data);
return newFile;
}
}
With it, I'm trying to save private part:
// (...)
CertBootstrap certBootstrap = new CertBootstrap("simple.pfx");
certBootstrap.LoadBootstrap();
// (...)
certBootstrap.SavePrivateKey();
and it all ends up with exception: "The requested operation it not supported".
I found similar thread: Cannot export RSA private key parameters, the requested operation is not supported and tried to do the same (Export -> Import with password). But did not help.
Can You point me propper direction? Most probably I'm missing something, but am out of ideas for now.
Thank You in advance.

Related

Producer terminating with 1 message (39bytes) still in queue or transit. Kafka

How do I solve this terminating with kafka? I have the following error: https://i.stack.imgur.com/bY2j3.png
Code:
public class KafkaHelper
{
public static async Task<bool> SendMessage(KafkaSettings settings, string topic, string key, string val)
{
var succeed = false;
var config = new ProducerConfig
{
BootstrapServers = settings.Server,
ClientId = Dns.GetHostName(),
};
using (var adminClient = new AdminClientBuilder(config).Build())
{
try
{
await adminClient.CreateTopicsAsync(new List<TopicSpecification> {
new TopicSpecification {
Name = topic,
NumPartitions = settings.NumPartitions,
ReplicationFactor = settings.ReplicationFactor } });
}
catch (CreateTopicsException e)
{
if (e.Results[0].Error.Code != ErrorCode.TopicAlreadyExists)
{
Console.WriteLine($"An error occured creating topic {topic}: {e.Results[0].Error.Reason}");
}
else
{
Console.WriteLine("Topic already exists");
}
}
}
using (var producer = new ProducerBuilder<string, string>(config).Build())
{
producer.Produce(topic, new Message<string, string>
{
Key = key,
Value = val
}, (deliveryReport) =>
{
if (deliveryReport.Error.Code != ErrorCode.NoError)
{
Console.WriteLine($"Failed to deliver message: {deliveryReport.Error.Reason}");
}
else
{
Console.WriteLine($"Produced message to: {deliveryReport.TopicPartitionOffset}");
succeed = true;
}
});
producer.Flush(TimeSpan.FromSeconds(10));
}
return await Task.FromResult(succeed);
}
}

Send sms using Mbn Api C#

I'm looking for a way to send Sms throught MbnApi using :
http://msdn.microsoft.com/en-us/library/windows/desktop/dd323167(v=vs.85).aspx
IMbnSms interface. But it's not working at all.
I could not have a sample project to see how to do it. I'm coding on C# .Net
Thx
public class NaErrorHandling
{
public Dictionary<UInt32, string> Hresults { get;private set; }
public NaErrorHandling()
{
Hresults = new Dictionary<UInt32, string>();
Init();
}
private void Init()
{
Hresults.Add(0, "S_OK");
Hresults.Add(0x8054820a, "E_MBN_SIM_NOT_INSERTED");
Hresults.Add(0x80070057, "E_INVALIDARG");
Hresults.Add(0x80548202, "E_MBN_BAD_SIM");
Hresults.Add(0x80548210, "E_MBN_PIN_REQUIRED");
Hresults.Add(0x80548224, "E_MBN_SMS_MEMORY_FAILURE");
Hresults.Add(0x80548226, "E_MBN_SMS_UNKNOWN_SMSC_ADDRESS");
Hresults.Add(0x80548209, "E_MBN_SERVICE_NOT_ACTIVATED");
Hresults.Add(0x80548225, "E_MBN_SMS_NETWORK_TIMEOUT");
Hresults.Add(0x8054820d, "E_MBN_NOT_REGISTERED");
Hresults.Add(0x80548223, "E_MBN_SMS_LANG_NOT_SUPPORTED");
Hresults.Add(0x80548220, "E_MBN_SMS_ENCODING_NOT_SUPPORTED");
Hresults.Add(0x80548228, "E_MBN_SMS_OPERATION_NOT_ALLOWED");
Hresults.Add(0x80548229, "E_MBN_SMS_MEMORY_FULL");
Hresults.Add(0X80070015, "ERROR_NOT_READY");
Hresults.Add(1062, "ERROR_SERVICE_NOT_ACTIVE");
}
public string GetError(int error)
{
UInt32 uerror = (UInt32)error;
if (Hresults.ContainsKey(uerror))
return Hresults[uerror];
return "Error Not Know";
}
}
public class SmsResult : MbnApi.IMbnSmsEvents
{
public void OnSetSmsConfigurationComplete(MbnApi.IMbnSms sms, uint requestID, int status)
{
}
public void OnSmsConfigurationChange(MbnApi.IMbnSms sms)
{
}
public void OnSmsDeleteComplete(MbnApi.IMbnSms sms, uint requestID, int status)
{
}
public void OnSmsNewClass0Message(MbnApi.IMbnSms sms, MbnApi.MBN_SMS_FORMAT SmsFormat, object[] readMsgs)
{
}
public void OnSmsReadComplete(MbnApi.IMbnSms sms, MbnApi.MBN_SMS_FORMAT SmsFormat, object[] readMsgs, bool moreMsgs, uint requestID, int status)
{
string messageShow = String.Empty;
SMSPDULib.SMS rms= new SMSPDULib.SMS();
foreach (var msgReceived in readMsgs)
{
var msg = msgReceived as IMbnSmsReadMsgPdu;
messageShow += GetSms(msg.PduData) + "\n";
}
System.Windows.MessageBox.Show( messageShow);
}
private string GetSms(string pduSource)
{
SMSType smsType = SMSBase.GetSMSType(pduSource);
string message = string.Empty;
switch (smsType)
{
case SMSType.SMS:
SMS sms = new SMS();
SMS.Fetch(sms, ref pduSource);
message = sms.Message;
//Use instance of SMS class here
break;
case SMSType.StatusReport:
SMSStatusReport statusReport = new SMSStatusReport();
SMSStatusReport.Fetch(statusReport, ref pduSource);
//Use instance of SMSStatusReport class here
break;
}
return message;
}
public void OnSmsSendComplete(MbnApi.IMbnSms sms, uint requestID, int status)
{
NaErrorHandling handling = new NaErrorHandling();
var res = handling.GetError(status);
UInt32 uStatus = (UInt32)status;
}
public void OnSmsStatusChange(MbnApi.IMbnSms sms)
{
throw new NotImplementedException();
}
}
public void SendSms()
{
MbnConnectionManager mbnConnectionMgr = new MbnConnectionManager();
IMbnConnectionManager connMgr = (IMbnConnectionManager)mbnConnectionMgr;
try
{
IMbnConnection[] arrConn = connMgr.GetConnections();
if (arrConn != null)
{
String res = String.Empty;
foreach (var connection in arrConn)
{
res += String.Format("Connection ID : {0} | Interface Id : {1}\n", connection.ConnectionID, connection.InterfaceID);
}
//MessageBox.Show(res);
var conn = arrConn[0];
uint prId = 0;
//conn.Connect(MBN_CONNECTION_MODE.MBN_CONNECTION_MODE_PROFILE, "Bouygues Telecom", out prId);
MbnInterfaceManager mbnInterfaceMgr = new MbnInterfaceManager();
var mbnInterface = mbnInterfaceMgr as IMbnInterfaceManager;
var selectInterface = mbnInterface.GetInterface(conn.InterfaceID);
MBN_INTERFACE_CAPS caps = selectInterface.GetInterfaceCapability();
var theCap =caps.smsCaps;// (uint)MBN_SMS_CAPS.MBN_SMS_CAPS_PDU_SEND;
IConnectionPointContainer icpc;
icpc = (IConnectionPointContainer)mbnInterfaceMgr;
Guid IID_IMbnConnectionEvents = typeof(IMbnSmsEvents).GUID;
IConnectionPoint icp;
icpc.FindConnectionPoint(ref IID_IMbnConnectionEvents, out icp);
SmsResult connEvtsSink = new SmsResult();
uint cookie;
icp.Advise(connEvtsSink, out cookie);
var sms = selectInterface as IMbnSms;
string phoneDest = "";
string pdu = String.Empty;
byte[] size = new byte[5];
uint requestId = 456;
MBN_SMS_STATUS_INFO smsStatusInfo = new MBN_SMS_STATUS_INFO();
smsStatusInfo.flag = 10;
try
{
IMbnSmsConfiguration smsConfig = sms.GetSmsConfiguration();
sms.GetSmsStatus(out smsStatusInfo);
var wtf = smsStatusInfo;
string serviceDatacenter = smsConfig.ServiceCenterAddress;
CreatePduSms(null, phoneDest, "Hello", out pdu, out size);
//var res1 = SMSPDULib.SMS.GetBytes(pdu, 16);
var total = SMSPDULib.SMS.GetBytes(pdu);
byte wantedSize =(byte) total.Length;
CreatePduSms(serviceDatacenter, phoneDest, "Hello", out pdu, out size);
//var byteArray = StringToByteArray(pdu);
//var str = System.Text.Encoding.UTF7.GetString(byteArray);
sms.SmsSendPdu(pdu, wantedSize, out requestId);
//sms.SmsSendCdma(phoneDest, MBN_SMS_CDMA_ENCODING.MBN_SMS_CDMA_ENCODING_7BIT_ASCII, MBN_SMS_CDMA_LANG.MBN_SMS_CDMA_LANG_FRENCH, 2, GetBytes("Hi"), out requestId);
}
catch (Exception exp)
{
//MessageBox.Show("Cannot send Message : " + exp.Message);
}
}
}
catch (Exception e)
{
//MessageBox.Show(e.Message + e.StackTrace);
}
}
private void CreatePduSms(string servAddress, string phoneDest, string msg, out string pdu, out byte[] size)
{
SMSPDULib.SMS sms = new SMSPDULib.SMS();
sms.Direction = SMSPDULib.SMSDirection.Submited;
sms.PhoneNumber = "";
if (servAddress != null)
sms.ServiceCenterNumber = servAddress;
sms.ValidityPeriod = new TimeSpan(4, 0, 0, 0);
sms.Message = msg + DateTime.Now.ToString();
pdu = sms.Compose(SMSPDULib.SMS.SMSEncoding._7bit);
size = 0;
}

StreamWriter MVVM C# writes variable address?

im studying C# and wanted to create a simple registration and loginform in order to practice. Im trying to use MVVM pattern. As it seemed to be easier just to store login data into text file and afterwards read from it for authentification. But a problem occured StreamWriter writes sth like that : System.Collections.ObjectModel.ObservableCollection`1[LoginForm.Andmed.LoginData]
If anyone can tell whats the issues or how to fix i would be very thankful.
the view model:
class LoginVM
{
public string path = #"C:\Users\Dell\Desktop\data.txt";
private ObservableCollection<LoginData> andmed; // creating ObservableCollection of LoginData data.
public ObservableCollection<LoginData> Andmed
{
get { return andmed; }
set { andmed = value; }
}
public LoginVM()
{
this.andmed = new ObservableCollection<LoginData>();
}
public void lisaAndmed(string user, string pass)//adds data to ObservableCollection
{
this.andmed.Add(new LoginData(user, pass));
}
public void salvestaAndmed()//
{
StreamWriter SW = new StreamWriter(path, true); // using streamwriter to save data from the Collection to the path defined
SW.WriteLine(this.andmed);
SW.Close();
}
public string autendi() // method for later purpose for authentification in login form.
{
StreamReader SR = new StreamReader(path);
path = SR.ReadToEnd();
SR.Close();
return path;
}
properties :
namespace LoginForm.Andmed
{
public class LoginData
{
private string username;
private string password;
public string Username
{
get { return username; }
set { username = value; }
}
public string Password
{
get { return password; }
set { password = value; }
}
public LoginData(string _username, string _password)
{
this.password = _password;
this.username = _username;
}
}
}
Model view class:
public partial class MainWindow : Window
{
LoginVM mudel;
public MainWindow()
{
InitializeComponent();
mudel = new LoginVM();
this.DataContext = mudel;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (user.Text.Length > 0 && pass1.Password == pass2.Password)
{
success.Text = "Successfuly registered!" + user.Text;
error.Text = "";
mudel.lisaAndmed(user.Text, pass1.Password); // calling the method to add data into obsercablecooll
mudel.salvestaAndmed(); // now trying to save the data from obsservablecall
}
else if (pass1.Password != pass2.Password)
{
error.Text = "Passwords arent the same";
}
else
{
error.Text = "Username incorrect!";
}
Logimine logimine = new Logimine();
logimine.ShowDialog();
}
}
This:
SW.WriteLine(this.andmed);
writes a result of ObservableCollection<T>.ToString() method call, which is a type name by default, since ObservableCollection<T> doesn't override Object.ToString().
You have to use any serializer to save and load ObservableCollection<LoginData> contents. For example, it could be XmlSerializer:
var serializer = new XmlSerializer(typeof(ObservableCollection<LoginData>));
var collection = new ObservableCollection<LoginData>
{
new LoginData { Username = "admin", Password = "123" },
new LoginData { Username = "johndoe", Password = "456" }
};
var sb = new StringBuilder();
// serialize
using (var writer = new StringWriter(sb))
{
serializer.Serialize(writer, collection);
}
// deserialize
using (var reader = new StringReader(sb.ToString()))
{
var collectionClone = serializer.Deserialize(reader);
}

write and update key to ini file c#

i want write some setting to ini file with this code that search to find key and update it and if can't find the key add it to file . but it show this error :
"Object reference not set to an instance of an object."
i try this code :
internal class IniData
{
public string Key;
public string Value;
}
internal class IniSection : Dictionary<string, IniData>
{
public string Name { get; set; }
}
internal class IniFile : Dictionary<string, IniSection>
{
public string Path { get; set; }
}
public sealed class IniManager
{
private static readonly Dictionary<string, IniFile> IniFiles;
static IniManager()
{
IniFiles = new Dictionary<string, IniFile>();
}
public static void WriteIni(string fileName, string section, string key, string value)
{
/* Check if ini file exists in the ini collection */
var fileKey = fileName.ToLower();
if (!IniFiles.ContainsKey(fileKey))
{
if (!ImportIni(fileKey))
{
/* Add a new blank file */
var ini = new IniFile { Path = fileName };
IniFiles.Add(fileKey, ini);
}
}
/* Find section */
if (IniFiles[fileKey].ContainsKey(section.ToLower()))
{
/* Find key, if exists replace it */
if (IniFiles[fileKey][section.ToLower()].ContainsKey(key.ToLower()))
{
IniFiles[fileKey][section.ToLower()][key.ToLower()].Value = value;
return;
}
var data = new IniData { Key = key, Value = value };
IniFiles[fileKey][section.ToLower()].Add(key.ToLower(), data);
}
else
{
/* Create new ini section */
var sec = new IniSection { Name = section };
var data = new IniData { Key = key, Value = value };
sec.Add(key.ToLower(), data);
IniFiles[fileKey].Add(section.ToLower(), sec);
}
}
private static bool ImportIni(string fileName)
{
if (!File.Exists(fileName)) { return false; }
string[] data;
try
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
using (var reader = new StreamReader(stream))
{
data = reader.ReadToEnd().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
reader.Close();
}
stream.Close();
}
}
catch (Exception) { return false; }
if (data.Length == 0) { return false; }
var file = new IniFile { Path = fileName };
var section = new IniSection();
foreach (var s in data)
{
if (s.StartsWith("[") && s.EndsWith("]"))
{
/* Section header */
if (section.Count > 0)
{
/* Add current section */
file.Add(section.Name.ToLower(), section);
}
section = new IniSection { Name = s.Replace("[", null).Replace("]", null) };
continue;
}
/* Using current section, parse ini keys/values */
var iniData = ParseIni(s);
section.Add(iniData.Key.ToLower(), iniData);
}
if (section.Count > 0)
{
/* Add current section */
//##################Erorr : Object reference not set to an instance of an object.
file.Add(section.Name.ToLower(), section);
}
IniFiles.Add(fileName, file);
return true;
}
private static IniData ParseIni(string s)
{
var parts = s.Split('=');
return new IniData { Key = parts[0].Trim(), Value = parts.Length > 1 ? parts[1].Trim() : string.Empty };
}
}
private void button9_Click(object sender, EventArgs e)
{
IniManager.WriteIni("seting.ini", "Sec", "key", "value");
}
Instead of implementing this yourself you should just use the API functions that Windows provide. Of course, if you need to run this on Mono or other platforms than Windows, you need to go back to a pure .NET implementation, but even so I would probably go look for an existing implementation instead of creating that wheel yourself.
Anywhere, here's the API functions:
GetPrivateProfileString
WritePrivateProfileString
Here's an example LINQPad program that uses them:
(hit F4 and paste the following two lines into the additional namespace tab):
System.Runtime.InteropServices
System.ComponentModel
Then try this program:
void Main()
{
var ini = new IniFile(#"d:\temp\test.ini");
ini.WriteValue("Section", "Key", "Value");
ini.ReadValue("Section", "Key").Dump();
ini["Main", "Key2"] = "Test";
ini["Main", "Key2"].Dump();
}
[DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName,string lpDefault, StringBuilder lpReturnedString, uint nSize,string lpFileName);
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);
public class IniFile
{
const int MAX_SIZE = 1024;
private readonly string _FilePath;
public IniFile(string filePath)
{
if (filePath == null)
throw new ArgumentNullException("filePath");
_FilePath = filePath;
}
public string this[string section, string key]
{
get
{
return ReadValue(section, key);
}
set
{
WriteValue(section, key, value);
}
}
public string ReadValue(string section, string key, string defaultValue = null)
{
var result = new StringBuilder(MAX_SIZE);
if (GetPrivateProfileString(section, key, defaultValue ?? string.Empty, result, (uint)result.Capacity, _FilePath) > 0)
return result.ToString();
throw new Win32Exception();
}
public void WriteValue(string section, string key, string value)
{
if (!WritePrivateProfileString(section, key, value, _FilePath))
throw new Win32Exception();
}
}
The problem here is that if the file starts with a key and not with a section, the foreach doesn't match the if (s.StartsWith("[") && s.EndsWith("]")) at all and so the Section.Name is never set, thus it is null when called in file.Add(section.Name.ToLower(), section);
BTW: your code seems quite buggy, try to redesign it at least in the main foreach of ImportIni

Bouncy Castle Encryption

I have a requirment to send PGP Encrypted CSV Files to SFTP and i know nothing aboutr PGP. After a lot of research I could find following code on internet using 'Bouncy Castle' Library. The code seems gogod but does not work for me given my inexperience in PGP. Please help me in finding right values for:
publicKeyFileName
privateKeyFileName
pasPhrase
Below is my code:
namespace PgpEncryption
{
class Program
{
public static void Main()
{
EncryptAndSign();
}
private static void EncryptAndSign()
{
string publicKeyFileName = "";
string privateKeyFileName = "";
string pasPhrase = "";
PgpEncryptionKeys encryptionKeys
= new PgpEncryptionKeys(publicKeyFileName, privateKeyFileName, pasPhrase);
PgpEncrypt encrypter = new PgpEncrypt(encryptionKeys);
string encryptedFileName = "";
using (Stream outputStream = File.Create(encryptedFileName))
{
string fileToEncrypt = "";
encrypter.EncryptAndSign(outputStream, new FileInfo(fileToEncrypt));
}
}
}
}
public class PgpEncryptionKeys
{
public PgpEncryptionKeys(string publicKeyPath, string privateKeyPath, string passPhrase)
{
if (!File.Exists(publicKeyPath))
throw new ArgumentException("Public key file not found", "publicKeyPath");
if (!File.Exists(privateKeyPath))
throw new ArgumentException("Private key file not found", "privateKeyPath");
if (String.IsNullOrEmpty(passPhrase))
throw new ArgumentException("passPhrase is null or empty.", "passPhrase");
PublicKey = ReadPublicKey(publicKeyPath);
SecretKey = ReadSecretKey(privateKeyPath);
PrivateKey = ReadPrivateKey(passPhrase);
}
#region Secret Key
private PgpSecretKey ReadSecretKey(string privateKeyPath)
{
using (Stream keyIn = File.OpenRead(privateKeyPath))
using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
{
PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(secretKeyRingBundle);
if (foundKey != null)
return foundKey;
}
throw new ArgumentException("Can't find signing key in key ring.");
}
private PgpSecretKey GetFirstSecretKey(PgpSecretKeyRingBundle secretKeyRingBundle)
{
foreach (PgpSecretKeyRing kRing in secretKeyRingBundle.GetKeyRings())
{
PgpSecretKey key = (PgpSecretKey)kRing.GetSecretKeys();
if (key != null)
return key;
}
return null;
}
#endregion
#region Public Key
private PgpPublicKey ReadPublicKey(string publicKeyPath)
{
using (Stream keyIn = File.OpenRead(publicKeyPath))
using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
{
PgpPublicKeyRingBundle publicKeyRingBundle = new PgpPublicKeyRingBundle(inputStream);
PgpPublicKey foundKey = GetFirstPublicKey(publicKeyRingBundle);
if (foundKey != null)
return foundKey;
}
throw new ArgumentException("No encryption key found in public key ring.");
}
private PgpPublicKey GetFirstPublicKey(PgpPublicKeyRingBundle publicKeyRingBundle)
{
foreach (PgpPublicKeyRing kRing in publicKeyRingBundle.GetKeyRings())
{
PgpPublicKey key = (PgpPublicKey)kRing.GetPublicKeys();
//PgpPublicKey key = kRing.GetPublicKeys()
//.Cast<PgpPublicKey>()
// .Where(k => k.IsEncryptionKey)
// .FirstOrDefault();
if (key != null)
return key;
}
return null;
}
#endregion
#region Private Key
private PgpPrivateKey ReadPrivateKey(string passPhrase)
{
PgpPrivateKey privateKey = SecretKey.ExtractPrivateKey(passPhrase.ToCharArray());
if (privateKey != null)
return privateKey;
throw new ArgumentException("No private key found in secret key.");
}
#endregion
}
public class PgpEncrypt
{
private PgpEncryptionKeys m_encryptionKeys;
private const int BufferSize = 0x10000; // should always be power of 2
/// <summary>
/// Instantiate a new PgpEncrypt class with initialized PgpEncryptionKeys.
/// </summary>
/// <param name="encryptionKeys"></param>
/// <exception cref="ArgumentNullException">encryptionKeys is null</exception>
public PgpEncrypt(PgpEncryptionKeys encryptionKeys)
{
if (encryptionKeys == null)
throw new ArgumentNullException("encryptionKeys", "encryptionKeys is null.");
m_encryptionKeys = encryptionKeys;
}
/// <summary>
/// Encrypt and sign the file pointed to by unencryptedFileInfo and
/// write the encrypted content to outputStream.
/// </summary>
/// <param name="outputStream">The stream that will contain the
/// encrypted data when this method returns.</param>
/// <param name="fileName">FileInfo of the file to encrypt</param>
public void EncryptAndSign(Stream outputStream, FileInfo unencryptedFileInfo)
{
if (outputStream == null)
throw new ArgumentNullException("outputStream", "outputStream is null.");
if (unencryptedFileInfo == null)
throw new ArgumentNullException("unencryptedFileInfo", "unencryptedFileInfo is null.");
if (!File.Exists(unencryptedFileInfo.FullName))
throw new ArgumentException("File to encrypt not found.");
using (Stream encryptedOut = ChainEncryptedOut(outputStream))
using (Stream compressedOut = ChainCompressedOut(encryptedOut))
{
PgpSignatureGenerator signatureGenerator = InitSignatureGenerator compressedOut);
using (Stream literalOut = ChainLiteralOut(compressedOut, unencryptedFileInfo))
using (FileStream inputFile = unencryptedFileInfo.OpenRead())
{
WriteOutputAndSign(compressedOut, literalOut, inputFile, signatureGenerator);
}
}
}
private static void WriteOutputAndSign(Stream compressedOut,Stream literalOut,FileStream inputFile,PgpSignatureGenerator signatureGenerator)
{
int length = 0;
byte[] buf = new byte[BufferSize];
while ((length = inputFile.Read(buf, 0, buf.Length)) > 0)
{
literalOut.Write(buf, 0, length);
signatureGenerator.Update(buf, 0, length);
}
signatureGenerator.Generate().Encode(compressedOut);
}
private Stream ChainEncryptedOut(Stream outputStream)
{
PgpEncryptedDataGenerator encryptedDataGenerator;
encryptedDataGenerator =
new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.TripleDes,
new SecureRandom());
encryptedDataGenerator.AddMethod(m_encryptionKeys.PublicKey);
return encryptedDataGenerator.Open(outputStream, new byte[BufferSize]);
}
private static Stream ChainCompressedOut(Stream encryptedOut)
{
PgpCompressedDataGenerator compressedDataGenerator =
new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
return compressedDataGenerator.Open(encryptedOut);
}
private static Stream ChainLiteralOut(Stream compressedOut, FileInfo file)
{
PgpLiteralDataGenerator pgpLiteralDataGenerator = new PgpLiteralDataGenerator();
return pgpLiteralDataGenerator.Open(compressedOut, PgpLiteralData.Binary, file);
}
private PgpSignatureGenerator InitSignatureGenerator(Stream compressedOut)
{
const bool IsCritical = false;
const bool IsNested = false;
PublicKeyAlgorithmTag tag = m_encryptionKeys.SecretKey.PublicKey.Algorithm;
PgpSignatureGenerator pgpSignatureGenerator =
new PgpSignatureGenerator(tag, HashAlgorithmTag.Sha1);
pgpSignatureGenerator.InitSign(PgpSignature.BinaryDocument, m_encryptionKeys.PrivateKey);
foreach (string userId in m_encryptionKeys.SecretKey.PublicKey.GetUserIds())
{
PgpSignatureSubpacketGenerator subPacketGenerator =
new PgpSignatureSubpacketGenerator();
subPacketGenerator.SetSignerUserId(IsCritical, userId);
pgpSignatureGenerator.SetHashedSubpackets(subPacketGenerator.Generate());
// Just the first one!
break;
}
pgpSignatureGenerator.GenerateOnePassVersion(IsNested).Encode(compressedOut);
return pgpSignatureGenerator;
}
}
You should obtain public key of the recipient of the message, and generate your own secret key (if you need to sign files). Also PGP allows password-based encryption, if this suits your needs.
Also I would recommend to take a look on commercial libraries (like SecureBlackbox) as well. They are costy, but includes much better support, demos, documentation, etc.
i think you miss some of the code?
public class PgpEncryptionKeys {
public PgpPublicKey PublicKey { get; private set; }
public PgpPrivateKey PrivateKey { get; private set; }
public PgpSecretKey SecretKey { get; private set; }

Categories

Resources