Avatar billede heinzdmx Nybegynder
15. september 2010 - 09:02 Der er 12 kommentarer og
1 løsning

Gemme og læse krypteret password

Problemet er som følgende:
Jeg har et program der skal have brugernavn/kodeord gemt i en fil, så det kan blive loadet hver gang programmet starter. Det er ikke selve programmet der skal bruge koden, men i stedet for skal det bruges til et andet program jeg ikke kontrollere. Derfor kan jeg ikke bruge hash.

Jeg har søgt lidt efter en forholsvis sikker metode til at kryptere og dekryptere en string.

Indtil videre har jeg fundet frem til at DPAPI (DataProtection API) fra Microsoft hvor det hele er krypteret så kun den nuværende bruger kan dekryptere det vil være en god metode.

Jeg kan sagtens kryptere/dekryptere i runtime. MEN når jeg vil gemme det i en fil, så kan jeg ikke få det til at spille.

Indtil videre har jeg forsøgt med en XmlTextWriter for at gemme det i XML, men det giver "forkert parameter" fejl når jeg prøver at læse dataene fra xml-filen, under password er der følgende tekst (uddrag):
���?????z�?O??

Jeg har overvejet at lave et object der indeholder brugernavn og password, og så serializere det. Men hvordan vil i anbefale jeg gør det?

Hvis i i stedet vil anbefale mig en anden måde at gøre det på vil det også være okay.

Ps. Bruger pt. Framework 3.5, men hvis det er en nem løsning til Framework 4.0 så gør det ikke noget
Avatar billede bennytordrup Nybegynder
15. september 2010 - 09:17 #1
Skal du serializere den krypterede værdi, så sørg for at skrive den i Base64. Det garanterer "læsbare" tegn og ikke volapyk. Understøttes af Framework 2 i hvert fald.
Avatar billede aaberg Nybegynder
15. september 2010 - 09:21 #2
Grunden til at du får fejl når du putter det krypterede password ned i en xml fil, er at der er en masse reserverede tegn i den krypterede streng.

Du kan eventuelt konvertere det til base64 før du putter det i xml filen.

string cryptetPassword = getMyCryptetPassword();
byte[] data = Encoding.UTF8.GetBytes(cryptetPassword);
string base64Representation = Convert.ToBase64String(data);

//put base64Representation strengen i din xml fil.

//Sådan konvertere du tilbage:
data = Convert.FromBase64String(base64Representation);
cryptetPassword = Encoding.UTF8.GetString(data);

Nu håber jeg at jeg forstod spørgsmålet rigtigt.
Avatar billede aaberg Nybegynder
15. september 2010 - 09:22 #3
ups. Der var jeg for langsom :)
Avatar billede bvli Praktikant
15. september 2010 - 09:58 #4
Jeg har selv lige haft samme opgave og lavede nedenstående. Den bruger protectedConfigurationProvideren og returnerer altså kun xml-gyldige tegn.

using System.Configuration;
using System.Xml;
using System.Xml.Linq;

namespace B.Testing {
    static class StringEncryptionExtensions {

        public static string Encrypt(this string argument) {
            if (string.IsNullOrEmpty(argument) throw new ArgumentException("argument is null or empty.", "argument");
            DpapiProtectedConfigurationProvider cp = new DpapiProtectedConfigurationProvider();
            XmlElement n = new XmlDocument().CreateElement("temp");
            n.InnerText = argument;
            return cp.Encrypt(n).FirstChild.FirstChild.InnerText;
        }

        public static string Decrypt(this string argument) {
            if (string.IsNullOrEmpty(argument) throw new ArgumentException("argument is null or empty.", "argument");
            DpapiProtectedConfigurationProvider cp = new DpapiProtectedConfigurationProvider();
            XElement e = new XElement("EncryptedData", new XElement("CipherData", new XElement("CipherValue", argument)));
            using (XmlReader xr = e.CreateReader()) {
                XmlDocument d = new XmlDocument();
                d.Load(xr);
                return cp.Decrypt(d.FirstChild).InnerText;
            }
        }
    }
}
Avatar billede heinzdmx Nybegynder
15. september 2010 - 10:08 #5
Burde lige have nævnt at jeg har prøvet at lave noget Base64 encoding/dekoding..

Men at det muligvis er mig der ikke kan få det gjort ordentligt det kan godt passe.

Selve DPAPI

Har funktioner:

byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)

byte[] UnProtect(byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope)

Jeg kigger på aabergs forslag lidt senere når jeg får tid
Avatar billede heinzdmx Nybegynder
16. september 2010 - 13:21 #6
Jeg har nu fået det til at virke. Jeg brugte aabergs som udgangspunkt, så jeg vil gerne give point til aaberg. Læg venligst et svar.

Hele klassen der kan bruges til DPAPI kan ses her:

using System;
using System.Security.Cryptography;
using System.Text;
using AutoLoginSDE;

namespace Crypto
{
    // bruger Microsoft encryption metode, kun den samme bruger som krypterede kan dekryptere
    // Hvis det skal gælde for en bestemt maskine så brug i stedet DataProtectionScope.LocalMachine
    public class DataProtection
    {
        public static string EncryptPasswordToBase64(string text, byte[] s_aditionalEntropy)
        {
            byte[] cipherData = Protect(Encoding.UTF8.GetBytes(text), s_aditionalEntropy);
            if (cipherData == null)
                return "";

            return Convert.ToBase64String(cipherData);
        }

