diff --git a/src/BirdsiteLive.Cryptography/Class1.cs b/src/BirdsiteLive.Cryptography/Class1.cs deleted file mode 100644 index 5b1ef77..0000000 --- a/src/BirdsiteLive.Cryptography/Class1.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace BirdsiteLive.Cryptography -{ - public class Class1 - { - } -} diff --git a/src/BirdsiteLive.Cryptography/RsaGenerator.cs b/src/BirdsiteLive.Cryptography/RsaGenerator.cs new file mode 100644 index 0000000..1be77ce --- /dev/null +++ b/src/BirdsiteLive.Cryptography/RsaGenerator.cs @@ -0,0 +1,99 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace BirdsiteLive.Cryptography +{ + //https://gist.github.com/ststeiger/f4b29a140b1e3fd618679f89b7f3ff4a + //https://gist.github.com/valep27/4a720c25b35fff83fbf872516f847863 + //https://gist.github.com/therightstuff/aa65356e95f8d0aae888e9f61aa29414 + //https://stackoverflow.com/questions/52468125/export-rsa-public-key-in-der-format-and-decrypt-data + public class RsaGenerator + { + public string GetRsa() + { + var rsa = RSA.Create(); + + var outputStream = new StringWriter(); + var parameters = rsa.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); + 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(); + } + + 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)); + } + } + } + + } +}