Avatar billede Droa Seniormester
28. marts 2018 - 23:40 Der er 4 kommentarer og
1 løsning

RSA og public private keys

Hej eksperter.

Jeg har prøvet og forstå hvordan RSA i C# Core fungere, siden den er meget anderledes end i .Net Framework

Jeg har f.eks været nødsaget til og bruge RSAParameters til og importere og exportere mine keypairs, desværre er den lidt svær og serializere da den prøver og holde den private nøgle hemmelig, som er lidt træls, hvis man f.eks prøver og gemme den private nøgle til en fil.

efter hvad jeg kan forstå er en private nøgle {e,n} mens den offentlige nøgle er {d,n}.

e er Exponent i RSAParameters
n er Modulus i RsAParameters
d er D i RSAParameters

men hvis jeg kun importere og exportere disse componenter, brokker den sig med exeption..

jeg under mig bare om jeg gøre dette korrekt ved og parse aller parameters, eller om man kan gøre de anderledes?


using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace RsaEncrypt
{
    class Program
    {
        static void Main(string[] args)
        {
            MakeKeyIfNeeded();

            bool finish = false;

            do
            {
                Console.Write("(R)ead / (W)rite / (Q)uit?:");
                var keyInfo = Console.ReadKey();
                Console.WriteLine();

                if(keyInfo.Key == ConsoleKey.R)
                {
                    ReadAction();
                }
                else if(keyInfo.Key == ConsoleKey.W)
                {
                    WriteAction();
                }
                else if(keyInfo.Key == ConsoleKey.Q)
                {
                    finish = true;
                }


            } while (!finish);

            Console.WriteLine("Press Any Key to Exit");
            Console.ReadKey();
        }

        private static void MakeKeyIfNeeded()
        {
            if (!System.IO.File.Exists("secret.json"))
            {
                Console.WriteLine("Key Not Found... Creating One");
                KeyHandler kh = new KeyHandler();
                kh.Save();
            }
        }

        static void WriteAction()
        {
            KeyHandler kh = new KeyHandler();
            kh.Open();
            Console.Write("Write message to Encrypt:");
            string text = Console.ReadLine();
            kh.SaveData(kh.Encrypt(text));
        }

        static void ReadAction()
        {
            KeyHandler kh = new KeyHandler();
            kh.Open();
            string text = kh.Decrypt(kh.OpenData());
            Console.WriteLine("Encrypted Message is: "+text);
        }
    }

    class KeyHandler
    {
        RSA rsa;
        RSAEncryptionPadding encryptionPadding;
       
        public KeyHandler()
        {
            rsa = RSA.Create();
            rsa.KeySize = 2048;
            encryptionPadding = RSAEncryptionPadding.OaepSHA1;
        }

        public void Save()
        {
            var keyPair= rsa.ExportParameters(true);

            Dictionary<string, byte[]> keyData = new Dictionary<string, byte[]>();
            keyData.Add("D", keyPair.D);
            keyData.Add("DP", keyPair.DP);
            keyData.Add("DQ", keyPair.DQ);
            keyData.Add("E", keyPair.Exponent);
            keyData.Add("InverseQ", keyPair.InverseQ);
            keyData.Add("N", keyPair.Modulus);
            keyData.Add("P", keyPair.P);
            keyData.Add("Q", keyPair.Q);
            string json = JsonConvert.SerializeObject(keyData);
            System.IO.File.WriteAllText("secret.json",json);
        }

        public void SaveData(string data)
        {
            System.IO.File.WriteAllText("data.txt", data);
        }

        public string OpenData()
        {
            return System.IO.File.ReadAllText("data.txt");
        }

        public void Open()
        {
            string json = System.IO.File.ReadAllText("secret.json");
            var keyData = JsonConvert.DeserializeObject<Dictionary<string, byte[]>>(json);

            RSAParameters keyPair = new RSAParameters { D = keyData["D"], DP=keyData["DP"],DQ=keyData["DQ"],Exponent = keyData["E"],InverseQ=keyData["InverseQ"], Modulus = keyData["N"],P=keyData["P"],Q=keyData["Q"] };

            rsa.ImportParameters(keyPair);
        }

        public string Encrypt(string m)
        {
            byte[] inData = System.Text.Encoding.UTF8.GetBytes(m);
            byte[] outData = rsa.Encrypt(inData,encryptionPadding);
            return BA2HS(outData);
        }

        public string Decrypt(string hs)
        {
            byte[] inData = HS2BA(hs);
            byte[] outData = rsa.Decrypt(inData, encryptionPadding);
            return System.Text.Encoding.UTF8.GetString(outData);
        }


        private string BA2HS(byte[] array)
        {
            return String.Join("", array.Select(b => b.ToString("X2")));
        }

        private byte[] HS2BA(string hexstring)
        {
            return Enumerable.Range(0, hexstring.Length)
                                .Where(x => x % 2 == 0)
                                .Select(x => Convert.ToByte(hexstring.Substring(x, 2), 16))
                                .ToArray();
        }
    }
}
Avatar billede arne_v Ekspert
29. marts 2018 - 02:47 #1
Hvad med rsa.ToXmlString(false), rsa.ToXmlString(true) og rsa.FromXmlString(xmlstr) ?
Avatar billede Droa Seniormester
29. marts 2018 - 08:16 #2
Det var os min første tanke, desværre er .ToXmlString() ikke supported i Core 2.0, og giver "PlatformNotSupportedException" hvis man bruger den, de siger det er fordi det er dependency requirement problemer.