        public static string DecryptBase64Password(string cipherText, byte[] s_aditionalEntropy)
        {
            byte[] cipherData = Convert.FromBase64String(cipherText);
            byte[] decryptedData = Unprotect(cipherData, s_aditionalEntropy);
            if (decryptedData == null)
                return "";

            return Encoding.UTF8.GetString(decryptedData);
        }

        public static byte[] Protect(byte[] data, byte[] s_aditionalEntropy)
        {
            try
            {
                return ProtectedData.Protect(data, s_aditionalEntropy, DataProtectionScope.CurrentUser);
            }
            catch (CryptographicException e)
            {
                // håndter fejlen
            }

            return null;
        }

        public static byte[] Unprotect(byte[] data, byte[] s_aditionalEntropy)
        {
            try
            {
                return ProtectedData.Unprotect(data, s_aditionalEntropy, DataProtectionScope.CurrentUser);
            }
            catch (CryptographicException e)
            {
                // håndter fejlen
            }
            return null;
        }
    }
}
Avatar billede aaberg Nybegynder
16. september 2010 - 18:32 #7
Svar :)
Avatar billede arne_v Ekspert
27. september 2010 - 03:54 #8
Spørgsmål: hvad forhindrer en person med adgang til maskinen i at køre noget kode som unprotecter på samme måde som det valide program?
Avatar billede heinzdmx Nybegynder
27. september 2010 - 07:57 #9
I princippet ingenting tror jeg, bortset fra et ekstra byte array jeg sender me fra selve programmet. selvfølgelig kan en med forstand på reflector slippe forbi det, men jeg har vurderet at ud fra hvor mange der skal bruge programmet, så er den her sikkerhed bedre end ingenting.

Hvis du har et andet og bedre forslag så vil jeg da gerne kigge på det.
Avatar billede bvli Praktikant
27. september 2010 - 10:00 #10
Løsningen bruger dpapi. Og du skal altså enten have adgang til maskinen eller bedre - brugeren som skal anvende data for at kunne dekryptere.

dpapi bruger en kontospecifik key til det. Det smarte ved den brugerspecifikke løsning er, at selvom nogen får tiltusket sig rollen som administrator vil det ikke nytte bare at resette kendeordet, da det også vil slette den nøgle (hash'en af dine credentials) data i dpapi er krypteret med. Så en hacker med onde hensigter skal altså have adgang til den specifikke konto. Normalt vil man sætte flere restriktioner på denne og normalt vil det være en lokal konto.

Se i øvrigt: http://msdn.microsoft.com/en-us/library/ms995355.aspx
Avatar billede arne_v Ekspert
28. september 2010 - 02:45 #11
Der er formentligt ikke bedre løsninger i det givne setup.

Jeg ville bare påpege at hvis målsætningen er at beskytte mod at brugeren selv kan finde det gemte password, så har metoden langtfra 100% sikker.
Avatar billede heinzdmx Nybegynder
28. september 2010 - 08:05 #12
God pointe du har, men i dette tilfælde er behovet mere at sørge for selvom en kopiere filen hvor kodeord gemmes i, kan personen ikke bruge den til. Og at det heller ikke skal være nemt for en person der lige låner computeren at få kodeordet ud af programmet.
Avatar billede arne_v Ekspert
29. september 2010 - 02:01 #13
Hvis det er setuppet og det er et krav at bruger ikke skal indtaste et password, så er det nok den bedste løsning.
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
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

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