diff --git a/src/BirdsiteLive.Cryptography/ASN1.cs b/src/BirdsiteLive.Cryptography/ASN1.cs
new file mode 100644
index 0000000..cd31579
--- /dev/null
+++ b/src/BirdsiteLive.Cryptography/ASN1.cs
@@ -0,0 +1,49 @@
+using System.Linq;
+using System.Security.Cryptography;
+using Asn1;
+using Asn1Sequence = Asn1.Asn1Sequence;
+using Asn1Null = Asn1.Asn1Null;
+
+namespace BirdsiteLive.Cryptography
+{
+ public class ASN1
+ {
+ public static RSA ToRSA(byte[] data)
+ {
+ var node = Asn1Node.ReadNode(data);
+
+ var rsaSequence = Asn1Node.ReadNode((node.Nodes[1] as Asn1BitString).Data);
+
+ var modulus = (rsaSequence.Nodes[0] as Asn1Integer).Value;
+ var exponent = (rsaSequence.Nodes[1] as Asn1Integer).Value;
+ var prms = new RSAParameters { Modulus = modulus, Exponent = exponent };
+ var rsa = RSA.Create();
+ rsa.ImportParameters(prms);
+ return rsa;
+ }
+
+ public static byte[] FromRSA(RSA rsa)
+ {
+ var prms = rsa.ExportParameters(false);
+
+ var modulus = new Asn1Integer((new byte[] { 0x00 }.Concat(prms.Modulus)).ToArray());
+ var exponent = new Asn1Integer(prms.Exponent);
+
+ var oidheader = new Asn1Sequence();
+ oidheader.Nodes.Add(new Asn1ObjectIdentifier("1.2.840.113549.1.1.1"));
+ oidheader.Nodes.Add(new Asn1Null());
+
+ var rsaSequence = new Asn1Sequence();
+ rsaSequence.Nodes.Add(modulus);
+ rsaSequence.Nodes.Add(exponent);
+
+ var bitString = new Asn1BitString(rsaSequence.GetBytes());
+
+ var result = new Asn1Sequence();
+ result.Nodes.Add(oidheader);
+ result.Nodes.Add(bitString);
+
+ return result.GetBytes();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj b/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj
index 9f5c4f4..f0d9f4f 100644
--- a/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj
+++ b/src/BirdsiteLive.Cryptography/BirdsiteLive.Cryptography.csproj
@@ -4,4 +4,10 @@
netstandard2.0
+
+
+
+
+
+
diff --git a/src/BirdsiteLive.Cryptography/MagicKey.cs b/src/BirdsiteLive.Cryptography/MagicKey.cs
new file mode 100644
index 0000000..24f7af2
--- /dev/null
+++ b/src/BirdsiteLive.Cryptography/MagicKey.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace BirdsiteLive.Cryptography
+{
+ public class MagicKey
+ {
+ //public class WebfingerLink
+ //{
+ // public string rel { get; set; }
+ // public string type { get; set; }
+ // public string href { get; set; }
+ // public string template { get; set; }
+ //}
+
+ //public class WebfingerResult
+ //{
+ // public string subject { get; set; }
+ // public List aliases { get; set; }
+ // public List links { get; set; }
+ //}
+
+ private string[] _parts;
+ private RSA _rsa;
+
+ private static byte[] _decodeBase64Url(string data)
+ {
+ return Convert.FromBase64String(data.Replace('-', '+').Replace('_', '/'));
+ }
+
+ private static string _encodeBase64Url(byte[] data)
+ {
+ return Convert.ToBase64String(data).Replace('+', '-').Replace('/', '_');
+ }
+
+ private class RSAKeyParms
+ {
+ public byte[] D;
+ public byte[] DP;
+ public byte[] DQ;
+ public byte[] Exponent;
+ public byte[] InverseQ;
+ public byte[] Modulus;
+ public byte[] P;
+ public byte[] Q;
+
+ public static RSAKeyParms From(RSAParameters parms)
+ {
+ var a = new RSAKeyParms();
+ a.D = parms.D;
+ a.DP = parms.DP;
+ a.DQ = parms.DQ;
+ a.Exponent = parms.Exponent;
+ a.InverseQ = parms.InverseQ;
+ a.Modulus = parms.Modulus;
+ a.P = parms.P;
+ a.Q = parms.Q;
+ return a;
+ }
+
+ public RSAParameters Make()
+ {
+ var a = new RSAParameters();
+ a.D = D;
+ a.DP = DP;
+ a.DQ = DQ;
+ a.Exponent = Exponent;
+ a.InverseQ = InverseQ;
+ a.Modulus = Modulus;
+ a.P = P;
+ a.Q = Q;
+ return a;
+ }
+ }
+
+ public MagicKey(string key)
+ {
+ if (key[0] == '{')
+ {
+ _rsa = RSA.Create();
+ _rsa.ImportParameters(JsonConvert.DeserializeObject(key).Make());
+ }
+ else
+ {
+ _parts = key.Split('.');
+ if (_parts[0] != "RSA") throw new Exception("Unknown magic key!");
+
+ var rsaParams = new RSAParameters();
+ rsaParams.Modulus = _decodeBase64Url(_parts[1]);
+ rsaParams.Exponent = _decodeBase64Url(_parts[2]);
+
+ _rsa = RSA.Create();
+ _rsa.ImportParameters(rsaParams);
+ }
+ }
+
+ public static MagicKey Generate()
+ {
+ var rsa = RSA.Create();
+ rsa.KeySize = 2048;
+
+ return new MagicKey(JsonConvert.SerializeObject(RSAKeyParms.From(rsa.ExportParameters(true))));
+ }
+
+ //public static async Task KeyForAuthor(ASObject obj)
+ //{
+ // var authorId = (string)obj["email"].FirstOrDefault()?.Primitive;
+ // if (authorId == null)
+ // {
+ // authorId = obj["name"].FirstOrDefault()?.Primitive + "@" + new Uri(obj.Id).Host;
+ // }
+
+ // var domain = authorId.Split('@')[1];
+ // var hc = new HttpClient();
+ // var wf = JsonConvert.DeserializeObject(await hc.GetStringAsync($"https://{domain}/.well-known/webfinger?resource=acct:{Uri.EscapeDataString(authorId)}"));
+ // var link = wf.links.FirstOrDefault(a => a.rel == "magic-public-key");
+ // if (link == null) return null;
+
+ // if (!link.href.StartsWith("data:")) return null; // does this happen?
+
+ // return new MagicKey(link.href.Split(new char[] { ',' }, 2)[1]);
+ //}
+
+ public byte[] BuildSignedData(string data, string dataType, string encoding, string algorithm)
+ {
+ var sig = data + "." + _encodeBase64Url(Encoding.UTF8.GetBytes(dataType)) + "." + _encodeBase64Url(Encoding.UTF8.GetBytes(encoding)) + "." + _encodeBase64Url(Encoding.UTF8.GetBytes(algorithm));
+ return Encoding.UTF8.GetBytes(sig);
+ }
+
+ public bool Verify(string signature, byte[] data)
+ {
+ return _rsa.VerifyData(data, _decodeBase64Url(signature), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+ }
+
+ public byte[] Sign(byte[] data)
+ {
+ return _rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+ }
+
+ public string AsPEM
+ {
+ get
+ {
+ var data = ASN1.FromRSA(_rsa);
+ var baseData = Convert.ToBase64String(data);
+ var builder = new StringBuilder(baseData);
+ for (int i = 72; i < builder.Length; i += 73)
+ builder.Insert(i, "\n");
+
+ builder.Insert(0, "-----BEGIN PUBLIC KEY-----\n");
+ builder.Append("\n-----END PUBLIC KEY-----");
+
+ return builder.ToString();
+ }
+ }
+
+ public string PrivateKey
+ {
+ get { return JsonConvert.SerializeObject(RSAKeyParms.From(_rsa.ExportParameters(true))); }
+ }
+
+ public string PublicKey
+ {
+ get
+ {
+ var parms = _rsa.ExportParameters(false);
+
+ return string.Join(".", "RSA", _encodeBase64Url(parms.Modulus), _encodeBase64Url(parms.Exponent));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BirdsiteLive.Cryptography/RsaKeys.cs b/src/BirdsiteLive.Cryptography/RsaKeys.cs
new file mode 100644
index 0000000..0bc4a90
--- /dev/null
+++ b/src/BirdsiteLive.Cryptography/RsaKeys.cs
@@ -0,0 +1,225 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.OpenSsl;
+using Org.BouncyCastle.Security;
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace MyProject.Data.Encryption
+{
+ public class RSAKeys
+ {
+ ///
+ /// Import OpenSSH PEM private key string into MS RSACryptoServiceProvider
+ ///
+ ///
+ ///
+ public static RSACryptoServiceProvider ImportPrivateKey(string pem)
+ {
+ PemReader pr = new PemReader(new StringReader(pem));
+ AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
+ RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
+
+ RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams);
+ csp.ImportParameters(rsaParams);
+ return csp;
+ }
+
+ ///
+ /// Import OpenSSH PEM public key string into MS RSACryptoServiceProvider
+ ///
+ ///
+ ///
+ public static RSACryptoServiceProvider ImportPublicKey(string pem)
+ {
+ PemReader pr = new PemReader(new StringReader(pem));
+ AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject();
+ RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
+
+ RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams);
+ csp.ImportParameters(rsaParams);
+ return csp;
+ }
+
+ ///
+ /// Export private (including public) key from MS RSACryptoServiceProvider into OpenSSH PEM string
+ /// slightly modified from https://stackoverflow.com/a/23739932/2860309
+ ///
+ ///
+ ///
+ public static string ExportPrivateKey(RSACryptoServiceProvider csp)
+ {
+ StringWriter outputStream = new StringWriter();
+ if (csp.PublicOnly) throw new ArgumentException("CSP does not contain a private key", "csp");
+ var parameters = csp.ExportParameters(true);
+ using (var stream = new MemoryStream())
+ {
+ var writer = new BinaryWriter(stream);
+ writer.Write((byte)0x30); // SEQUENCE
+ using (var innerStream = new MemoryStream())
+ {
+ var innerWriter = new BinaryWriter(innerStream);
+ EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 }); // Version
+ EncodeIntegerBigEndian(innerWriter, parameters.Modulus);
+ EncodeIntegerBigEndian(innerWriter, parameters.Exponent);
+ EncodeIntegerBigEndian(innerWriter, parameters.D);
+ EncodeIntegerBigEndian(innerWriter, parameters.P);
+ EncodeIntegerBigEndian(innerWriter, parameters.Q);
+ EncodeIntegerBigEndian(innerWriter, parameters.DP);
+ EncodeIntegerBigEndian(innerWriter, parameters.DQ);
+ EncodeIntegerBigEndian(innerWriter, parameters.InverseQ);
+ var length = (int)innerStream.Length;
+ EncodeLength(writer, length);
+ writer.Write(innerStream.GetBuffer(), 0, length);
+ }
+
+ var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
+ // WriteLine terminates with \r\n, we want only \n
+ outputStream.Write("-----BEGIN RSA PRIVATE KEY-----\n");
+ // Output as Base64 with lines chopped at 64 characters
+ for (var i = 0; i < base64.Length; i += 64)
+ {
+ outputStream.Write(base64, i, Math.Min(64, base64.Length - i));
+ outputStream.Write("\n");
+ }
+ outputStream.Write("-----END RSA PRIVATE KEY-----");
+ }
+
+ return outputStream.ToString();
+ }
+
+ ///
+ /// Export public key from MS RSACryptoServiceProvider into OpenSSH PEM string
+ /// slightly modified from https://stackoverflow.com/a/28407693
+ ///
+ ///
+ ///
+ public static string ExportPublicKey(RSACryptoServiceProvider csp)
+ {
+ StringWriter outputStream = new StringWriter();
+ var parameters = csp.ExportParameters(false);
+ using (var stream = new MemoryStream())
+ {
+ var writer = new BinaryWriter(stream);
+ writer.Write((byte)0x30); // SEQUENCE
+ using (var innerStream = new MemoryStream())
+ {
+ var innerWriter = new BinaryWriter(innerStream);
+ innerWriter.Write((byte)0x30); // SEQUENCE
+ EncodeLength(innerWriter, 13);
+ innerWriter.Write((byte)0x06); // OBJECT IDENTIFIER
+ var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
+ EncodeLength(innerWriter, rsaEncryptionOid.Length);
+ innerWriter.Write(rsaEncryptionOid);
+ innerWriter.Write((byte)0x05); // NULL
+ EncodeLength(innerWriter, 0);
+ innerWriter.Write((byte)0x03); // BIT STRING
+ using (var bitStringStream = new MemoryStream())
+ {
+ var bitStringWriter = new BinaryWriter(bitStringStream);
+ bitStringWriter.Write((byte)0x00); // # of unused bits
+ bitStringWriter.Write((byte)0x30); // SEQUENCE
+ using (var paramsStream = new MemoryStream())
+ {
+ var paramsWriter = new BinaryWriter(paramsStream);
+ EncodeIntegerBigEndian(paramsWriter, parameters.Modulus); // Modulus
+ EncodeIntegerBigEndian(paramsWriter, parameters.Exponent); // Exponent
+ var paramsLength = (int)paramsStream.Length;
+ EncodeLength(bitStringWriter, paramsLength);
+ bitStringWriter.Write(paramsStream.GetBuffer(), 0, paramsLength);
+ }
+ var bitStringLength = (int)bitStringStream.Length;
+ EncodeLength(innerWriter, bitStringLength);
+ innerWriter.Write(bitStringStream.GetBuffer(), 0, bitStringLength);
+ }
+ var length = (int)innerStream.Length;
+ EncodeLength(writer, length);
+ writer.Write(innerStream.GetBuffer(), 0, length);
+ }
+
+ var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
+ // WriteLine terminates with \r\n, we want only \n
+ outputStream.Write("-----BEGIN PUBLIC KEY-----\n");
+ for (var i = 0; i < base64.Length; i += 64)
+ {
+ outputStream.Write(base64, i, Math.Min(64, base64.Length - i));
+ outputStream.Write("\n");
+ }
+ outputStream.Write("-----END PUBLIC KEY-----");
+ }
+
+ return outputStream.ToString();
+ }
+
+ ///
+ /// https://stackoverflow.com/a/23739932/2860309
+ ///
+ ///
+ ///
+ private static void EncodeLength(BinaryWriter stream, int length)
+ {
+ if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
+ if (length < 0x80)
+ {
+ // Short form
+ stream.Write((byte)length);
+ }
+ else
+ {
+ // Long form
+ var temp = length;
+ var bytesRequired = 0;
+ while (temp > 0)
+ {
+ temp >>= 8;
+ bytesRequired++;
+ }
+ stream.Write((byte)(bytesRequired | 0x80));
+ for (var i = bytesRequired - 1; i >= 0; i--)
+ {
+ stream.Write((byte)(length >> (8 * i) & 0xff));
+ }
+ }
+ }
+
+ ///
+ /// https://stackoverflow.com/a/23739932/2860309
+ ///
+ ///
+ ///
+ ///
+ private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
+ {
+ stream.Write((byte)0x02); // INTEGER
+ var prefixZeros = 0;
+ for (var i = 0; i < value.Length; i++)
+ {
+ if (value[i] != 0) break;
+ prefixZeros++;
+ }
+ if (value.Length - prefixZeros == 0)
+ {
+ EncodeLength(stream, 1);
+ stream.Write((byte)0);
+ }
+ else
+ {
+ if (forceUnsigned && value[prefixZeros] > 0x7f)
+ {
+ // Add a prefix zero to force unsigned if the MSB is 1
+ EncodeLength(stream, value.Length - prefixZeros + 1);
+ stream.Write((byte)0);
+ }
+ else
+ {
+ EncodeLength(stream, value.Length - prefixZeros);
+ }
+ for (var i = prefixZeros; i < value.Length; i++)
+ {
+ stream.Write(value[i]);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BirdsiteLive.sln b/src/BirdsiteLive.sln
index 0efc944..b743257 100644
--- a/src/BirdsiteLive.sln
+++ b/src/BirdsiteLive.sln
@@ -11,7 +11,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{4FEAD6
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BirdsiteLive.Twitter", "BirdsiteLive.Twitter\BirdsiteLive.Twitter.csproj", "{77C559D1-80A2-4B1C-A566-AE2D156944A4}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdsiteLive.Common", "BirdsiteLive.Common\BirdsiteLive.Common.csproj", "{E64E7501-5DB8-4620-BA35-BA59FD746ABA}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BirdsiteLive.Common", "BirdsiteLive.Common\BirdsiteLive.Common.csproj", "{E64E7501-5DB8-4620-BA35-BA59FD746ABA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{A32D3458-09D0-4E0A-BA4B-8C411B816B94}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdsiteLive.Cryptography.Tests", "Tests\BirdsiteLive.Cryptography.Tests\BirdsiteLive.Cryptography.Tests.csproj", "{155D46A4-2D05-47F2-8FFC-0B7C412A7652}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -35,6 +39,10 @@ Global
{E64E7501-5DB8-4620-BA35-BA59FD746ABA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E64E7501-5DB8-4620-BA35-BA59FD746ABA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E64E7501-5DB8-4620-BA35-BA59FD746ABA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {155D46A4-2D05-47F2-8FFC-0B7C412A7652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {155D46A4-2D05-47F2-8FFC-0B7C412A7652}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {155D46A4-2D05-47F2-8FFC-0B7C412A7652}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {155D46A4-2D05-47F2-8FFC-0B7C412A7652}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -43,6 +51,7 @@ Global
{160AD138-4E29-4706-8546-9826B529E9B2} = {4FEAD6BC-3C8E-451A-8CA1-FF1AF47D26CC}
{77C559D1-80A2-4B1C-A566-AE2D156944A4} = {4FEAD6BC-3C8E-451A-8CA1-FF1AF47D26CC}
{E64E7501-5DB8-4620-BA35-BA59FD746ABA} = {4FEAD6BC-3C8E-451A-8CA1-FF1AF47D26CC}
+ {155D46A4-2D05-47F2-8FFC-0B7C412A7652} = {A32D3458-09D0-4E0A-BA4B-8C411B816B94}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {69E8DCAD-4C37-4010-858F-5F94E6FBABCE}
diff --git a/src/Tests/BirdsiteLive.Cryptography.Tests/BirdsiteLive.Cryptography.Tests.csproj b/src/Tests/BirdsiteLive.Cryptography.Tests/BirdsiteLive.Cryptography.Tests.csproj
new file mode 100644
index 0000000..0c9c0a6
--- /dev/null
+++ b/src/Tests/BirdsiteLive.Cryptography.Tests/BirdsiteLive.Cryptography.Tests.csproj
@@ -0,0 +1,20 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Tests/BirdsiteLive.Cryptography.Tests/MagicKeyTests.cs b/src/Tests/BirdsiteLive.Cryptography.Tests/MagicKeyTests.cs
new file mode 100644
index 0000000..d77b67a
--- /dev/null
+++ b/src/Tests/BirdsiteLive.Cryptography.Tests/MagicKeyTests.cs
@@ -0,0 +1,19 @@
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace BirdsiteLive.Cryptography.Tests
+{
+ [TestClass]
+ public class MagicKeyTests
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ var g = MagicKey.Generate();
+
+ var magicKey = new MagicKey(g.PrivateKey);
+
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/BirdsiteLive.Cryptography.Tests/RsaGeneratorTests.cs b/src/Tests/BirdsiteLive.Cryptography.Tests/RsaGeneratorTests.cs
new file mode 100644
index 0000000..639c392
--- /dev/null
+++ b/src/Tests/BirdsiteLive.Cryptography.Tests/RsaGeneratorTests.cs
@@ -0,0 +1,15 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace BirdsiteLive.Cryptography.Tests
+{
+ [TestClass]
+ public class RsaGeneratorTests
+ {
+ [TestMethod]
+ public void TestMethod1()
+ {
+ var rsaGen = new RsaGenerator();
+ var rsa = rsaGen.GetRsa();
+ }
+ }
+}
diff --git a/src/Tests/BirdsiteLive.Cryptography.Tests/RsaKeysTests.cs b/src/Tests/BirdsiteLive.Cryptography.Tests/RsaKeysTests.cs
new file mode 100644
index 0000000..50c77b9
--- /dev/null
+++ b/src/Tests/BirdsiteLive.Cryptography.Tests/RsaKeysTests.cs
@@ -0,0 +1,34 @@
+using System.Security.Cryptography;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using MyProject.Data.Encryption;
+
+namespace BirdsiteLive.Cryptography.Tests
+{
+ [TestClass]
+ public class RsaKeysTests
+ {
+ [TestMethod]
+ public void TestMethod1()
+ {
+ var rsa = RSA.Create();
+
+ var cspParams = new CspParameters();
+ cspParams.ProviderType = 1; // PROV_RSA_FULL
+ cspParams.Flags = CspProviderFlags.CreateEphemeralKey;
+ var rsaProvider = new RSACryptoServiceProvider(2048, cspParams);
+
+ var rsaPublicKey = RSAKeys.ExportPublicKey(rsaProvider);
+ var rsaPrivateKey = RSAKeys.ExportPrivateKey(rsaProvider);
+
+ //rsaProvider.
+
+ var pem = RSAKeys.ImportPublicKey(rsaPrivateKey);
+ }
+
+ [TestMethod]
+ public void TestMethod2()
+ {
+
+ }
+ }
+}
\ No newline at end of file