Xml skal bruge Networking.
Networking skal bruge Cryptography
Cryptography skal bruge XML

det har åbenbart skabt problemer med et loop, så de har ungået og fixe det, ved simplethent og ungå og lave methoden færdig :)
Avatar billede Droa Seniormester
29. marts 2018 - 08:17 #3
Avatar billede arne_v Ekspert
29. marts 2018 - 14:59 #4
Hmmm.

Men hvad med at snyde ved at kigge i facit listen.

Hvis ToXmlString og FromXmlString virker på .NET 4.7.1, saa kan du kigge der hvilke felter de outputtes.

Og så putter du praecist de samme felter i din JSON.
Avatar billede Droa Seniormester
30. marts 2018 - 06:46 #5
jeg endte med og snyde, ved og bruge ILSpy til og kigge i koden til methoden.

Såden ser koden ud i ILSpy, t

public override string ToXmlString(bool includePrivateParameters)
{
    RSAParameters rSAParameters = ExportParameters(includePrivateParameters);
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.Append("<RSAKeyValue>");
    stringBuilder.Append("<Modulus>" + Convert.ToBase64String(rSAParameters.Modulus) + "</Modulus>");
    stringBuilder.Append("<Exponent>" + Convert.ToBase64String(rSAParameters.Exponent) + "</Exponent>");
    if (includePrivateParameters)
    {
        stringBuilder.Append("<P>" + Convert.ToBase64String(rSAParameters.P) + "</P>");
        stringBuilder.Append("<Q>" + Convert.ToBase64String(rSAParameters.Q) + "</Q>");
        stringBuilder.Append("<DP>" + Convert.ToBase64String(rSAParameters.DP) + "</DP>");
        stringBuilder.Append("<DQ>" + Convert.ToBase64String(rSAParameters.DQ) + "</DQ>");
        stringBuilder.Append("<InverseQ>" + Convert.ToBase64String(rSAParameters.InverseQ) + "</InverseQ>");
        stringBuilder.Append("<D>" + Convert.ToBase64String(rSAParameters.D) + "</D>");
    }
    stringBuilder.Append("</RSAKeyValue>");
    return stringBuilder.ToString();
}



public override void FromXmlString(string xmlString)
{
    if (xmlString == null)
    {
        throw new ArgumentNullException("xmlString");
    }
    RSAParameters parameters = default(RSAParameters);
    Parser parser = new Parser(xmlString);
    SecurityElement topElement = parser.GetTopElement();
    string text = topElement.SearchForTextOfLocalName("Modulus");
    if (text == null)
    {
        throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString", "RSA", "Modulus"));
    }
    parameters.Modulus = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text));
    string text2 = topElement.SearchForTextOfLocalName("Exponent");
    if (text2 == null)
    {
        throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString", "RSA", "Exponent"));
    }
    parameters.Exponent = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text2));
    string text3 = topElement.SearchForTextOfLocalName("P");
    if (text3 != null)
    {
        parameters.P = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text3));
    }
    string text4 = topElement.SearchForTextOfLocalName("Q");
    if (text4 != null)
    {
        parameters.Q = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text4));
    }
    string text5 = topElement.SearchForTextOfLocalName("DP");
    if (text5 != null)
    {
        parameters.DP = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text5));
    }
    string text6 = topElement.SearchForTextOfLocalName("DQ");
    if (text6 != null)
    {
        parameters.DQ = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text6));
    }
    string text7 = topElement.SearchForTextOfLocalName("InverseQ");
    if (text7 != null)
    {
        parameters.InverseQ = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text7));
    }
    string text8 = topElement.SearchForTextOfLocalName("D");
    if (text8 != null)
    {
        parameters.D = Convert.FromBase64String(Utils.DiscardWhiteSpaces(text8));
    }
    ImportParameters(parameters);
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester